From 32ac63ee10ca5daa149344a75d736c1b98177392 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 10 May 2011 11:29:08 -0400 Subject: mdec.c: fix overread. --- libavcodec/mdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libavcodec') diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 545b919411..9b6e6b6dd9 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -125,7 +125,8 @@ static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){ a->dsp.clear_blocks(block[0]); for(i=0; i<6; i++){ - if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0) + if( mdec_decode_block_intra(a, block[ block_index[i] ], block_index[i]) < 0 || + get_bits_left(&a->gb) < 0) return -1; } return 0; -- cgit v1.2.3 From a64c58a24023b3e8c9b30bfb6908150b57117a3b Mon Sep 17 00:00:00 2001 From: Alexander Strange Date: Tue, 10 May 2011 11:29:09 -0400 Subject: mdec: enable frame-level multithreading. Signed-off-by: Ronald S. Bultje --- libavcodec/mdec.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 9b6e6b6dd9..02b69d045a 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -31,6 +31,7 @@ #include "dsputil.h" #include "mpegvideo.h" #include "mpeg12.h" +#include "thread.h" typedef struct MDECContext{ AVCodecContext *avctx; @@ -163,10 +164,10 @@ static int decode_frame(AVCodecContext *avctx, int i; if(p->data[0]) - avctx->release_buffer(avctx, p); + ff_thread_release_buffer(avctx, p); p->reference= 0; - if(avctx->get_buffer(avctx, p) < 0){ + if(ff_thread_get_buffer(avctx, p) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } @@ -239,6 +240,18 @@ static av_cold int decode_init(AVCodecContext *avctx){ return 0; } +static av_cold int decode_init_thread_copy(AVCodecContext *avctx){ + MDECContext * const a = avctx->priv_data; + AVFrame *p = (AVFrame*)&a->picture; + + avctx->coded_frame = p; + a->avctx= avctx; + + p->qscale_table = av_mallocz( a->mb_width); + + return 0; +} + static av_cold int decode_end(AVCodecContext *avctx){ MDECContext * const a = avctx->priv_data; @@ -260,7 +273,8 @@ AVCodec ff_mdec_decoder = { NULL, decode_end, decode_frame, - CODEC_CAP_DR1, + CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, .long_name= NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"), + .init_thread_copy= ONLY_IF_THREADS_ENABLED(decode_init_thread_copy) }; -- cgit v1.2.3 From 8d44cd2cd82e27e6b051fe0606dece3b0bec0bcd Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 17 May 2011 10:26:30 -0400 Subject: h264: copy pixel_shift between slice threading contexts. Fixes "make THREADS=2 THREAD_TYPE=2 fate-h264-conformance-frext-pph10i3_panasonic_a". --- libavcodec/h264.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libavcodec') diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 616d0a4804..6b262bc992 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1965,6 +1965,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ c->h264dsp = h->h264dsp; c->sps = h->sps; c->pps = h->pps; + c->pixel_shift = h->pixel_shift; init_scan_tables(c); clone_tables(c, h, i); } -- cgit v1.2.3 From 508a24f8dc63e74bd9917e6f0c4cdbb744741ef0 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 17 May 2011 10:26:29 -0400 Subject: mpeg12: add slice-threading checks to slice-threading initializers. Fixes "make THREADS=2 THREAD_TYPE=1 fate-mpeg2-field-enc". --- libavcodec/mpeg12.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index ffe6b94c05..88ed5332ae 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -2262,7 +2262,7 @@ static int decode_chunks(AVCodecContext *avctx, buf_ptr = ff_find_start_code(buf_ptr,buf_end, &start_code); if (start_code > 0x1ff){ if(s2->pict_type != AV_PICTURE_TYPE_B || avctx->skip_frame <= AVDISCARD_DEFAULT){ - if(avctx->thread_count > 1){ + if((avctx->active_thread_type & FF_THREAD_SLICE) && avctx->thread_count > 1){ int i; avctx->execute(avctx, slice_decode_thread, &s2->thread_context[0], NULL, s->slice_count, sizeof(void*)); @@ -2430,7 +2430,7 @@ static int decode_chunks(AVCodecContext *avctx, break; } - if(avctx->thread_count > 1){ + if((avctx->active_thread_type & FF_THREAD_SLICE) && avctx->thread_count > 1){ int threshold= (s2->mb_height*s->slice_count + avctx->thread_count/2) / avctx->thread_count; if(threshold <= mb_y){ MpegEncContext *thread_context= s2->thread_context[s->slice_count]; @@ -2541,7 +2541,7 @@ AVCodec ff_mpegvideo_decoder = { #if CONFIG_MPEG_XVMC_DECODER static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx){ - if( avctx->thread_count > 1) + if((avctx->active_thread_type & FF_THREAD_SLICE) && avctx->thread_count > 1) return -1; if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) ) return -1; -- cgit v1.2.3 From dede36bd024fb23da244dbfab32b7ef18ca51c82 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 17 May 2011 20:39:09 +0100 Subject: mpegaudio: sanitise compute_antialias_* names This makes the compute_antialias functions use the same naming convention as everything else. Signed-off-by: Mans Rullgard --- libavcodec/mpegaudiodec.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index 77ecb44c9e..4802a04bc8 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -41,7 +41,6 @@ #if CONFIG_FLOAT # define SHR(a,b) ((a)*(1.0f/(1<<(b)))) -# define compute_antialias compute_antialias_float # define FIXR_OLD(a) ((int)((a) * FRAC_ONE + 0.5)) # define FIXR(x) ((float)(x)) # define FIXHR(x) ((float)(x)) @@ -51,7 +50,6 @@ # define OUT_FMT AV_SAMPLE_FMT_FLT #else # define SHR(a,b) ((a)>>(b)) -# define compute_antialias compute_antialias_integer /* WARNING: only correct for posititive numbers */ # define FIXR_OLD(a) ((int)((a) * FRAC_ONE + 0.5)) # define FIXR(a) ((int)((a) * FRAC_ONE + 0.5)) @@ -69,7 +67,7 @@ #include "mpegaudiodata.h" #include "mpegaudiodectab.h" -static void compute_antialias(MPADecodeContext *s, GranuleDef *g); +static void RENAME(compute_antialias)(MPADecodeContext *s, GranuleDef *g); static void apply_window_mp3_c(MPA_INT *synth_buf, MPA_INT *window, int *dither_state, OUT_INT *samples, int incr); @@ -1480,8 +1478,7 @@ static void compute_stereo(MPADecodeContext *s, } #if !CONFIG_FLOAT -static void compute_antialias_integer(MPADecodeContext *s, - GranuleDef *g) +static void compute_antialias_fixed(MPADecodeContext *s, GranuleDef *g) { int32_t *ptr, *csa; int n, i; @@ -1848,7 +1845,7 @@ static int mp_decode_layer3(MPADecodeContext *s) g = &s->granules[ch][gr]; reorder_block(s, g); - compute_antialias(s, g); + RENAME(compute_antialias)(s, g); compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]); } } /* gr */ -- cgit v1.2.3 From a06bf6368be2acb760a10289645eba1f65bf967b Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Mon, 16 May 2011 16:37:38 +0100 Subject: mpegaudiodec: remove decode_end() function This function is not needed since 721d6f2dc5 removed the DCT table allocations for the configuration used here. Signed-off-by: Mans Rullgard --- libavcodec/mpegaudiodec_float.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/mpegaudiodec_float.c b/libavcodec/mpegaudiodec_float.c index e9041fcb63..0ef85d19c1 100644 --- a/libavcodec/mpegaudiodec_float.c +++ b/libavcodec/mpegaudiodec_float.c @@ -80,13 +80,6 @@ static void compute_antialias_float(MPADecodeContext *s, } } -static av_cold int decode_end(AVCodecContext * avctx) -{ - MPADecodeContext *s = avctx->priv_data; - ff_dct_end(&s->dct); - return 0; -} - #if CONFIG_MP1FLOAT_DECODER AVCodec ff_mp1float_decoder = { @@ -96,7 +89,7 @@ AVCodec ff_mp1float_decoder = sizeof(MPADecodeContext), decode_init, NULL, - decode_end, + .close = NULL, decode_frame, CODEC_CAP_PARSE_ONLY, .flush= flush, @@ -112,7 +105,7 @@ AVCodec ff_mp2float_decoder = sizeof(MPADecodeContext), decode_init, NULL, - decode_end, + .close = NULL, decode_frame, CODEC_CAP_PARSE_ONLY, .flush= flush, @@ -128,7 +121,7 @@ AVCodec ff_mp3float_decoder = sizeof(MPADecodeContext), decode_init, NULL, - decode_end, + .close = NULL, decode_frame, CODEC_CAP_PARSE_ONLY, .flush= flush, @@ -144,7 +137,7 @@ AVCodec ff_mp3adufloat_decoder = sizeof(MPADecodeContext), decode_init, NULL, - decode_end, + .close = NULL, decode_frame_adu, CODEC_CAP_PARSE_ONLY, .flush= flush, -- cgit v1.2.3 From 32f8fb8ecf8178b9c9ec8d7152f1fdd8537f7f3a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 24 Apr 2011 17:50:17 -0400 Subject: Add float_interleave() to FmtConvertContext with x86-optimized versions. Partially based on patches by clsid2 in ffdshow-tryout. ff_float_interleave6() x86 improvements by Loren Merrit. --- libavcodec/fmtconvert.c | 20 ++++++ libavcodec/fmtconvert.h | 9 +++ libavcodec/x86/fmtconvert.asm | 141 ++++++++++++++++++++++++++++++++++++++++ libavcodec/x86/fmtconvert_mmx.c | 30 +++++++++ 4 files changed, 200 insertions(+) (limited to 'libavcodec') diff --git a/libavcodec/fmtconvert.c b/libavcodec/fmtconvert.c index e9707555af..58fece70b2 100644 --- a/libavcodec/fmtconvert.c +++ b/libavcodec/fmtconvert.c @@ -56,11 +56,31 @@ static void float_to_int16_interleave_c(int16_t *dst, const float **src, } } +void ff_float_interleave_c(float *dst, const float **src, unsigned int len, + int channels) +{ + int j, c; + unsigned int i; + if (channels == 2) { + for (i = 0; i < len; i++) { + dst[2*i] = src[0][i]; + dst[2*i+1] = src[1][i]; + } + } else if (channels == 1 && len < INT_MAX / sizeof(float)) { + memcpy(dst, src[0], len * sizeof(float)); + } else { + for (c = 0; c < channels; c++) + for (i = 0, j = c; i < len; i++, j += channels) + dst[j] = src[c][i]; + } +} + av_cold void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx) { c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_c; c->float_to_int16 = float_to_int16_c; c->float_to_int16_interleave = float_to_int16_interleave_c; + c->float_interleave = ff_float_interleave_c; if (ARCH_ARM) ff_fmt_convert_init_arm(c, avctx); if (HAVE_ALTIVEC) ff_fmt_convert_init_altivec(c, avctx); diff --git a/libavcodec/fmtconvert.h b/libavcodec/fmtconvert.h index e0afee47e1..d7741135b7 100644 --- a/libavcodec/fmtconvert.h +++ b/libavcodec/fmtconvert.h @@ -68,8 +68,17 @@ typedef struct FmtConvertContext { */ void (*float_to_int16_interleave)(int16_t *dst, const float **src, long len, int channels); + + /** + * Convert an array of interleaved float to multiple arrays of float. + */ + void (*float_interleave)(float *dst, const float **src, unsigned int len, + int channels); } FmtConvertContext; +void ff_float_interleave_c(float *dst, const float **src, unsigned int len, + int channels); + void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx); void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx); diff --git a/libavcodec/x86/fmtconvert.asm b/libavcodec/x86/fmtconvert.asm index 5cd8f6c596..e023b48322 100644 --- a/libavcodec/x86/fmtconvert.asm +++ b/libavcodec/x86/fmtconvert.asm @@ -20,6 +20,7 @@ ;****************************************************************************** %include "x86inc.asm" +%include "x86util.asm" section .text align=16 @@ -89,3 +90,143 @@ FLOAT_TO_INT16_INTERLEAVE6 3dnow %undef pswapd FLOAT_TO_INT16_INTERLEAVE6 3dn2 %undef cvtps2pi + +;----------------------------------------------------------------------------- +; void ff_float_interleave6(float *dst, const float **src, unsigned int len); +;----------------------------------------------------------------------------- + +%macro BUTTERFLYPS 3 + movaps m%3, m%1 + unpcklps m%1, m%2 + unpckhps m%3, m%2 + SWAP %2, %3 +%endmacro + +%macro FLOAT_INTERLEAVE6 2 +cglobal float_interleave6_%1, 2,7,%2, dst, src, src1, src2, src3, src4, src5 +%ifdef ARCH_X86_64 + %define lend r10d + mov lend, r2d +%else + %define lend dword r2m +%endif + mov src1q, [srcq+1*gprsize] + mov src2q, [srcq+2*gprsize] + mov src3q, [srcq+3*gprsize] + mov src4q, [srcq+4*gprsize] + mov src5q, [srcq+5*gprsize] + mov srcq, [srcq] + sub src1q, srcq + sub src2q, srcq + sub src3q, srcq + sub src4q, srcq + sub src5q, srcq +.loop: +%ifidn %1, sse + movaps m0, [srcq] + movaps m1, [srcq+src1q] + movaps m2, [srcq+src2q] + movaps m3, [srcq+src3q] + movaps m4, [srcq+src4q] + movaps m5, [srcq+src5q] + + BUTTERFLYPS 0, 1, 6 + BUTTERFLYPS 2, 3, 6 + BUTTERFLYPS 4, 5, 6 + + movaps m6, m4 + shufps m4, m0, 0xe4 + movlhps m0, m2 + movhlps m6, m2 + movaps [dstq ], m0 + movaps [dstq+16], m4 + movaps [dstq+32], m6 + + movaps m6, m5 + shufps m5, m1, 0xe4 + movlhps m1, m3 + movhlps m6, m3 + movaps [dstq+48], m1 + movaps [dstq+64], m5 + movaps [dstq+80], m6 +%else ; mmx + movq m0, [srcq] + movq m1, [srcq+src1q] + movq m2, [srcq+src2q] + movq m3, [srcq+src3q] + movq m4, [srcq+src4q] + movq m5, [srcq+src5q] + + SBUTTERFLY dq, 0, 1, 6 + SBUTTERFLY dq, 2, 3, 6 + SBUTTERFLY dq, 4, 5, 6 + movq [dstq ], m0 + movq [dstq+ 8], m2 + movq [dstq+16], m4 + movq [dstq+24], m1 + movq [dstq+32], m3 + movq [dstq+40], m5 +%endif + add srcq, mmsize + add dstq, mmsize*6 + sub lend, mmsize/4 + jg .loop +%ifidn %1, mmx + emms +%endif + REP_RET +%endmacro + +INIT_MMX +FLOAT_INTERLEAVE6 mmx, 0 +INIT_XMM +FLOAT_INTERLEAVE6 sse, 7 + +;----------------------------------------------------------------------------- +; void ff_float_interleave2(float *dst, const float **src, unsigned int len); +;----------------------------------------------------------------------------- + +%macro FLOAT_INTERLEAVE2 2 +cglobal float_interleave2_%1, 3,4,%2, dst, src, len, src1 + mov src1q, [srcq+gprsize] + mov srcq, [srcq ] + sub src1q, srcq +.loop + MOVPS m0, [srcq ] + MOVPS m1, [srcq+src1q ] + MOVPS m3, [srcq +mmsize] + MOVPS m4, [srcq+src1q+mmsize] + + MOVPS m2, m0 + PUNPCKLDQ m0, m1 + PUNPCKHDQ m2, m1 + + MOVPS m1, m3 + PUNPCKLDQ m3, m4 + PUNPCKHDQ m1, m4 + + MOVPS [dstq ], m0 + MOVPS [dstq+1*mmsize], m2 + MOVPS [dstq+2*mmsize], m3 + MOVPS [dstq+3*mmsize], m1 + + add srcq, mmsize*2 + add dstq, mmsize*4 + sub lend, mmsize/2 + jg .loop +%ifidn %1, mmx + emms +%endif + REP_RET +%endmacro + +INIT_MMX +%define MOVPS movq +%define PUNPCKLDQ punpckldq +%define PUNPCKHDQ punpckhdq +FLOAT_INTERLEAVE2 mmx, 0 +INIT_XMM +%define MOVPS movaps +%define PUNPCKLDQ unpcklps +%define PUNPCKHDQ unpckhps +FLOAT_INTERLEAVE2 sse, 5 diff --git a/libavcodec/x86/fmtconvert_mmx.c b/libavcodec/x86/fmtconvert_mmx.c index 847bd80fcd..61a4272a69 100644 --- a/libavcodec/x86/fmtconvert_mmx.c +++ b/libavcodec/x86/fmtconvert_mmx.c @@ -235,11 +235,40 @@ static void float_to_int16_interleave_3dn2(int16_t *dst, const float **src, long float_to_int16_interleave_3dnow(dst, src, len, channels); } +void ff_float_interleave2_mmx(float *dst, const float **src, unsigned int len); +void ff_float_interleave2_sse(float *dst, const float **src, unsigned int len); + +void ff_float_interleave6_mmx(float *dst, const float **src, unsigned int len); +void ff_float_interleave6_sse(float *dst, const float **src, unsigned int len); + +static void float_interleave_mmx(float *dst, const float **src, + unsigned int len, int channels) +{ + if (channels == 2) { + ff_float_interleave2_mmx(dst, src, len); + } else if (channels == 6) + ff_float_interleave6_mmx(dst, src, len); + else + ff_float_interleave_c(dst, src, len, channels); +} + +static void float_interleave_sse(float *dst, const float **src, + unsigned int len, int channels) +{ + if (channels == 2) { + ff_float_interleave2_sse(dst, src, len); + } else if (channels == 6) + ff_float_interleave6_sse(dst, src, len); + else + ff_float_interleave_c(dst, src, len, channels); +} + void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx) { int mm_flags = av_get_cpu_flags(); if (mm_flags & AV_CPU_FLAG_MMX) { + c->float_interleave = float_interleave_mmx; if(mm_flags & AV_CPU_FLAG_3DNOW){ if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ @@ -256,6 +285,7 @@ void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx) c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_sse; c->float_to_int16 = float_to_int16_sse; c->float_to_int16_interleave = float_to_int16_interleave_sse; + c->float_interleave = float_interleave_sse; } if(mm_flags & AV_CPU_FLAG_SSE2){ c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_sse2; -- cgit v1.2.3 From 64150ff014708b4b00cb5d76237e9e908ac0fbfc Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 19 Apr 2011 19:47:01 -0400 Subject: Add request_sample_fmt field to AVCodecContext. This will allow audio decoders to support output of different sample formats as a runtime option. --- libavcodec/avcodec.h | 7 +++++++ libavcodec/options.c | 6 ++++++ libavcodec/version.h | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'libavcodec') diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 2eb218ba4f..e067ee0273 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2836,6 +2836,13 @@ typedef struct AVCodecContext { * - decoding: Set by libavcodec. */ enum AVAudioServiceType audio_service_type; + + /** + * Used to request a sample format from the decoder. + * - encoding: unused. + * - decoding: Set by user. + */ + enum AVSampleFormat request_sample_fmt; } AVCodecContext; /** diff --git a/libavcodec/options.c b/libavcodec/options.c index 9c714fb73e..8f9aec4ac2 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -441,6 +441,12 @@ static const AVOption options[]={ {"em", "Emergency", 0, FF_OPT_TYPE_CONST, {.dbl = AV_AUDIO_SERVICE_TYPE_EMERGENCY }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, {"vo", "Voice Over", 0, FF_OPT_TYPE_CONST, {.dbl = AV_AUDIO_SERVICE_TYPE_VOICE_OVER }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, {"ka", "Karaoke", 0, FF_OPT_TYPE_CONST, {.dbl = AV_AUDIO_SERVICE_TYPE_KARAOKE }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"request_sample_fmt", NULL, OFFSET(request_sample_fmt), FF_OPT_TYPE_INT, {.dbl = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"}, +{"u8" , "8-bit unsigned integer", 0, FF_OPT_TYPE_CONST, {.dbl = AV_SAMPLE_FMT_U8 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, +{"s16", "16-bit signed integer", 0, FF_OPT_TYPE_CONST, {.dbl = AV_SAMPLE_FMT_S16 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, +{"s32", "32-bit signed integer", 0, FF_OPT_TYPE_CONST, {.dbl = AV_SAMPLE_FMT_S32 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, +{"flt", "32-bit float", 0, FF_OPT_TYPE_CONST, {.dbl = AV_SAMPLE_FMT_FLT }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, +{"dbl", "64-bit double", 0, FF_OPT_TYPE_CONST, {.dbl = AV_SAMPLE_FMT_DBL }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"}, {NULL}, }; diff --git a/libavcodec/version.h b/libavcodec/version.h index 1b454b8bd6..0def0d1ff9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 3 +#define LIBAVCODEC_VERSION_MINOR 4 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ -- cgit v1.2.3 From 9aa8193a234ccb6a79cba5cc550531f62ffb0a17 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 22 Apr 2011 21:30:19 -0400 Subject: Add floating-point sample format support to the ac3, eac3, dca, aac, and vorbis decoders. Based on patches by clsid2 in ffdshow-tryout. --- libavcodec/aacdec.c | 34 ++++++++++++++++++++++++---------- libavcodec/aacsbr.c | 11 ++++++++--- libavcodec/aacsbr.h | 2 +- libavcodec/ac3dec.c | 32 ++++++++++++++++++++++++++------ libavcodec/dca.c | 34 +++++++++++++++++++++++++++------- libavcodec/vorbisdec.c | 23 ++++++++++++++++++----- 6 files changed, 104 insertions(+), 32 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 5f9dd834a0..f2d50f4aba 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -186,7 +186,7 @@ static av_cold int che_configure(AACContext *ac, if (che_pos[type][id]) { if (!ac->che[type][id] && !(ac->che[type][id] = av_mallocz(sizeof(ChannelElement)))) return AVERROR(ENOMEM); - ff_aac_sbr_ctx_init(&ac->che[type][id]->sbr); + ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr); if (type != TYPE_CCE) { ac->output_data[(*channels)++] = ac->che[type][id]->ch[0].ret; if (type == TYPE_CPE || @@ -546,6 +546,7 @@ static void reset_predictor_group(PredictorState *ps, int group_num) static av_cold int aac_decode_init(AVCodecContext *avctx) { AACContext *ac = avctx->priv_data; + float output_scale_factor; ac->avctx = avctx; ac->m4ac.sample_rate = avctx->sample_rate; @@ -557,7 +558,13 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) return -1; } - avctx->sample_fmt = AV_SAMPLE_FMT_S16; + if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) { + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + output_scale_factor = 1.0 / 32768.0; + } else { + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + output_scale_factor = 1.0; + } AAC_INIT_VLC_STATIC( 0, 304); AAC_INIT_VLC_STATIC( 1, 270); @@ -585,9 +592,9 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) ff_aac_scalefactor_code, sizeof(ff_aac_scalefactor_code[0]), sizeof(ff_aac_scalefactor_code[0]), 352); - ff_mdct_init(&ac->mdct, 11, 1, 1.0/1024.0); - ff_mdct_init(&ac->mdct_small, 8, 1, 1.0/128.0); - ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0); + ff_mdct_init(&ac->mdct, 11, 1, output_scale_factor/1024.0); + ff_mdct_init(&ac->mdct_small, 8, 1, output_scale_factor/128.0); + ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0/output_scale_factor); // window initialization ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); @@ -2169,7 +2176,8 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, avctx->frame_size = samples; } - data_size_tmp = samples * avctx->channels * sizeof(int16_t); + data_size_tmp = samples * avctx->channels * + (av_get_bits_per_sample_fmt(avctx->sample_fmt) / 8); if (*data_size < data_size_tmp) { av_log(avctx, AV_LOG_ERROR, "Output buffer too small (%d) or trying to output too many samples (%d) for this frame.\n", @@ -2178,8 +2186,14 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, } *data_size = data_size_tmp; - if (samples) - ac->fmt_conv.float_to_int16_interleave(data, (const float **)ac->output_data, samples, avctx->channels); + if (samples) { + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) + ac->fmt_conv.float_interleave(data, (const float **)ac->output_data, + samples, avctx->channels); + else + ac->fmt_conv.float_to_int16_interleave(data, (const float **)ac->output_data, + samples, avctx->channels); + } if (ac->output_configured) ac->output_configured = OC_LOCKED; @@ -2497,7 +2511,7 @@ AVCodec ff_aac_decoder = { aac_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("Advanced Audio Coding"), .sample_fmts = (const enum AVSampleFormat[]) { - AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .channel_layouts = aac_channel_layout, }; @@ -2517,7 +2531,7 @@ AVCodec ff_aac_latm_decoder = { .decode = latm_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Codec LATM syntax)"), .sample_fmts = (const enum AVSampleFormat[]) { - AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .channel_layouts = aac_channel_layout, }; diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c index 7a217abfda..81b0b4c001 100644 --- a/libavcodec/aacsbr.c +++ b/libavcodec/aacsbr.c @@ -126,14 +126,19 @@ av_cold void ff_aac_sbr_init(void) ff_ps_init(); } -av_cold void ff_aac_sbr_ctx_init(SpectralBandReplication *sbr) +av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr) { + float mdct_scale; sbr->kx[0] = sbr->kx[1] = 32; //Typo in spec, kx' inits to 32 sbr->data[0].e_a[1] = sbr->data[1].e_a[1] = -1; sbr->data[0].synthesis_filterbank_samples_offset = SBR_SYNTHESIS_BUF_SIZE - (1280 - 128); sbr->data[1].synthesis_filterbank_samples_offset = SBR_SYNTHESIS_BUF_SIZE - (1280 - 128); - ff_mdct_init(&sbr->mdct, 7, 1, 1.0/64); - ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0); + /* SBR requires samples to be scaled to +/-32768.0 to work correctly. + * mdct scale factors are adjusted to scale up from +/-1.0 at analysis + * and scale back down at synthesis. */ + mdct_scale = ac->avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? 32768.0f : 1.0f; + ff_mdct_init(&sbr->mdct, 7, 1, 1.0 / (64 * mdct_scale)); + ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0 * mdct_scale); ff_ps_ctx_init(&sbr->ps); } diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h index dca83305ad..153070d3f2 100644 --- a/libavcodec/aacsbr.h +++ b/libavcodec/aacsbr.h @@ -36,7 +36,7 @@ /** Initialize SBR. */ av_cold void ff_aac_sbr_init(void); /** Initialize one SBR context. */ -av_cold void ff_aac_sbr_ctx_init(SpectralBandReplication *sbr); +av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr); /** Close one SBR context. */ av_cold void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr); /** Decode one SBR element. */ diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 015ebaebec..2966c33b25 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -189,7 +189,13 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) av_lfg_init(&s->dith_state, 0); /* set scale value for float to int16 conversion */ - s->mul_bias = 32767.0f; + if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) { + s->mul_bias = 1.0f; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + } else { + s->mul_bias = 32767.0f; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + } /* allow downmixing to stereo or mono */ if (avctx->channels > 0 && avctx->request_channels > 0 && @@ -204,7 +210,6 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) if (!s->input_buffer) return AVERROR(ENOMEM); - avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } @@ -1299,7 +1304,8 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AC3DecodeContext *s = avctx->priv_data; - int16_t *out_samples = (int16_t *)data; + float *out_samples_flt = data; + int16_t *out_samples_s16 = data; int blk, ch, err; const uint8_t *channel_map; const float *output[AC3_MAX_CHANNELS]; @@ -1405,10 +1411,18 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n"); err = 1; } - s->fmt_conv.float_to_int16_interleave(out_samples, output, 256, s->out_channels); - out_samples += 256 * s->out_channels; + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { + s->fmt_conv.float_interleave(out_samples_flt, output, 256, + s->out_channels); + out_samples_flt += 256 * s->out_channels; + } else { + s->fmt_conv.float_to_int16_interleave(out_samples_s16, output, 256, + s->out_channels); + out_samples_s16 += 256 * s->out_channels; + } } - *data_size = s->num_blocks * 256 * avctx->channels * sizeof (int16_t); + *data_size = s->num_blocks * 256 * avctx->channels * + (av_get_bits_per_sample_fmt(avctx->sample_fmt) / 8); return FFMIN(buf_size, s->frame_size); } @@ -1435,6 +1449,9 @@ AVCodec ff_ac3_decoder = { .close = ac3_decode_end, .decode = ac3_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE + }, }; #if CONFIG_EAC3_DECODER @@ -1447,5 +1464,8 @@ AVCodec ff_eac3_decoder = { .close = ac3_decode_end, .decode = ac3_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE + }, }; #endif diff --git a/libavcodec/dca.c b/libavcodec/dca.c index f1cd64e9ed..dbadebacff 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -1626,7 +1626,9 @@ static int dca_decode_frame(AVCodecContext * avctx, int lfe_samples; int num_core_channels = 0; int i; - int16_t *samples = data; + float *samples_flt = data; + int16_t *samples_s16 = data; + int out_size; DCAContext *s = avctx->priv_data; int channels; int core_ss_end; @@ -1812,9 +1814,11 @@ static int dca_decode_frame(AVCodecContext * avctx, return -1; } - if (*data_size < (s->sample_blocks / 8) * 256 * sizeof(int16_t) * channels) + out_size = 256 / 8 * s->sample_blocks * channels * + (av_get_bits_per_sample_fmt(avctx->sample_fmt) / 8); + if (*data_size < out_size) return -1; - *data_size = 256 / 8 * s->sample_blocks * sizeof(int16_t) * channels; + *data_size = out_size; /* filter to get final output */ for (i = 0; i < (s->sample_blocks / 8); i++) { @@ -1833,8 +1837,16 @@ static int dca_decode_frame(AVCodecContext * avctx, } } - s->fmt_conv.float_to_int16_interleave(samples, s->samples_chanptr, 256, channels); - samples += 256 * channels; + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { + s->fmt_conv.float_interleave(samples_flt, s->samples_chanptr, 256, + channels); + samples_flt += 256 * channels; + } else { + s->fmt_conv.float_to_int16_interleave(samples_s16, + s->samples_chanptr, 256, + channels); + samples_s16 += 256 * channels; + } } /* update lfe history */ @@ -1870,9 +1882,14 @@ static av_cold int dca_decode_init(AVCodecContext * avctx) for (i = 0; i < DCA_PRIM_CHANNELS_MAX+1; i++) s->samples_chanptr[i] = s->samples + i * 256; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; - s->scale_bias = 1.0; + if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) { + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + s->scale_bias = 1.0 / 32768.0; + } else { + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + s->scale_bias = 1.0; + } /* allow downmixing to stereo */ if (avctx->channels > 0 && avctx->request_channels < avctx->channels && @@ -1909,5 +1926,8 @@ AVCodec ff_dca_decoder = { .close = dca_decode_end, .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), .capabilities = CODEC_CAP_CHANNEL_CONF, + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE + }, .profiles = NULL_IF_CONFIG_SMALL(profiles), }; diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index 7443e98a64..f6ec74f4a1 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -979,7 +979,13 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) dsputil_init(&vc->dsp, avccontext); ff_fmt_convert_init(&vc->fmt_conv, avccontext); - vc->scale_bias = 32768.0f; + if (avccontext->request_sample_fmt == AV_SAMPLE_FMT_FLT) { + avccontext->sample_fmt = AV_SAMPLE_FMT_FLT; + vc->scale_bias = 1.0f; + } else { + avccontext->sample_fmt = AV_SAMPLE_FMT_S16; + vc->scale_bias = 32768.0f; + } if (!headers_len) { av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n"); @@ -1024,7 +1030,6 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext) avccontext->channels = vc->audio_channels; avccontext->sample_rate = vc->audio_samplerate; avccontext->frame_size = FFMIN(vc->blocksize[0], vc->blocksize[1]) >> 2; - avccontext->sample_fmt = AV_SAMPLE_FMT_S16; return 0 ; } @@ -1634,9 +1639,14 @@ static int vorbis_decode_frame(AVCodecContext *avccontext, len * ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i]; } - vc->fmt_conv.float_to_int16_interleave(data, channel_ptrs, len, - vc->audio_channels); - *data_size = len * 2 * vc->audio_channels; + if (avccontext->sample_fmt == AV_SAMPLE_FMT_FLT) + vc->fmt_conv.float_interleave(data, channel_ptrs, len, vc->audio_channels); + else + vc->fmt_conv.float_to_int16_interleave(data, channel_ptrs, len, + vc->audio_channels); + + *data_size = len * vc->audio_channels * + (av_get_bits_per_sample_fmt(avccontext->sample_fmt) / 8); return buf_size ; } @@ -1663,5 +1673,8 @@ AVCodec ff_vorbis_decoder = { vorbis_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), .channel_layouts = ff_vorbis_channel_layouts, + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE + }, }; -- cgit v1.2.3