diff options
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/ffmpeg_decoder_plugin.c | 183 |
1 files changed, 67 insertions, 116 deletions
diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c index 6e4119136..369e8d426 100644 --- a/src/decoder/ffmpeg_decoder_plugin.c +++ b/src/decoder/ffmpeg_decoder_plugin.c @@ -45,14 +45,6 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "ffmpeg" -struct ffmpeg_context { - int audio_stream; - AVFormatContext *format_context; - AVCodecContext *codec_context; - struct decoder *decoder; - struct input_stream *input; -}; - struct ffmpeg_stream { /** hack - see url_to_struct() */ char url[64]; @@ -160,82 +152,6 @@ append_uri_suffix(struct ffmpeg_stream *stream, const char *uri) g_free(base); } -static bool -ffmpeg_helper(struct input_stream *input, - bool (*callback)(struct ffmpeg_context *ctx), - struct ffmpeg_context *ctx) -{ - AVFormatContext *format_context; - AVCodecContext *codec_context; - AVCodec *codec; - int audio_stream; - struct ffmpeg_stream stream = { - .url = "mpd://X", /* only the mpd:// prefix matters */ - }; - bool ret; - - if (input->uri != NULL) - append_uri_suffix(&stream, input->uri); - - stream.input = input; - if (ctx && ctx->decoder) { - stream.decoder = ctx->decoder; //are we in decoding loop ? - } else { - stream.decoder = NULL; - } - - //ffmpeg works with ours "fileops" helper - if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) { - g_warning("Open failed\n"); - return false; - } - - if (av_find_stream_info(format_context)<0) { - g_warning("Couldn't find stream info\n"); - av_close_input_file(format_context); - return false; - } - - audio_stream = ffmpeg_find_audio_stream(format_context); - if (audio_stream == -1) { - g_warning("No audio stream inside\n"); - av_close_input_file(format_context); - return false; - } - - codec_context = format_context->streams[audio_stream]->codec; - if (codec_context->codec_name[0] != 0) - g_debug("codec '%s'", codec_context->codec_name); - - codec = avcodec_find_decoder(codec_context->codec_id); - - if (!codec) { - g_warning("Unsupported audio codec\n"); - av_close_input_file(format_context); - return false; - } - - if (avcodec_open(codec_context, codec)<0) { - g_warning("Could not open codec\n"); - av_close_input_file(format_context); - return false; - } - - if (callback) { - ctx->audio_stream = audio_stream; - ctx->format_context = format_context; - ctx->codec_context = codec_context; - - ret = callback(ctx); - } else - ret = true; - - avcodec_close(codec_context); - av_close_input_file(format_context); - - return ret; -} - /** * On some platforms, libavcodec wants the output buffer aligned to 16 * bytes (because it uses SSE/Altivec internally). This function @@ -321,46 +237,91 @@ ffmpeg_sample_format(G_GNUC_UNUSED const AVCodecContext *codec_context) #endif } -static bool -ffmpeg_decode_internal(struct ffmpeg_context *ctx) +static void +ffmpeg_decode(struct decoder *decoder, struct input_stream *input) { - GError *error = NULL; - struct decoder *decoder = ctx->decoder; - AVCodecContext *codec_context = ctx->codec_context; - AVFormatContext *format_context = ctx->format_context; - AVPacket packet; - struct audio_format audio_format; - enum decoder_command cmd; - int total_time; + struct ffmpeg_stream stream = { + .url = "mpd://X", /* only the mpd:// prefix matters */ + .decoder = decoder, + .input = input, + }; + AVFormatContext *format_context; + AVCodecContext *codec_context; + AVCodec *codec; + int audio_stream; + + if (input->uri != NULL) + append_uri_suffix(&stream, input->uri); + + //ffmpeg works with ours "fileops" helper + if (av_open_input_file(&format_context, stream.url, NULL, 0, NULL) != 0) { + g_warning("Open failed\n"); + av_close_input_file(format_context); + return; + } + + if (av_find_stream_info(format_context)<0) { + g_warning("Couldn't find stream info\n"); + av_close_input_file(format_context); + return; + } - total_time = 0; + audio_stream = ffmpeg_find_audio_stream(format_context); + if (audio_stream == -1) { + g_warning("No audio stream inside\n"); + av_close_input_file(format_context); + return; + } + codec_context = format_context->streams[audio_stream]->codec; + if (codec_context->codec_name[0] != 0) + g_debug("codec '%s'", codec_context->codec_name); + + codec = avcodec_find_decoder(codec_context->codec_id); + + if (!codec) { + g_warning("Unsupported audio codec\n"); + av_close_input_file(format_context); + return; + } + + if (avcodec_open(codec_context, codec)<0) { + g_warning("Could not open codec\n"); + av_close_input_file(format_context); + return; + } + + GError *error = NULL; + struct audio_format audio_format; if (!audio_format_init_checked(&audio_format, codec_context->sample_rate, ffmpeg_sample_format(codec_context), codec_context->channels, &error)) { g_warning("%s", error->message); g_error_free(error); - return false; + avcodec_close(codec_context); + av_close_input_file(format_context); + return; } - //there is some problem with this on some demux (mp3 at least) - if (format_context->duration != (int64_t)AV_NOPTS_VALUE) { - total_time = format_context->duration / AV_TIME_BASE; - } + int total_time = format_context->duration != (int64_t)AV_NOPTS_VALUE + ? format_context->duration / AV_TIME_BASE + : 0; decoder_initialized(decoder, &audio_format, - ctx->input->seekable, total_time); + input->seekable, total_time); + enum decoder_command cmd; do { + AVPacket packet; if (av_read_frame(format_context, &packet) < 0) /* end of file */ break; - if (packet.stream_index == ctx->audio_stream) - cmd = ffmpeg_send_packet(decoder, ctx->input, + if (packet.stream_index == audio_stream) + cmd = ffmpeg_send_packet(decoder, input, &packet, codec_context, - &format_context->streams[ctx->audio_stream]->time_base); + &format_context->streams[audio_stream]->time_base); else cmd = decoder_get_command(decoder); @@ -377,18 +338,8 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) } } while (cmd != DECODE_COMMAND_STOP); - return true; -} - -static void -ffmpeg_decode(struct decoder *decoder, struct input_stream *input) -{ - struct ffmpeg_context ctx; - - ctx.input = input; - ctx.decoder = decoder; - - ffmpeg_helper(input, ffmpeg_decode_internal, &ctx); + avcodec_close(codec_context); + av_close_input_file(format_context); } #if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0) |