diff options
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/ffmpeg_decoder_plugin.c | 115 |
1 files changed, 111 insertions, 4 deletions
diff --git a/src/decoder/ffmpeg_decoder_plugin.c b/src/decoder/ffmpeg_decoder_plugin.c index 5dc95ccf8..05a59c1e0 100644 --- a/src/decoder/ffmpeg_decoder_plugin.c +++ b/src/decoder/ffmpeg_decoder_plugin.c @@ -36,6 +36,7 @@ #include <libavformat/avformat.h> #include <libavformat/avio.h> #include <libavutil/log.h> +#include <libavutil/mathematics.h> #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "ffmpeg" @@ -196,6 +197,7 @@ 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 @@ -210,6 +212,7 @@ align16(void *p, size_t *length_p) *length_p -= add; return (char *)p + add; } +#endif G_GNUC_CONST static double @@ -229,6 +232,40 @@ time_to_ffmpeg(double t, const AVRational time_base) time_base); } +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,25,0) +/** + * 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) +{ + 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) { + for (int i = 0, channels = codec_context->channels; + i < channels; i++) { + memcpy(buffer, frame->extended_data[i], plane_size); + buffer += plane_size; + } + } else { + memcpy(buffer, frame->extended_data[0], data_size); + } + + return data_size; +} +#endif + static enum decoder_command ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, const AVPacket *packet, @@ -246,9 +283,15 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, int packet_size = packet->size; #endif +#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 = align16(audio_buf, &buffer_size); +#endif enum decoder_command cmd = DECODE_COMMAND_NONE; while ( @@ -259,7 +302,22 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, #endif cmd == DECODE_COMMAND_NONE) { int audio_size = buffer_size; -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,25,0) +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,25,0) + AVFrame frame; + int got_frame = 0; + int len = avcodec_decode_audio4(codec_context, + &frame, &got_frame, + &packet2); + if (len >= 0 && got_frame) { + audio_size = copy_interleave_frame(codec_context, + &frame, + aligned_buffer, + buffer_size); + if (audio_size < 0) + len = audio_size; + } else if (len >= 0) + len = -1; +#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52,25,0) int len = avcodec_decode_audio3(codec_context, aligned_buffer, &audio_size, &packet2); @@ -370,9 +428,19 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) return; } - if (av_find_stream_info(format_context)<0) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,2,0) + const int find_result = + avformat_find_stream_info(format_context, NULL); +#else + const int find_result = av_find_stream_info(format_context); +#endif + if (find_result < 0) { g_warning("Couldn't find stream info\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; } @@ -380,7 +448,11 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) 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; } @@ -395,7 +467,11 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) 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; } @@ -408,7 +484,11 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) 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; } @@ -418,9 +498,18 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) values into AVCodecContext.channels - a change that will be reverted later by avcodec_decode_audio3() */ - if (avcodec_open(codec_context, codec)<0) { +#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"); +#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; } @@ -469,7 +558,11 @@ ffmpeg_decode(struct decoder *decoder, struct input_stream *input) } while (cmd != DECODE_COMMAND_STOP); avcodec_close(codec_context); +#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); } @@ -542,8 +635,18 @@ ffmpeg_stream_tag(struct input_stream *is) return NULL; } - if (av_find_stream_info(f) < 0) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,2,0) + const int find_result = + avformat_find_stream_info(f, NULL); +#else + const int find_result = av_find_stream_info(f); +#endif + if (find_result < 0) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0) + avformat_close_input(&f); +#else av_close_input_stream(f); +#endif mpd_ffmpeg_stream_close(stream); return NULL; } @@ -565,7 +668,11 @@ ffmpeg_stream_tag(struct input_stream *is) ffmpeg_copy_metadata(tag, f->streams[idx]->metadata, ffmpeg_tag_maps[i]); } +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,17,0) + avformat_close_input(&f); +#else av_close_input_stream(f); +#endif mpd_ffmpeg_stream_close(stream); return tag; |