From 679582503c8ba2f91a82e44c4a2938550306fd07 Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Thu, 21 Feb 2013 22:35:00 +0200 Subject: [PATCH 3/5] ffmpeg_audio_decoder: support new av_decode_audio4 () --- src/combined/ffmpeg/ff_audio_decoder.c | 153 +++++++++++++++++++++++++++------ src/combined/ffmpeg/ffmpeg_compat.h | 4 +- 2 files changed, 131 insertions(+), 26 deletions(-) diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index 4e64378..34a7a9e 100644 --- a/src/combined/ffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -71,7 +71,9 @@ typedef struct ff_audio_decoder_s { int decoder_ok; AVCodecParserContext *parser_context; - +#if AVAUDIO > 3 + AVFrame *av_frame; +#endif } ff_audio_decoder_t; @@ -150,6 +152,9 @@ static void ff_audio_init_codec(ff_audio_decoder_t *this, unsigned int codec_typ return; } + /* Try to make the following true */ + this->context->request_sample_fmt = AV_SAMPLE_FMT_S16; + /* Current ffmpeg audio decoders usually use 16 bits/sample * buf->decoder_info[2] can't be used as it doesn't refer to the output * bits/sample for some codecs (e.g. MS ADPCM) */ @@ -358,25 +363,19 @@ static void ff_audio_output_close(ff_audio_decoder_t *this) this->audio_channels = 0; } -static int ff_audio_decode(xine_t *xine, - AVCodecContext *ctx, - AVCodecParserContext *parser_ctx, - int16_t *decode_buffer, int *decode_buffer_size, - uint8_t *buf, int size) -{ +static int ff_audio_decode (ff_audio_decoder_t *this, + int16_t *decode_buffer, int *decode_buffer_size, uint8_t *buf, int size) { int consumed; int parser_consumed = 0; #if AVPARSE > 1 - if (parser_ctx) { + if (this->parser_context) { uint8_t *outbuf; int outsize; do { - int ret = av_parser_parse2(parser_ctx, ctx, - &outbuf, &outsize, - buf, size, - 0, 0, 0); + int ret = av_parser_parse2 (this->parser_context, this->context, + &outbuf, &outsize, buf, size, 0, 0, 0); parser_consumed += ret; buf += ret; size -= ret; @@ -385,7 +384,7 @@ static int ff_audio_decode(xine_t *xine, /* nothing to decode ? */ if (outsize <= 0) { *decode_buffer_size = 0; - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: not enough data to decode\n"); return parser_consumed; } @@ -402,21 +401,115 @@ static int ff_audio_decode(xine_t *xine, avpkt.data = buf; avpkt.size = size; avpkt.flags = AV_PKT_FLAG_KEY; - consumed = avcodec_decode_audio3 (ctx, - decode_buffer, decode_buffer_size, - &avpkt); +# if AVAUDIO > 3 + int got_frame; + if (!this->av_frame) + this->av_frame = avcodec_alloc_frame (); + + consumed = avcodec_decode_audio4 (this->context, this->av_frame, &got_frame, &avpkt); + if ((consumed >= 0) && got_frame) { + int16_t *q = decode_buffer; + int samples = this->av_frame->nb_samples; + int channels = this->context->channels; + int bytes, i, j; + /* limit buffer */ + if (channels > 12) + channels = 12; + if (*decode_buffer_size < samples * channels * 2) + samples = *decode_buffer_size / (channels * 2); + bytes = samples * channels * 2; + *decode_buffer_size = bytes; + /* convert to packed int16_t. I guess there is something + in libavfilter but also another dependency... */ + switch (this->context->sample_fmt) { + case AV_SAMPLE_FMT_U8P: + if (channels > 1) { + uint8_t *p[12]; + for (i = 0; i < channels; i++) + p[i] = (uint8_t *)this->av_frame->extended_data[i]; + for (i = samples; i; i--) { + for (j = 0; j < channels; j++) + *q++ = ((uint16_t)(*p[j]++) << 8) ^ 0x8000; + } + break; + } + case AV_SAMPLE_FMT_U8: + { + uint8_t *p = (uint8_t *)this->av_frame->extended_data[0]; + for (i = samples * channels; i; i--) + *q++ = ((uint16_t)(*p++) << 8) ^ 0x8000; + } + break; + case AV_SAMPLE_FMT_S16P: + if (channels > 1) { + int16_t *p[12]; + for (i = 0; i < channels; i++) + p[i] = (int16_t *)this->av_frame->extended_data[i]; + for (i = samples; i; i--) { + for (j = 0; j < channels; j++) + *q++ = *p[j]++; + } + break; + } + case AV_SAMPLE_FMT_S16: + xine_fast_memcpy (q, this->av_frame->extended_data[0], bytes); + break; + case AV_SAMPLE_FMT_S32P: + if (channels > 1) { + int32_t *p[12]; + for (i = 0; i < channels; i++) + p[i] = (int32_t *)this->av_frame->extended_data[i]; + for (i = samples; i; i--) { + for (j = 0; j < channels; j++) + *q++ = *p[j]++ >> 16; + } + break; + } + case AV_SAMPLE_FMT_S32: + { + int32_t *p = (int32_t *)this->av_frame->extended_data[0]; + for (i = samples * channels; i; i--) + *q++ = *p++ >> 16; + } + break; + case AV_SAMPLE_FMT_FLTP: /* the most popular one */ + if (channels > 1) { + float *p[12]; + for (i = 0; i < channels; i++) + p[i] = (float *)this->av_frame->extended_data[i]; + for (i = samples; i; i--) { + for (j = 0; j < channels; j++) { + int v = *p[j]++ * (float)0x7fff; + *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v; + } + } + break; + } + case AV_SAMPLE_FMT_FLT: + { + float *p = (float *)this->av_frame->extended_data[0]; + for (i = samples * channels; i; i--) { + int v = *p++ * (float)0x7fff; + *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v; + } + } + break; + default: ; + } + } else *decode_buffer_size = 0; +# else + consumed = avcodec_decode_audio3 (this->context, decode_buffer, decode_buffer_size, &avpkt); +# endif #else - consumed = avcodec_decode_audio2 (ctx, - decode_buffer, decode_buffer_size, - buf, size); + consumed = avcodec_decode_audio2 (this->context, decode_buffer, decode_buffer_size, buf, size); #endif if (consumed < 0) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: error decompressing audio frame (%d)\n", consumed); } else if (parser_consumed && consumed != size) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: decoder didn't consume all data\n"); } @@ -469,8 +562,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) decode_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; bytes_consumed = - ff_audio_decode(this->stream->xine, this->context, - this->parser_context, + ff_audio_decode(this, (int16_t *)this->decode_buffer, &decode_buffer_size, &this->buf[offset], this->size); @@ -539,6 +631,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) } /* fill up this buffer */ +#if AVAUDIO < 4 if (codec_type == BUF_AUDIO_WMAPRO) { /* the above codecs output float samples, not 16-bit integers */ int bytes_per_sample = sizeof(float); @@ -558,7 +651,9 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) bytes_to_send = bytes_to_send * 2 / bytes_per_sample; xine_fast_memcpy(audio_buffer->mem, int_buffer, bytes_to_send); free(int_buffer); - } else { + } else +#endif + { if ((decode_buffer_size - out) > audio_buffer->mem_size) bytes_to_send = audio_buffer->mem_size; else @@ -595,6 +690,9 @@ static void ff_audio_reset (audio_decoder_t *this_gen) { /* try to reset the wma decoder */ if( this->decoder_ok ) { +#if AVAUDIO > 3 + avcodec_free_frame (&this->av_frame); +#endif pthread_mutex_lock (&ffmpeg_lock); avcodec_close (this->context); if (avcodec_open (this->context, this->codec) < 0) @@ -626,6 +724,9 @@ static void ff_audio_dispose (audio_decoder_t *this_gen) { } if( this->context && this->decoder_ok ) { +#if AVAUDIO > 3 + avcodec_free_frame (&this->av_frame); +#endif pthread_mutex_lock (&ffmpeg_lock); avcodec_close (this->context); pthread_mutex_unlock (&ffmpeg_lock); @@ -668,7 +769,9 @@ static audio_decoder_t *ff_audio_open_plugin (audio_decoder_class_t *class_gen, this->context = avcodec_alloc_context(); this->decode_buffer = malloc16 (AVCODEC_MAX_AUDIO_FRAME_SIZE); - +#if AVAUDIO > 3 + this->av_frame = NULL; +#endif return &this->audio_decoder; } diff --git a/src/combined/ffmpeg/ffmpeg_compat.h b/src/combined/ffmpeg/ffmpeg_compat.h index 0acead8..b567dc1 100644 --- a/src/combined/ffmpeg/ffmpeg_compat.h +++ b/src/combined/ffmpeg/ffmpeg_compat.h @@ -94,7 +94,9 @@ #endif /* avcodec_decode_audio() */ -#if LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 32) +#if LIBAVCODEC_VERSION_MAJOR >= 54 +# define AVAUDIO 4 +#elif LIBAVCODEC_VERSION_MAJOR >= 53 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 32) # define AVAUDIO 3 #else # define AVAUDIO 2 -- 1.8.1.5