It is not meant to be used with the new audio decoding API, decoded
audio frames can now be arbitrarily large depending on the decoder and
the input packet size. Instead dynamically allocate the interleaving
buffer to be as large as needed.

Fixes build with libavcodec 55.

With the old decoding API, use the av_fast_malloc() function to allocate
the aligned decoding buffer instead of doing manual alignment.
---
 src/decoder/FfmpegDecoderPlugin.cxx |  101 +++++++++++++++--------------------
 1 file changed, 42 insertions(+), 59 deletions(-)

diff --git a/src/decoder/FfmpegDecoderPlugin.cxx 
b/src/decoder/FfmpegDecoderPlugin.cxx
index dc34ac6..87b855b 100644
--- a/src/decoder/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/FfmpegDecoderPlugin.cxx
@@ -55,6 +55,19 @@ extern "C" {
 #undef G_LOG_DOMAIN
 #define G_LOG_DOMAIN "ffmpeg"
 
+struct ffmpeg_decoder_context {
+       AVStream *st;
+       AVCodecContext *avctx;
+       AVFrame *frame;
+       AVRational time_base;
+       struct audio_format audio_format;
+
+       /* a decoding buffer for old decoding API or
+        * for interleaved data */
+       void *buf;
+       unsigned int buf_size;
+};
+
 static GLogLevelFlags
 level_ffmpeg_to_glib(int level)
 {
@@ -183,23 +196,6 @@ ffmpeg_find_audio_stream(const AVFormatContext 
*format_context)
        return -1;
 }
 
-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53,25,0)
-/**
- * On some platforms, libavcodec wants the output buffer aligned to 16
- * bytes (because it uses SSE/Altivec internally).  This function
- * returns the aligned version of the specified buffer, and corrects
- * the buffer size.
- */
-static void *
-align16(void *p, size_t *length_p)
-{
-       unsigned add = 16 - (size_t)p % 16;
-
-       *length_p -= add;
-       return (char *)p + add;
-}
-#endif
-
 G_GNUC_CONST
 static double
 time_from_ffmpeg(int64_t t, const AVRational time_base)
@@ -238,42 +234,32 @@ copy_interleave_frame2(uint8_t *dest, uint8_t **src,
  * Copy PCM data from a AVFrame to an interleaved buffer.
  */
 static int
-copy_interleave_frame(const AVCodecContext *codec_context,
-                     const AVFrame *frame,
-                     uint8_t *buffer, size_t buffer_size)
+copy_interleave_frame(struct ffmpeg_decoder_context *dec)
 {
        int plane_size;
        const int data_size =
                av_samples_get_buffer_size(&plane_size,
-                                          codec_context->channels,
-                                          frame->nb_samples,
-                                          codec_context->sample_fmt, 1);
-       if (buffer_size < (size_t)data_size)
-               /* buffer is too small - shouldn't happen */
-               return AVERROR(EINVAL);
-
-       if (av_sample_fmt_is_planar(codec_context->sample_fmt) &&
-           codec_context->channels > 1) {
-               copy_interleave_frame2(buffer, frame->extended_data,
-                                      frame->nb_samples,
-                                      codec_context->channels,
-                                      
av_get_bytes_per_sample(codec_context->sample_fmt));
+                                          dec->avctx->channels,
+                                          dec->frame->nb_samples,
+                                          dec->avctx->sample_fmt, 1);
+       av_fast_malloc(&dec->buf, &dec->buf_size, data_size);
+       if (!dec->buf)
+               return AVERROR(ENOMEM);
+
+       if (av_sample_fmt_is_planar(dec->avctx->sample_fmt) &&
+           dec->avctx->channels > 1) {
+               copy_interleave_frame2((uint8_t*)dec->buf, 
dec->frame->extended_data,
+                                      dec->frame->nb_samples,
+                                      dec->avctx->channels,
+                                      
av_get_bytes_per_sample(dec->avctx->sample_fmt));
        } else {
-               memcpy(buffer, frame->extended_data[0], data_size);
+               memcpy(dec->buf, dec->frame->extended_data[0], data_size);
        }
 
        return data_size;
 }
 #endif
 
-struct ffmpeg_decoder_context {
-       AVStream *st;
-       AVCodecContext *avctx;
-       AVFrame *frame;
-       AVRational time_base;
-       struct audio_format audio_format;
-};
-
 static enum decoder_command
 ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
                   struct ffmpeg_decoder_context *dec,
@@ -285,37 +271,24 @@ ffmpeg_send_packet(struct decoder *decoder, struct 
input_stream *is,
 
        AVPacket packet2 = *packet;
 
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,25,0)
-       uint8_t aligned_buffer[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16];
-       const size_t buffer_size = sizeof(aligned_buffer);
-#else
-       /* libavcodec < 0.8 needs an aligned buffer */
-       uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16];
-       size_t buffer_size = sizeof(audio_buf);
-       int16_t *aligned_buffer = (int16_t *)align16(audio_buf, &buffer_size);
-#endif
-
        enum decoder_command cmd = DECODE_COMMAND_NONE;
        while (packet2.size > 0 &&
               cmd == DECODE_COMMAND_NONE) {
-               int audio_size = buffer_size;
+               int audio_size = dec->buf_size;
 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,25,0)
                int got_frame = 0;
                int len = avcodec_decode_audio4(dec->avctx,
                                                dec->frame, &got_frame,
                                                &packet2);
                if (len >= 0 && got_frame) {
-                       audio_size = copy_interleave_frame(dec->avctx,
-                                                          dec->frame,
-                                                          aligned_buffer,
-                                                          buffer_size);
+                       audio_size = copy_interleave_frame(dec);
                        if (audio_size < 0)
                                len = audio_size;
                } else if (len >= 0)
                        len = -1;
 #else
                int len = avcodec_decode_audio3(dec->avctx,
-                                               aligned_buffer, &audio_size,
+                                               (int16_t*)dec->buf, &audio_size,
                                                &packet2);
 #endif
 
@@ -332,7 +305,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct 
input_stream *is,
                        continue;
 
                cmd = decoder_data(decoder, is,
-                                  aligned_buffer, audio_size,
+                                  dec->buf, audio_size,
                                   dec->avctx->bit_rate / 1000);
        }
        return cmd;
@@ -452,6 +425,15 @@ static int init_decoder(struct ffmpeg_decoder_context *dec,
                return -1;
        }
 
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 25, 0)
+       av_fast_malloc(&dec->buf, &dec->buf_size,
+                                  (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2);
+       if (!dec->buf) {
+               g_warning("Could not allocate decoding buffer\n");
+               return -1;
+       }
+#endif
+
        /* the audio format must be read from AVCodecContext by now,
           because avcodec_open() has been demonstrated to fill bogus
           values into AVCodecContext.channels - a change that will be
@@ -478,6 +460,7 @@ static void uninit_decoder(struct ffmpeg_decoder_context 
*dec)
        av_freep(&dec->frame);
 #endif
 
+       av_freep(&dec->buf);
        avcodec_close(dec->avctx);
 }
 
-- 
1.7.10.4


------------------------------------------------------------------------------
Own the Future-Intel&reg; Level Up Game Demo Contest 2013
Rise to greatness in Intel's independent game demo contest.
Compete for recognition, cash, and the chance to get your game 
on Steam. $5K grand prize plus 10 genre and skill prizes. 
Submit your demo by 6/6/13. http://p.sf.net/sfu/intel_levelupd2d
_______________________________________________
Musicpd-dev-team mailing list
Musicpd-dev-team@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/musicpd-dev-team

Reply via email to