From 0eea212943544d40f99b05571aa7159d78667154 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 6 Sep 2011 12:17:45 -0400 Subject: Add avcodec_decode_audio4(). Deprecate avcodec_decode_audio3(). Implement audio support in avcodec_default_get_buffer(). Implement the new audio decoder API in all audio decoders. --- libavcodec/wavpack.c | 116 +++++++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 72 deletions(-) (limited to 'libavcodec/wavpack.c') diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index ec46fb166a..e4b7ebe43b 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -115,8 +115,6 @@ typedef struct WavpackFrameContext { int float_shift; int float_max_exp; WvChannel ch[2]; - int samples_left; - int max_samples; int pos; SavedContext sc, extra_sc; } WavpackFrameContext; @@ -125,6 +123,7 @@ typedef struct WavpackFrameContext { typedef struct WavpackContext { AVCodecContext *avctx; + AVFrame frame; WavpackFrameContext *fdec[WV_MAX_FRAME_DECODERS]; int fdec_num; @@ -133,7 +132,6 @@ typedef struct WavpackContext { int mkv_mode; int block; int samples; - int samples_left; int ch_offset; } WavpackContext; @@ -485,7 +483,6 @@ static float wv_get_value_float(WavpackFrameContext *s, uint32_t *crc, int S) static void wv_reset_saved_context(WavpackFrameContext *s) { s->pos = 0; - s->samples_left = 0; s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF; } @@ -502,8 +499,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, vo float *dstfl = dst; const int channel_pad = s->avctx->channels - 2; - if(s->samples_left == s->samples) - s->one = s->zero = s->zeroes = 0; + s->one = s->zero = s->zeroes = 0; do{ L = wv_get_value(s, gb, 0, &last); if(last) break; @@ -594,13 +590,8 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, vo dst16 += channel_pad; } count++; - }while(!last && count < s->max_samples); + } while (!last && count < s->samples); - if (last) - s->samples_left = 0; - else - s->samples_left -= count; - if(!s->samples_left){ wv_reset_saved_context(s); if(crc != s->CRC){ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); @@ -610,15 +601,7 @@ static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, vo av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n"); return -1; } - }else{ - s->pos = pos; - s->sc.crc = crc; - s->sc.bits_used = get_bits_count(&s->gb); - if(s->got_extra_bits){ - s->extra_sc.crc = crc_extra_bits; - s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits); - } - } + return count * 2; } @@ -635,8 +618,7 @@ static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, void float *dstfl = dst; const int channel_stride = s->avctx->channels; - if(s->samples_left == s->samples) - s->one = s->zero = s->zeroes = 0; + s->one = s->zero = s->zeroes = 0; do{ T = wv_get_value(s, gb, 0, &last); S = 0; @@ -675,13 +657,8 @@ static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, void dst16 += channel_stride; } count++; - }while(!last && count < s->max_samples); + } while (!last && count < s->samples); - if (last) - s->samples_left = 0; - else - s->samples_left -= count; - if(!s->samples_left){ wv_reset_saved_context(s); if(crc != s->CRC){ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); @@ -691,15 +668,7 @@ static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, void av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n"); return -1; } - }else{ - s->pos = pos; - s->sc.crc = crc; - s->sc.bits_used = get_bits_count(&s->gb); - if(s->got_extra_bits){ - s->extra_sc.crc = crc_extra_bits; - s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits); - } - } + return count; } @@ -743,6 +712,9 @@ static av_cold int wavpack_decode_init(AVCodecContext *avctx) s->fdec_num = 0; + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; + return 0; } @@ -759,7 +731,7 @@ static av_cold int wavpack_decode_end(AVCodecContext *avctx) } static int wavpack_decode_block(AVCodecContext *avctx, int block_no, - void *data, int *data_size, + void *data, int *got_frame_ptr, const uint8_t *buf, int buf_size) { WavpackContext *wc = avctx->priv_data; @@ -774,7 +746,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, int bpp, chan, chmask; if (buf_size == 0){ - *data_size = 0; + *got_frame_ptr = 0; return 0; } @@ -789,18 +761,16 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, return -1; } - if(!s->samples_left){ memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr)); memset(s->ch, 0, sizeof(s->ch)); s->extra_bits = 0; s->and = s->or = s->shift = 0; s->got_extra_bits = 0; - } if(!wc->mkv_mode){ s->samples = AV_RL32(buf); buf += 4; if(!s->samples){ - *data_size = 0; + *got_frame_ptr = 0; return 0; } }else{ @@ -829,13 +799,6 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, wc->ch_offset += 1 + s->stereo; - s->max_samples = *data_size / (bpp * avctx->channels); - s->max_samples = FFMIN(s->max_samples, s->samples); - if(s->samples_left > 0){ - s->max_samples = FFMIN(s->max_samples, s->samples_left); - buf = buf_end; - } - // parse metadata blocks while(buf < buf_end){ id = *buf++; @@ -1064,7 +1027,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } if(id & WP_IDF_ODD) buf++; } - if(!s->samples_left){ + if(!got_terms){ av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n"); return -1; @@ -1101,16 +1064,6 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, s->got_extra_bits = 0; } } - s->samples_left = s->samples; - }else{ - init_get_bits(&s->gb, orig_buf + s->sc.offset, s->sc.size); - skip_bits_long(&s->gb, s->sc.bits_used); - if(s->got_extra_bits){ - init_get_bits(&s->gb_extra_bits, orig_buf + s->extra_sc.offset, - s->extra_sc.size); - skip_bits_long(&s->gb_extra_bits, s->extra_sc.bits_used); - } - } if(s->stereo_in){ if(avctx->sample_fmt == AV_SAMPLE_FMT_S16) @@ -1167,7 +1120,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } } - wc->samples_left = s->samples_left; + *got_frame_ptr = 1; return samplecount * bpp; } @@ -1181,23 +1134,40 @@ static void wavpack_decode_flush(AVCodecContext *avctx) wv_reset_saved_context(s->fdec[i]); } -static int wavpack_decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +static int wavpack_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) { WavpackContext *s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - int frame_size; + int frame_size, ret; int samplecount = 0; s->block = 0; - s->samples_left = 0; s->ch_offset = 0; + /* determine number of samples */ if(s->mkv_mode){ s->samples = AV_RL32(buf); buf += 4; + } else { + if (s->multichannel) + s->samples = AV_RL32(buf + 4); + else + s->samples = AV_RL32(buf); + } + if (s->samples <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of samples: %d\n", + s->samples); + return AVERROR(EINVAL); + } + + /* get output buffer */ + s->frame.nb_samples = s->samples; + if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; } + while(buf_size > 0){ if(!s->multichannel){ frame_size = buf_size; @@ -1216,17 +1186,19 @@ static int wavpack_decode_frame(AVCodecContext *avctx, wavpack_decode_flush(avctx); return -1; } - if((samplecount = wavpack_decode_block(avctx, s->block, data, - data_size, buf, frame_size)) < 0) { + if((samplecount = wavpack_decode_block(avctx, s->block, s->frame.data[0], + got_frame_ptr, buf, frame_size)) < 0) { wavpack_decode_flush(avctx); return -1; } s->block++; buf += frame_size; buf_size -= frame_size; } - *data_size = samplecount * avctx->channels; - return s->samples_left > 0 ? 0 : avpkt->size; + if (*got_frame_ptr) + *(AVFrame *)data = s->frame; + + return avpkt->size; } AVCodec ff_wavpack_decoder = { @@ -1238,6 +1210,6 @@ AVCodec ff_wavpack_decoder = { .close = wavpack_decode_end, .decode = wavpack_decode_frame, .flush = wavpack_decode_flush, - .capabilities = CODEC_CAP_SUBFRAMES, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("WavPack"), }; -- cgit v1.2.3