aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-03-27 16:49:29 +0100
committerAnton Khirnov <anton@khirnov.net>2013-04-11 10:49:09 +0200
commitf22dd3e134527d3290bad749489583b851e1c6a5 (patch)
treec49a5f7e58c4d5efcca7632c6d19fe510bba3935
parent94b4e2341e6442ca3008cff81dd5842a147c0b9e (diff)
ffmpeg decoder plugin: refactor the decoding functions
Move some variables shared between multiple functions to a struct so the functions don't need too many parameters. Move initializing the decoder into a separate function to improve readability and reduce cleanup code duplication.
-rw-r--r--src/decoder/FfmpegDecoderPlugin.cxx206
1 files changed, 103 insertions, 103 deletions
diff --git a/src/decoder/FfmpegDecoderPlugin.cxx b/src/decoder/FfmpegDecoderPlugin.cxx
index 3f3e8a43..a3a98a22 100644
--- a/src/decoder/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/FfmpegDecoderPlugin.cxx
@@ -266,16 +266,22 @@ copy_interleave_frame(const AVCodecContext *codec_context,
}
#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,
- const AVPacket *packet,
- AVCodecContext *codec_context,
- const AVRational *time_base,
- AVFrame *frame)
+ struct ffmpeg_decoder_context *dec,
+ const AVPacket *packet)
{
if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE)
decoder_timestamp(decoder,
- time_from_ffmpeg(packet->pts, *time_base));
+ time_from_ffmpeg(packet->pts, dec->time_base));
AVPacket packet2 = *packet;
@@ -295,12 +301,12 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
int audio_size = buffer_size;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,25,0)
int got_frame = 0;
- int len = avcodec_decode_audio4(codec_context,
- frame, &got_frame,
+ int len = avcodec_decode_audio4(dec->avctx,
+ dec->frame, &got_frame,
&packet2);
if (len >= 0 && got_frame) {
- audio_size = copy_interleave_frame(codec_context,
- frame,
+ audio_size = copy_interleave_frame(dec->avctx,
+ dec->frame,
aligned_buffer,
buffer_size);
if (audio_size < 0)
@@ -308,7 +314,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
} else if (len >= 0)
len = -1;
#else
- int len = avcodec_decode_audio3(codec_context,
+ int len = avcodec_decode_audio3(dec->avctx,
aligned_buffer, &audio_size,
&packet2);
#endif
@@ -327,7 +333,7 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
cmd = decoder_data(decoder, is,
aligned_buffer, audio_size,
- codec_context->bit_rate / 1000);
+ dec->avctx->bit_rate / 1000);
}
return cmd;
}
@@ -403,6 +409,80 @@ ffmpeg_probe(struct decoder *decoder, struct input_stream *is)
return format;
}
+static int init_decoder(struct ffmpeg_decoder_context *dec,
+ AVFormatContext *fmtctx)
+{
+ int audio_stream = ffmpeg_find_audio_stream(fmtctx);
+ if (audio_stream == -1) {
+ g_warning("No audio stream inside\n");
+ return -1;
+ }
+
+ memset(dec, 0, sizeof(dec));
+ dec->st = fmtctx->streams[audio_stream];
+
+ dec->time_base = dec->st->time_base;
+ dec->avctx = dec->st->codec;
+ if (dec->avctx->codec_name[0] != 0)
+ g_debug("codec '%s'", dec->avctx->codec_name);
+
+ AVCodec *codec = avcodec_find_decoder(dec->avctx->codec_id);
+
+ if (!codec) {
+ g_warning("Unsupported audio codec\n");
+ return -1;
+ }
+
+ const enum sample_format sample_format =
+ ffmpeg_sample_format(dec->avctx->sample_fmt);
+ if (sample_format == SAMPLE_FORMAT_UNDEFINED)
+ return -1;
+
+ GError *error = NULL;
+ if (!audio_format_init_checked(&dec->audio_format,
+ dec->avctx->sample_rate,
+ sample_format,
+ dec->avctx->channels, &error)) {
+ g_warning("%s", error->message);
+ g_error_free(error);
+ return -1;
+ }
+
+ dec->frame = avcodec_alloc_frame();
+ if (!dec->frame) {
+ g_warning("Could not allocate frame\n");
+ return -1;
+ }
+
+ /* 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
+ reverted later by avcodec_decode_audio3() */
+
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,6,0)
+ const int open_result = avcodec_open2(dec->avctx, codec, NULL);
+#else
+ const int open_result = avcodec_open(dec->avctx, codec);
+#endif
+ if (open_result < 0) {
+ g_warning("Could not open codec\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void uninit_decoder(struct ffmpeg_decoder_context *dec)
+{
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
+ avcodec_free_frame(&dec->frame);
+#else
+ av_freep(&dec->frame);
+#endif
+
+ avcodec_close(dec->avctx);
+}
+
static void
ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
{
@@ -447,71 +527,10 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
return;
}
- int audio_stream = ffmpeg_find_audio_stream(format_context);
- if (audio_stream == -1) {
- g_warning("No audio stream inside\n");
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
- avformat_close_input(&format_context);
-#else
- av_close_input_stream(format_context);
-#endif
- mpd_ffmpeg_stream_close(stream);
- return;
- }
-
- AVStream *av_stream = format_context->streams[audio_stream];
-
- AVCodecContext *codec_context = av_stream->codec;
- if (codec_context->codec_name[0] != 0)
- g_debug("codec '%s'", codec_context->codec_name);
-
- AVCodec *codec = avcodec_find_decoder(codec_context->codec_id);
-
- if (!codec) {
- g_warning("Unsupported audio codec\n");
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
- avformat_close_input(&format_context);
-#else
- av_close_input_stream(format_context);
-#endif
- mpd_ffmpeg_stream_close(stream);
- return;
- }
-
- const enum sample_format sample_format =
- ffmpeg_sample_format(codec_context->sample_fmt);
- if (sample_format == SAMPLE_FORMAT_UNDEFINED)
- return;
-
- GError *error = NULL;
- struct audio_format audio_format;
- if (!audio_format_init_checked(&audio_format,
- codec_context->sample_rate,
- sample_format,
- codec_context->channels, &error)) {
- g_warning("%s", error->message);
- g_error_free(error);
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
- avformat_close_input(&format_context);
-#else
- av_close_input_stream(format_context);
-#endif
- mpd_ffmpeg_stream_close(stream);
- return;
- }
-
- /* 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
- reverted later by avcodec_decode_audio3() */
-
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,6,0)
- const int open_result = avcodec_open2(codec_context, codec, NULL);
-#else
- const int open_result = avcodec_open(codec_context, codec);
-#endif
- if (open_result < 0) {
- g_warning("Could not open codec\n");
+ struct ffmpeg_decoder_context dec;
+ int res = init_decoder(&dec, format_context);
+ if (res < 0) {
+ uninit_decoder(&dec);
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
avformat_close_input(&format_context);
#else
@@ -525,21 +544,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
? format_context->duration / AV_TIME_BASE
: 0;
- decoder_initialized(decoder, &audio_format,
+ decoder_initialized(decoder, &dec.audio_format,
input->seekable, total_time);
- AVFrame *frame = avcodec_alloc_frame();
- if (!frame) {
- g_warning("Could not allocate frame\n");
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
- avformat_close_input(&format_context);
-#else
- av_close_input_stream(format_context);
-#endif
- mpd_ffmpeg_stream_close(stream);
- return;
- }
-
enum decoder_command cmd;
do {
AVPacket packet;
@@ -547,11 +554,9 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
/* end of file */
break;
- if (packet.stream_index == audio_stream)
- cmd = ffmpeg_send_packet(decoder, input,
- &packet, codec_context,
- &av_stream->time_base,
- frame);
+ if (packet.stream_index == dec.st->index)
+ cmd = ffmpeg_send_packet(decoder, input, &dec,
+ &packet);
else
cmd = decoder_get_command(decoder);
@@ -560,25 +565,20 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
if (cmd == DECODE_COMMAND_SEEK) {
int64_t where =
time_to_ffmpeg(decoder_seek_where(decoder),
- av_stream->time_base);
+ dec.st->time_base);
- if (av_seek_frame(format_context, audio_stream, where,
+ if (av_seek_frame(format_context, dec.st->index, where,
AV_TIME_BASE) < 0)
decoder_seek_error(decoder);
else {
- avcodec_flush_buffers(codec_context);
+ avcodec_flush_buffers(dec.avctx);
decoder_command_finished(decoder);
}
}
} while (cmd != DECODE_COMMAND_STOP);
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
- avcodec_free_frame(&frame);
-#else
- av_freep(&frame);
-#endif
+ uninit_decoder(&dec);
- avcodec_close(codec_context);
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0)
avformat_close_input(&format_context);
#else