2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #define AC3_ENCODE_BITRATE 640000
22 #define DTS_ENCODE_BITRATE 1411200
24 #include "AEEncoderFFmpeg.h"
25 #include "cores/AudioEngine/Utils/AEUtil.h"
26 #include "utils/log.h"
27 #include "settings/AdvancedSettings.h"
28 #include "settings/Settings.h"
31 CAEEncoderFFmpeg::CAEEncoderFFmpeg():
38 m_SampleRateMul (0.0 ),
40 m_NeedConversion(false),
41 m_ResampBuffer (NULL ),
42 m_ResampBufferSize(0 )
46 CAEEncoderFFmpeg::~CAEEncoderFFmpeg()
49 m_dllAvUtil.av_freep(&m_CodecCtx);
50 m_dllAvUtil.av_freep(&m_ResampBuffer);
52 m_dllSwResample.swr_free(&m_SwrCtx);
55 bool CAEEncoderFFmpeg::IsCompatible(AEAudioFormat format)
61 format.m_dataFormat == m_CurrentFormat.m_dataFormat &&
62 format.m_sampleRate == m_CurrentFormat.m_sampleRate
67 CAEChannelInfo layout;
68 BuildChannelLayout(AV_CH_LAYOUT_5POINT1_BACK, layout); /* hard coded for AC3 & DTS currently */
69 match = (m_CurrentFormat.m_channelLayout == layout);
75 unsigned int CAEEncoderFFmpeg::BuildChannelLayout(const int64_t ffmap, CAEChannelInfo& layout)
77 /* build the channel layout and count the channels */
79 if (ffmap & AV_CH_FRONT_LEFT ) layout += AE_CH_FL ;
80 if (ffmap & AV_CH_FRONT_RIGHT ) layout += AE_CH_FR ;
81 if (ffmap & AV_CH_FRONT_CENTER ) layout += AE_CH_FC ;
82 if (ffmap & AV_CH_LOW_FREQUENCY ) layout += AE_CH_LFE ;
83 if (ffmap & AV_CH_BACK_LEFT ) layout += AE_CH_BL ;
84 if (ffmap & AV_CH_BACK_RIGHT ) layout += AE_CH_BR ;
85 if (ffmap & AV_CH_FRONT_LEFT_OF_CENTER ) layout += AE_CH_FLOC;
86 if (ffmap & AV_CH_FRONT_RIGHT_OF_CENTER) layout += AE_CH_FROC;
87 if (ffmap & AV_CH_BACK_CENTER ) layout += AE_CH_BC ;
88 if (ffmap & AV_CH_SIDE_LEFT ) layout += AE_CH_SL ;
89 if (ffmap & AV_CH_SIDE_RIGHT ) layout += AE_CH_SR ;
90 if (ffmap & AV_CH_TOP_CENTER ) layout += AE_CH_TC ;
91 if (ffmap & AV_CH_TOP_FRONT_LEFT ) layout += AE_CH_TFL ;
92 if (ffmap & AV_CH_TOP_FRONT_CENTER ) layout += AE_CH_TFC ;
93 if (ffmap & AV_CH_TOP_FRONT_RIGHT ) layout += AE_CH_TFR ;
94 if (ffmap & AV_CH_TOP_BACK_LEFT ) layout += AE_CH_TBL ;
95 if (ffmap & AV_CH_TOP_BACK_CENTER ) layout += AE_CH_TBC ;
96 if (ffmap & AV_CH_TOP_BACK_RIGHT ) layout += AE_CH_TBR ;
98 return layout.Count();
101 bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format, bool allow_planar_input)
105 if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load())
108 m_dllAvCodec.avcodec_register_all();
110 bool ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough");
112 AVCodec *codec = NULL;
114 /* the DCA encoder is currently useless for transcode, it creates a 196 kHz DTS-HD like mongrel which is useless for SPDIF */
115 bool dts = CSettings::Get().GetBool("audiooutput.dtspassthrough");
116 if (dts && (!ac3 || g_advancedSettings.m_audioTranscodeTo.Equals("dts")))
119 m_CodecID = AV_CODEC_ID_DTS;
120 m_PackFunc = &CAEPackIEC61937::PackDTS_1024;
121 m_BitRate = DTS_ENCODE_BITRATE;
122 codec = m_dllAvCodec.avcodec_find_encoder(m_CodecID);
126 /* fallback to ac3 if we support it, we might not have DTS support */
130 m_CodecID = AV_CODEC_ID_AC3;
131 m_PackFunc = &CAEPackIEC61937::PackAC3;
132 m_BitRate = AC3_ENCODE_BITRATE;
133 codec = m_dllAvCodec.avcodec_find_encoder(m_CodecID);
136 /* check we got the codec */
140 m_CodecCtx = m_dllAvCodec.avcodec_alloc_context3(codec);
141 m_CodecCtx->bit_rate = m_BitRate;
142 m_CodecCtx->sample_rate = format.m_sampleRate;
143 m_CodecCtx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
145 /* select a suitable data format */
146 if (codec->sample_fmts)
148 bool hasFloat = false;
149 bool hasDouble = false;
153 bool hasFloatP = false;
154 bool hasUnknownFormat = false;
156 for(int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i)
158 switch (codec->sample_fmts[i])
160 case AV_SAMPLE_FMT_FLT: hasFloat = true; break;
161 case AV_SAMPLE_FMT_DBL: hasDouble = true; break;
162 case AV_SAMPLE_FMT_S32: hasS32 = true; break;
163 case AV_SAMPLE_FMT_S16: hasS16 = true; break;
164 case AV_SAMPLE_FMT_U8 : hasU8 = true; break;
165 case AV_SAMPLE_FMT_FLTP:
166 if (allow_planar_input)
169 hasUnknownFormat = true;
171 case AV_SAMPLE_FMT_NONE: return false;
172 default: hasUnknownFormat = true; break;
178 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT;
179 format.m_dataFormat = AE_FMT_FLOAT;
183 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
184 format.m_dataFormat = AE_FMT_FLOATP;
188 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_DBL;
189 format.m_dataFormat = AE_FMT_DOUBLE;
193 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S32;
194 format.m_dataFormat = AE_FMT_S32NE;
198 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
199 format.m_dataFormat = AE_FMT_S16NE;
203 m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_U8;
204 format.m_dataFormat = AE_FMT_U8;
206 else if (hasUnknownFormat)
208 m_CodecCtx->sample_fmt = codec->sample_fmts[0];
209 format.m_dataFormat = AE_FMT_FLOAT;
210 m_NeedConversion = true;
211 CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - Unknown audio format, it will be resampled.");
215 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec (%s)", m_CodecName.c_str());
220 m_CodecCtx->channels = BuildChannelLayout(m_CodecCtx->channel_layout, m_Layout);
223 if (m_dllAvCodec.avcodec_open2(m_CodecCtx, codec, NULL))
225 m_dllAvUtil.av_freep(&m_CodecCtx);
229 format.m_frames = m_CodecCtx->frame_size;
230 format.m_frameSamples = m_CodecCtx->frame_size * m_CodecCtx->channels;
231 format.m_frameSize = m_CodecCtx->channels * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
232 format.m_channelLayout = m_Layout;
234 m_CurrentFormat = format;
235 m_NeededFrames = format.m_frames;
236 m_OutputSize = m_PackFunc(NULL, 0, m_Buffer);
237 m_OutputRatio = (double)m_NeededFrames / m_OutputSize;
238 m_SampleRateMul = 1.0 / (double)m_CodecCtx->sample_rate;
240 if (m_NeedConversion)
242 m_SwrCtx = m_dllSwResample.swr_alloc_set_opts(NULL,
243 m_CodecCtx->channel_layout, m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate,
244 m_CodecCtx->channel_layout, AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate,
246 if (!m_SwrCtx || m_dllSwResample.swr_init(m_SwrCtx) < 0)
248 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler.");
252 CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - %s encoder ready", m_CodecName.c_str());
256 void CAEEncoderFFmpeg::Reset()
261 unsigned int CAEEncoderFFmpeg::GetBitRate()
266 AVCodecID CAEEncoderFFmpeg::GetCodecID()
271 unsigned int CAEEncoderFFmpeg::GetFrames()
273 return m_NeededFrames;
276 int CAEEncoderFFmpeg::Encode(float *data, unsigned int frames)
280 const uint8_t *input = (const uint8_t*) data;
282 if (!m_CodecCtx || frames < m_NeededFrames)
285 /* size of the buffer sent to the encoder: either from the input data or after
286 * conversion, in all cases it is in the m_CodecCtx->sample_fmt format */
287 int buf_size = m_dllAvUtil.av_samples_get_buffer_size(NULL, m_CodecCtx->channels, frames, m_CodecCtx->sample_fmt, 0);
290 /* allocate the input frame
291 * sadly, we have to alloc/dealloc it everytime since we have no guarantee the
292 * data argument will be constant over iterated calls and the frame needs to
293 * setup pointers inside data */
294 frame = m_dllAvCodec.avcodec_alloc_frame();
298 frame->nb_samples = m_CodecCtx->frame_size;
299 frame->format = m_CodecCtx->sample_fmt;
300 frame->channel_layout = m_CodecCtx->channel_layout;
302 if (m_NeedConversion)
304 if (!m_ResampBuffer || buf_size > m_ResampBufferSize)
306 m_ResampBuffer = (uint8_t*)m_dllAvUtil.av_realloc(m_ResampBuffer, buf_size);
309 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Failed to allocate %i bytes buffer for resampling", buf_size);
310 m_dllAvCodec.avcodec_free_frame(&frame);
313 m_ResampBufferSize = buf_size;
316 m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt, m_ResampBuffer, buf_size, 0);
318 /* important note: the '&input' here works because we convert from a packed
319 * format (ie, interleaved). If it were to be used to convert from planar
320 * formats (ie, non-interleaved, which is not currently supported by AE),
321 * we would need to adapt it or it would segfault. */
322 if (m_dllSwResample.swr_convert(m_SwrCtx, frame->extended_data, frames, &input, frames) < 0)
324 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Resampling failed");
325 m_dllAvCodec.avcodec_free_frame(&frame);
330 m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt,
333 /* initialize the output packet */
334 m_dllAvCodec.av_init_packet(&m_Pkt);
335 m_Pkt.size = sizeof(m_Buffer) - IEC61937_DATA_OFFSET;
336 m_Pkt.data = m_Buffer + IEC61937_DATA_OFFSET;
339 int ret = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
341 /* free temporary data */
342 m_dllAvCodec.avcodec_free_frame(&frame);
344 if (ret < 0 || !got_output)
346 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed");
350 /* pack it into an IEC958 frame */
351 m_BufferSize = m_PackFunc(NULL, m_Pkt.size, m_Buffer);
352 if (m_BufferSize != m_OutputSize)
354 m_OutputSize = m_BufferSize;
355 m_OutputRatio = (double)m_NeededFrames / m_OutputSize;
358 /* free the packet */
359 m_dllAvCodec.av_free_packet(&m_Pkt);
361 /* return the number of frames used */
362 return m_NeededFrames;
365 int CAEEncoderFFmpeg::Encode(uint8_t *in, int in_size, uint8_t *out, int out_size)
373 /* allocate the input frame
374 * sadly, we have to alloc/dealloc it everytime since we have no guarantee the
375 * data argument will be constant over iterated calls and the frame needs to
376 * setup pointers inside data */
377 frame = m_dllAvCodec.avcodec_alloc_frame();
381 frame->nb_samples = m_CodecCtx->frame_size;
382 frame->format = m_CodecCtx->sample_fmt;
383 frame->channel_layout = m_CodecCtx->channel_layout;
385 m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt,
388 /* initialize the output packet */
389 m_dllAvCodec.av_init_packet(&m_Pkt);
390 m_Pkt.size = out_size - IEC61937_DATA_OFFSET;
391 m_Pkt.data = out + IEC61937_DATA_OFFSET;
394 int ret = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
396 /* free temporary data */
397 m_dllAvCodec.avcodec_free_frame(&frame);
399 if (ret < 0 || !got_output)
401 CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed");
405 /* pack it into an IEC958 frame */
406 m_PackFunc(NULL, m_Pkt.size, out);
408 /* free the packet */
409 m_dllAvCodec.av_free_packet(&m_Pkt);
411 /* return the number of frames used */
412 return m_NeededFrames;
416 int CAEEncoderFFmpeg::GetData(uint8_t **data)
425 double CAEEncoderFFmpeg::GetDelay(unsigned int bufferSize)
430 int frames = m_CodecCtx->delay;
432 frames += m_NeededFrames;
434 return ((double)frames + ((double)bufferSize * m_OutputRatio)) * m_SampleRateMul;