diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/decoder/plugins/FfmpegDecoderPlugin.cxx | 27 | ||||
-rw-r--r-- | src/lib/ffmpeg/Buffer.hxx | 73 |
2 files changed, 83 insertions, 17 deletions
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 60c49800d..c0eadfb55 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -24,6 +24,7 @@ #include "FfmpegDecoderPlugin.hxx" #include "lib/ffmpeg/Domain.hxx" #include "lib/ffmpeg/LogError.hxx" +#include "lib/ffmpeg/Buffer.hxx" #include "../DecoderAPI.hxx" #include "FfmpegMetaData.hxx" #include "tag/TagBuilder.hxx" @@ -275,7 +276,7 @@ static int copy_interleave_frame(const AVCodecContext *codec_context, const AVFrame *frame, uint8_t **output_buffer, - uint8_t **global_buffer, int *global_buffer_size) + FfmpegBuffer &global_buffer) { int plane_size; const int data_size = @@ -288,17 +289,11 @@ copy_interleave_frame(const AVCodecContext *codec_context, if (av_sample_fmt_is_planar(codec_context->sample_fmt) && codec_context->channels > 1) { - if(*global_buffer_size < data_size) { - av_freep(global_buffer); + *output_buffer = global_buffer.GetT<uint8_t>(data_size); + if (*output_buffer == nullptr) + /* Not enough memory - shouldn't happen */ + return AVERROR(ENOMEM); - *global_buffer = (uint8_t*)av_malloc(data_size); - - if (!*global_buffer) - /* Not enough memory - shouldn't happen */ - return AVERROR(ENOMEM); - *global_buffer_size = data_size; - } - *output_buffer = *global_buffer; copy_interleave_frame2(*output_buffer, frame->extended_data, frame->nb_samples, codec_context->channels, @@ -316,7 +311,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is, AVCodecContext *codec_context, const AVStream *stream, AVFrame *frame, - uint8_t **buffer, int *buffer_size) + FfmpegBuffer &buffer) { if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE) { auto start = start_time_fallback(*stream); @@ -346,7 +341,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is, audio_size = copy_interleave_frame(codec_context, frame, &output_buffer, - buffer, buffer_size); + buffer); if (audio_size < 0) { /* this must be a serious error, e.g. OOM */ @@ -667,8 +662,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) return; } - uint8_t *interleaved_buffer = nullptr; - int interleaved_buffer_size = 0; + FfmpegBuffer interleaved_buffer; DecoderCommand cmd; do { @@ -686,7 +680,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) &packet, codec_context, av_stream, frame, - &interleaved_buffer, &interleaved_buffer_size); + interleaved_buffer); else cmd = decoder_get_command(decoder); @@ -715,7 +709,6 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) #else av_freep(&frame); #endif - av_freep(&interleaved_buffer); avcodec_close(codec_context); avformat_close_input(&format_context); diff --git a/src/lib/ffmpeg/Buffer.hxx b/src/lib/ffmpeg/Buffer.hxx new file mode 100644 index 000000000..eab1be8ce --- /dev/null +++ b/src/lib/ffmpeg/Buffer.hxx @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FFMPEG_BUFFER_HXX +#define MPD_FFMPEG_BUFFER_HXX + +extern "C" { +#include <libavutil/avutil.h> + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0) +#define HAVE_AV_FAST_MALLOC +#include <libavutil/mem.h> +#else +#include <libavcodec/avcodec.h> +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0) +#define HAVE_AV_FAST_MALLOC +#endif +#endif +} + +#include <stddef.h> + +/* suppress the ffmpeg compatibility macro */ +#ifdef SampleFormat +#undef SampleFormat +#endif + +class FfmpegBuffer { + void *data; + unsigned size; + +public: + FfmpegBuffer():data(nullptr), size(0) {} + + ~FfmpegBuffer() { + av_free(data); + } + + void *Get(size_t min_size) { +#ifdef HAVE_AV_FAST_MALLOC + av_fast_malloc(&data, &size, min_size); +#else + void *new_data = av_fast_realloc(data, &size, min_size); + if (new_data == nullptr) + return AVERROR(ENOMEM); + data = new_data; +#endif + return data; + } + + template<typename T> + T *GetT(size_t n) { + return (T *)Get(n * sizeof(T)); + } +}; + +#endif |