From 2b858b45c26b52cdbf80528b6445248adc8eb7f1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 26 Jan 2014 13:22:26 +0100 Subject: audaspace: use new libavcodec audio encoding API where available --- intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp | 40 +++++++++++++++++++++++++--- intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h | 5 ++++ intern/ffmpeg/ffmpeg_compat.h | 22 +++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp index d35b6d56c69..d8f0d837fec 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp @@ -183,6 +183,20 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, m_input_size = m_codecCtx->frame_size; } +#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 + m_frame = av_frame_alloc(); + if (!m_frame) + AUD_THROW(AUD_ERROR_FFMPEG, codec_error); + m_frame->linesize[0] = m_input_size * samplesize; + m_frame->format = m_codecCtx->sample_fmt; +# ifdef FFMPEG_HAVE_AVFRAME_SAMPLE_RATE + m_frame->sample_rate = m_codecCtx->sample_rate; +# endif +# ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT + m_frame->channel_layout = m_codecCtx->channel_layout; +# endif +#endif + try { if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE)) @@ -229,6 +243,10 @@ AUD_FFMPEGWriter::~AUD_FFMPEGWriter() av_freep(&m_formatCtx->streams[0]->codec); av_freep(&m_formatCtx->streams[0]); +#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 + av_frame_free(&m_frame); +#endif + avio_close(m_formatCtx->pb); av_free(m_formatCtx); } @@ -245,20 +263,34 @@ AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const void AUD_FFMPEGWriter::encode(sample_t* data) { - sample_t* outbuf = m_output_buffer.getBuffer(); - // convert first if(m_input_size) m_convert(reinterpret_cast(data), reinterpret_cast(data), m_input_size * m_specs.channels); - AVPacket packet; + AVPacket packet = { 0 }; av_init_packet(&packet); + +#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 + int got_output, ret; + + m_frame->data[0] = reinterpret_cast(data); + ret = avcodec_encode_audio2(m_codecCtx, &packet, m_frame, &got_output); + if (ret < 0) + AUD_THROW(AUD_ERROR_FFMPEG, codec_error); + + if (!got_output) + return; +#else + sample_t* outbuf = m_output_buffer.getBuffer(); + packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast(outbuf), m_output_buffer.getSize(), reinterpret_cast(data)); if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE) packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base); packet.flags |= AV_PKT_FLAG_KEY; - packet.stream_index = m_stream->index; packet.data = reinterpret_cast(outbuf); +#endif + + packet.stream_index = m_stream->index; if(av_interleaved_write_frame(m_formatCtx, &packet)) AUD_THROW(AUD_ERROR_FFMPEG, write_error); diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h index 17830308fd5..310f69258ea 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h @@ -77,6 +77,11 @@ private: */ AVStream* m_stream; + /** + * Frame sent to the encoder. + */ + AVFrame *m_frame; + /** * The input buffer for the format converted data before encoding. */ diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 91db329592d..58cf62ab623 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -90,6 +90,10 @@ #define FFMPEG_HAVE_DECODE_AUDIO4 #endif +#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13)) +#define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE +#endif + #if ((LIBAVUTIL_VERSION_MAJOR > 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 21)) #define FFMPEG_FFV1_ALPHA_SUPPORTED #define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED @@ -267,6 +271,10 @@ void avcodec_free_frame(AVFrame **frame) } #endif +#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13)) +#define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE +#endif + #if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13)) #define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT #endif @@ -397,4 +405,18 @@ void avformat_close_input(AVFormatContext **ctx) } #endif +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) +FFMPEG_INLINE +AVFrame *av_frame_alloc(void) +{ + return avcodec_alloc_frame(); +} + +FFMPEG_INLINE +void av_frame_free(AVFrame **frame) +{ + av_freep(frame); +} +#endif + #endif -- cgit v1.2.3