aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/decoder/FfmpegDecoderPlugin.cxx103
1 files changed, 43 insertions, 60 deletions
diff --git a/src/decoder/FfmpegDecoderPlugin.cxx b/src/decoder/FfmpegDecoderPlugin.cxx
index 50b39d21..78720ad8 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;
@@ -418,7 +391,7 @@ static int init_decoder(struct ffmpeg_decoder_context *dec,
return -1;
}
- memset(dec, 0, sizeof(dec));
+ memset(dec, 0, sizeof(*dec));
dec->st = fmtctx->streams[audio_stream];
dec->time_base = dec->st->time_base;
@@ -453,6 +426,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
@@ -479,6 +461,7 @@ static void uninit_decoder(struct ffmpeg_decoder_context *dec)
av_freep(&dec->frame);
#endif
+ av_freep(&dec->buf);
avcodec_close(dec->avctx);
}