decoder/ffmpeg: merged ffmpeg_helper() into ffmpeg_decode()
This commit is contained in:
@@ -45,14 +45,6 @@
|
|||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "ffmpeg"
|
#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 {
|
struct ffmpeg_stream {
|
||||||
/** hack - see url_to_struct() */
|
/** hack - see url_to_struct() */
|
||||||
char url[64];
|
char url[64];
|
||||||
@@ -160,82 +152,6 @@ append_uri_suffix(struct ffmpeg_stream *stream, const char *uri)
|
|||||||
g_free(base);
|
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
|
* On some platforms, libavcodec wants the output buffer aligned to 16
|
||||||
* bytes (because it uses SSE/Altivec internally). This function
|
* bytes (because it uses SSE/Altivec internally). This function
|
||||||
@@ -321,46 +237,91 @@ ffmpeg_sample_format(G_GNUC_UNUSED const AVCodecContext *codec_context)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
ffmpeg_decode_internal(struct ffmpeg_context *ctx)
|
ffmpeg_decode(struct decoder *decoder, struct input_stream *input)
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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;
|
struct audio_format audio_format;
|
||||||
enum decoder_command cmd;
|
|
||||||
int total_time;
|
|
||||||
|
|
||||||
total_time = 0;
|
|
||||||
|
|
||||||
if (!audio_format_init_checked(&audio_format,
|
if (!audio_format_init_checked(&audio_format,
|
||||||
codec_context->sample_rate,
|
codec_context->sample_rate,
|
||||||
ffmpeg_sample_format(codec_context),
|
ffmpeg_sample_format(codec_context),
|
||||||
codec_context->channels, &error)) {
|
codec_context->channels, &error)) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
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)
|
int total_time = format_context->duration != (int64_t)AV_NOPTS_VALUE
|
||||||
if (format_context->duration != (int64_t)AV_NOPTS_VALUE) {
|
? format_context->duration / AV_TIME_BASE
|
||||||
total_time = format_context->duration / AV_TIME_BASE;
|
: 0;
|
||||||
}
|
|
||||||
|
|
||||||
decoder_initialized(decoder, &audio_format,
|
decoder_initialized(decoder, &audio_format,
|
||||||
ctx->input->seekable, total_time);
|
input->seekable, total_time);
|
||||||
|
|
||||||
|
enum decoder_command cmd;
|
||||||
do {
|
do {
|
||||||
|
AVPacket packet;
|
||||||
if (av_read_frame(format_context, &packet) < 0)
|
if (av_read_frame(format_context, &packet) < 0)
|
||||||
/* end of file */
|
/* end of file */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (packet.stream_index == ctx->audio_stream)
|
if (packet.stream_index == audio_stream)
|
||||||
cmd = ffmpeg_send_packet(decoder, ctx->input,
|
cmd = ffmpeg_send_packet(decoder, input,
|
||||||
&packet, codec_context,
|
&packet, codec_context,
|
||||||
&format_context->streams[ctx->audio_stream]->time_base);
|
&format_context->streams[audio_stream]->time_base);
|
||||||
else
|
else
|
||||||
cmd = decoder_get_command(decoder);
|
cmd = decoder_get_command(decoder);
|
||||||
|
|
||||||
@@ -377,18 +338,8 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
|
|||||||
}
|
}
|
||||||
} while (cmd != DECODE_COMMAND_STOP);
|
} while (cmd != DECODE_COMMAND_STOP);
|
||||||
|
|
||||||
return true;
|
avcodec_close(codec_context);
|
||||||
}
|
av_close_input_file(format_context);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
|
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(31<<8)+0)
|
||||||
|
Reference in New Issue
Block a user