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.
---
 src/decoder/FfmpegDecoderPlugin.cxx |  205 +++++++++++++++++------------------
 1 file changed, 102 insertions(+), 103 deletions(-)

diff --git a/src/decoder/FfmpegDecoderPlugin.cxx 
b/src/decoder/FfmpegDecoderPlugin.cxx
index 3f3e8a4..71ba966 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,79 @@ 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;
+       }
+
+       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 +526,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 = { NULL };
+       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 +543,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 +553,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 +564,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
-- 
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