From 5ac1b38b4b21959b552c0787e2f86a104624c615 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 28 Feb 2014 15:15:04 +0600 Subject: Support planar sample formats in audio mixdown Now libav-10 should work for output of ac3 container. --- intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp | 29 +++++++++++++++++++++++++++- intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h | 9 ++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'intern/audaspace') diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp index dcacf71a2d3..d30835da4e5 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp @@ -169,6 +169,19 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, if(!codec) AUD_THROW(AUD_ERROR_FFMPEG, codec_error); + if(codec->sample_fmts) { + // Check if the prefered sample format for this codec is supported. + const enum AVSampleFormat *p = codec->sample_fmts; + for(; *p != -1; p++) { + if(*p == m_stream->codec->sample_fmt) + break; + } + if(*p == -1) { + // Sample format incompatible with codec. Defaulting to a format known to work. + m_stream->codec->sample_fmt = codec->sample_fmts[0]; + } + } + if(avcodec_open2(m_codecCtx, codec, NULL)) AUD_THROW(AUD_ERROR_FFMPEG, codec_error); @@ -199,8 +212,11 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, # ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT m_frame->channel_layout = m_codecCtx->channel_layout; # endif - m_audio_sample_size = av_get_bytes_per_sample(m_codecCtx->sample_fmt); + m_sample_size = av_get_bytes_per_sample(m_codecCtx->sample_fmt); m_frame_pts = 0; + m_deinterleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt); + if(m_deinterleave) + m_deinterleave_buffer.resize(m_input_size * m_codecCtx->channels * m_sample_size); #endif try @@ -284,6 +300,17 @@ void AUD_FFMPEGWriter::encode(sample_t* data) m_frame->channel_layout = m_codecCtx->channel_layout; #endif + if(m_deinterleave) { + for(int channel = 0; channel < m_codecCtx->channels; channel++) { + for(int i = 0; i < m_frame->nb_samples; i++) { + memcpy(reinterpret_cast(m_deinterleave_buffer.getBuffer()) + (i + channel * m_frame->nb_samples) * m_sample_size, + reinterpret_cast(data) + (m_codecCtx->channels * i + channel) * m_sample_size, m_sample_size); + } + } + + data = m_deinterleave_buffer.getBuffer(); + } + avcodec_fill_audio_frame(m_frame, m_codecCtx->channels, m_codecCtx->sample_fmt, reinterpret_cast(data), m_frame->nb_samples * av_get_bytes_per_sample(m_codecCtx->sample_fmt) * m_codecCtx->channels, 1); diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h index 743d885fca8..492aa35ff12 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h @@ -90,7 +90,14 @@ private: /** * Number of bytes per sample. */ - int m_audio_sample_size; + int m_sample_size; + + /** + * Need to de-interleave audio for planar sample formats. + */ + bool m_deinterleave; + + AUD_Buffer m_deinterleave_buffer; /** * The input buffer for the format converted data before encoding. -- cgit v1.2.3