From 7c08daf5475034f020d6fcde373ca3c5361edcef Mon Sep 17 00:00:00 2001 From: "anton@khirnov.net" Date: Sat, 1 Mar 2014 10:28:51 +0100 Subject: [PATCH] Re: FTBFS with libav10 Gbp-Pq: Name libav10.patch --- ffmpeg.c | 107 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index bd73f49..97f7163 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -26,18 +26,12 @@ #endif #include -#ifdef HAVE_FFMPEG_AVCODEC_H -#include -#include -#include -#else #include #include #include -#ifndef AVUTIL_MATHEMATICS_H +#include +#include #include -#endif -#endif #if (LIBAVFORMAT_VERSION_INT < ((52<<16)+(31<<8)+0)) # define NUM_FFMPEG_KEYS 8 @@ -77,6 +71,7 @@ struct ffmpeg_output { uint8_t *buffer_malloc; uint8_t *buffer_pos; /* current buffer position */ int buffer_used_len; + int buffer_size; }; struct ffmpeg_private { @@ -87,6 +82,13 @@ struct ffmpeg_private { struct ffmpeg_input *input; struct ffmpeg_output *output; + + AVFrame *frame; + + AVAudioResampleContext *avr; + uint64_t resample_channel_layout; + int resample_sample_rate; + int resample_sample_fmt; }; static struct ffmpeg_input *ffmpeg_input_create(void) @@ -112,7 +114,8 @@ static struct ffmpeg_output *ffmpeg_output_create(void) { struct ffmpeg_output *output = xnew(struct ffmpeg_output, 1); - output->buffer_malloc = xnew(uint8_t, AVCODEC_MAX_AUDIO_FRAME_SIZE + 15); + output->buffer_size = 192000 + 15; + output->buffer_malloc = xnew(uint8_t, output->buffer_size); output->buffer = output->buffer_malloc; /* align to 16 bytes so avcodec can SSE/Altivec/etc */ while ((intptr_t) output->buffer % 16) @@ -241,20 +244,12 @@ static int ffmpeg_open(struct input_plugin_data *ip_data) break; } -#if (LIBAVCODEC_VERSION_INT > ((51<<16)+(64<<8)+0)) - if (cc->sample_fmt == AV_SAMPLE_FMT_FLT || cc->sample_fmt == AV_SAMPLE_FMT_DBL) { -#else - if (cc->sample_fmt == AV_SAMPLE_FMT_FLT) { -#endif - err = -IP_ERROR_SAMPLE_FORMAT; - break; - } /* We assume below that no more errors follow. */ } while (0); if (err < 0) { /* Clean up. cc is never opened at this point. (See above assumption.) */ - av_close_input_file(ic); + avformat_close_input(&ic); return err; } @@ -262,11 +257,12 @@ static int ffmpeg_open(struct input_plugin_data *ip_data) priv->codec_context = cc; priv->input_context = ic; priv->codec = codec; + priv->frame = av_frame_alloc(); priv->stream_index = stream_index; priv->input = ffmpeg_input_create(); if (priv->input == NULL) { avcodec_close(cc); - av_close_input_file(ic); + avformat_close_input(&ic); free(priv); return -IP_ERROR_INTERNAL; } @@ -300,8 +296,10 @@ static int ffmpeg_close(struct input_plugin_data *ip_data) { struct ffmpeg_private *priv = ip_data->private; + av_frame_free(&priv->frame); + avresample_free(&priv->avr); avcodec_close(priv->codec_context); - av_close_input_file(priv->input_context); + avformat_close_input(&priv->input_context); ffmpeg_input_free(priv->input); ffmpeg_output_free(priv->output); free(priv); @@ -313,14 +311,18 @@ static int ffmpeg_close(struct input_plugin_data *ip_data) * This returns the number of bytes added to the buffer. * It returns < 0 on error. 0 on EOF. */ -static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ffmpeg_input *input, +static int ffmpeg_fill_buffer(struct ffmpeg_private *priv, struct ffmpeg_input *input, struct ffmpeg_output *output) { + AVFormatContext *ic = priv->input_context; + AVCodecContext *cc = priv->codec_context; + AVFrame *frame = priv->frame; + while (1) { /* frame_size specifies the size of output->buffer for * avcodec_decode_audio2. */ - int frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; - int len; + AVPacket avpkt; + int len, got_output, ret; if (input->curr_pkt_size <= 0) { av_free_packet(&input->pkt); @@ -335,26 +337,11 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff continue; } - /* The change to avcodec_decode_audio2 occurred between - * 51.28.0 and 51.29.0 */ -#if (LIBAVCODEC_VERSION_INT <= ((51<<16) + (28<<8) + 0)) - len = avcodec_decode_audio(cc, (int16_t *)output->buffer, &frame_size, - input->curr_pkt_buf, input->curr_pkt_size); - /* The change to avcodec_decode_audio3 occurred between - * 52.25.0 and 52.26.0 */ -#elif (LIBAVCODEC_VERSION_INT <= ((52<<16) + (25<<8) + 0)) - len = avcodec_decode_audio2(cc, (int16_t *) output->buffer, &frame_size, - input->curr_pkt_buf, input->curr_pkt_size); -#else - { - AVPacket avpkt; - av_init_packet(&avpkt); - avpkt.data = input->curr_pkt_buf; - avpkt.size = input->curr_pkt_size; - len = avcodec_decode_audio3(cc, (int16_t *) output->buffer, &frame_size, &avpkt); - av_free_packet(&avpkt); - } -#endif + av_init_packet(&avpkt); + avpkt.data = input->curr_pkt_buf; + avpkt.size = input->curr_pkt_size; + len = avcodec_decode_audio4(cc, frame, &got_output, &avpkt); + if (len < 0) { /* this is often reached when seeking, not sure why */ input->curr_pkt_size = 0; @@ -362,10 +349,34 @@ static int ffmpeg_fill_buffer(AVFormatContext *ic, AVCodecContext *cc, struct ff } input->curr_pkt_size -= len; input->curr_pkt_buf += len; - if (frame_size > 0) { + if (got_output) { + if (!priv->avr || + frame->format != priv->resample_sample_fmt || + frame->sample_rate != priv->resample_sample_rate || + frame->channel_layout != priv->resample_channel_layout) { + + avresample_free(&priv->avr); + + priv->avr = avresample_alloc_context(); + av_opt_set_int(priv->avr, "in_channel_layout", frame->channel_layout, 0); + av_opt_set_int(priv->avr, "out_channel_layout", frame->channel_layout, 0); + av_opt_set_int(priv->avr, "in_sample_rate", frame->sample_rate, 0); + av_opt_set_int(priv->avr, "out_sample_rate", frame->sample_rate, 0); + av_opt_set_int(priv->avr, "in_sample_fmt", frame->format, 0); + av_opt_set_int(priv->avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + + ret = avresample_open(priv->avr); + if (ret < 0) + return -IP_ERROR_INTERNAL; + } + + len = avresample_convert(priv->avr, (uint8_t**)&output->buffer, + output->buffer_size, frame->nb_samples, + frame->extended_data, frame->linesize[0], frame->nb_samples); + output->buffer_pos = output->buffer; - output->buffer_used_len = frame_size; - return frame_size; + output->buffer_used_len = len * 2 * cc->channels; + return output->buffer_used_len; } } /* This should never get here. */ @@ -380,7 +391,7 @@ static int ffmpeg_read(struct input_plugin_data *ip_data, char *buffer, int coun int out_size; if (output->buffer_used_len == 0) { - rc = ffmpeg_fill_buffer(priv->input_context, priv->codec_context, priv->input, priv->output); + rc = ffmpeg_fill_buffer(priv, priv->input, priv->output); if (rc <= 0) { return rc; } @@ -494,7 +505,7 @@ static long ffmpeg_current_bitrate(struct input_plugin_data *ip_data) long bitrate = -1; #if (LIBAVFORMAT_VERSION_INT > ((51<<16)+(43<<8)+0)) /* ape codec returns silly numbers */ - if (priv->codec->id == CODEC_ID_APE) + if (priv->codec->id == AV_CODEC_ID_APE) return -1; #endif if (priv->input->curr_duration > 0) { -- 2.30.2