From c25b464f3730dbc2e09560404e6ed8b75188753a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 18 Dec 2014 21:28:50 +0100 Subject: [PATCH] decoder/ffmpeg: move code to class FfmpegBuffer --- Makefile.am | 1 + src/decoder/plugins/FfmpegDecoderPlugin.cxx | 27 +++----- src/lib/ffmpeg/Buffer.hxx | 72 +++++++++++++++++++++ 3 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 src/lib/ffmpeg/Buffer.hxx diff --git a/Makefile.am b/Makefile.am index ff2d1fbf8..ec01fd845 100644 --- a/Makefile.am +++ b/Makefile.am @@ -799,6 +799,7 @@ endif if HAVE_FFMPEG noinst_LIBRARIES += libffmpeg.a libffmpeg_a_SOURCES = \ + src/lib/ffmpeg/Buffer.hxx \ src/lib/ffmpeg/LogError.cxx src/lib/ffmpeg/LogError.hxx \ src/lib/ffmpeg/Error.cxx src/lib/ffmpeg/Error.hxx \ src/lib/ffmpeg/Domain.cxx src/lib/ffmpeg/Domain.hxx diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 1743ec621..95aa2905d 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/TagHandler.hxx" @@ -281,7 +282,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 = @@ -294,17 +295,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(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, @@ -356,7 +351,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is, const AVStream &stream, AVFrame *frame, uint64_t min_frame, size_t pcm_frame_size, - uint8_t **buffer, int *buffer_size) + FfmpegBuffer &buffer) { size_t skip_bytes = 0; @@ -390,7 +385,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 */ @@ -619,8 +614,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) return; } - uint8_t *interleaved_buffer = nullptr; - int interleaved_buffer_size = 0; + FfmpegBuffer interleaved_buffer; uint64_t min_frame = 0; @@ -638,7 +632,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input) *av_stream, frame, min_frame, audio_format.GetFrameSize(), - &interleaved_buffer, &interleaved_buffer_size); + interleaved_buffer); min_frame = 0; } else cmd = decoder_get_command(decoder); @@ -677,7 +671,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..50a702f59 --- /dev/null +++ b/src/lib/ffmpeg/Buffer.hxx @@ -0,0 +1,72 @@ +/* + * 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 + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0) +#define HAVE_AV_FAST_MALLOC +#else +#include +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0) +#define HAVE_AV_FAST_MALLOC +#endif +#endif +} + +#include + +/* 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 + T *GetT(size_t n) { + return (T *)Get(n * sizeof(T)); + } +}; + +#endif