Merge pull request #4314 from MartijnKaijser/beta1
[vuplus_xbmc] / xbmc / cores / AudioEngine / Encoders / AEEncoderFFmpeg.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #define AC3_ENCODE_BITRATE 640000
22 #define DTS_ENCODE_BITRATE 1411200
23
24 #include "cores/AudioEngine/Encoders/AEEncoderFFmpeg.h"
25 #include "cores/AudioEngine/Utils/AEUtil.h"
26 #include "utils/log.h"
27 #include "settings/AdvancedSettings.h"
28 #include "settings/Settings.h"
29 #include <string.h>
30
31 CAEEncoderFFmpeg::CAEEncoderFFmpeg():
32   m_BitRate       (0    ),
33   m_CodecCtx      (NULL ),
34   m_SwrCtx        (NULL ),
35   m_BufferSize    (0    ),
36   m_OutputSize    (0    ),
37   m_OutputRatio   (0.0  ),
38   m_SampleRateMul (0.0  ),
39   m_NeededFrames  (0    ),
40   m_NeedConversion(false),
41   m_ResampBuffer  (NULL ),
42   m_ResampBufferSize(0  )
43 {
44 }
45
46 CAEEncoderFFmpeg::~CAEEncoderFFmpeg()
47 {
48   Reset();
49   m_dllAvUtil.av_freep(&m_CodecCtx);
50   m_dllAvUtil.av_freep(&m_ResampBuffer);
51   if (m_SwrCtx)
52     m_dllSwResample.swr_free(&m_SwrCtx);
53 }
54
55 bool CAEEncoderFFmpeg::IsCompatible(AEAudioFormat format)
56 {
57   if (!m_CodecCtx)
58     return false;
59
60   bool match = (
61     format.m_dataFormat == m_CurrentFormat.m_dataFormat &&
62     format.m_sampleRate == m_CurrentFormat.m_sampleRate
63   );
64
65   if (match)
66   {
67     CAEChannelInfo layout;
68     BuildChannelLayout(AV_CH_LAYOUT_5POINT1_BACK, layout); /* hard coded for AC3 & DTS currently */
69     match = (m_CurrentFormat.m_channelLayout == layout);
70   }
71
72   return match;
73 }
74
75 unsigned int CAEEncoderFFmpeg::BuildChannelLayout(const int64_t ffmap, CAEChannelInfo& layout)
76 {
77   /* build the channel layout and count the channels */
78   layout.Reset();
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 ;
97
98   return layout.Count();
99 }
100
101 bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format, bool allow_planar_input)
102 {
103   Reset();
104
105   if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load())
106     return false;
107
108   m_dllAvCodec.avcodec_register_all();
109
110   bool ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough");
111
112   AVCodec *codec = NULL;
113 #if 0
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")))
117   {
118     m_CodecName = "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);
123   }
124 #endif
125
126   /* fallback to ac3 if we support it, we might not have DTS support */
127   if (!codec && ac3)
128   {
129     m_CodecName = "AC3";
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);
134   }
135
136   /* check we got the codec */
137   if (!codec)
138     return false;
139
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;
144
145   /* select a suitable data format */
146   if (codec->sample_fmts)
147   {
148     bool hasFloat  = false;
149     bool hasDouble = false;
150     bool hasS32    = false;
151     bool hasS16    = false;
152     bool hasU8     = false;
153     bool hasFloatP = false;
154     bool hasUnknownFormat = false;
155
156     for(int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i)
157     {
158       switch (codec->sample_fmts[i])
159       {
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)
167             hasFloatP  = true;
168           else
169             hasUnknownFormat = true;
170           break;
171         case AV_SAMPLE_FMT_NONE: return false;
172         default: hasUnknownFormat = true; break;
173       }
174     }
175
176     if (hasFloat)
177     {
178       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT;
179       format.m_dataFormat    = AE_FMT_FLOAT;
180     }
181     else if (hasFloatP)
182     {
183       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
184       format.m_dataFormat    = AE_FMT_FLOATP;
185     }
186     else if (hasDouble)
187     {
188       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_DBL;
189       format.m_dataFormat    = AE_FMT_DOUBLE;
190     }
191     else if (hasS32)
192     {
193       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S32;
194       format.m_dataFormat    = AE_FMT_S32NE;
195     }
196     else if (hasS16)
197     {
198       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
199       format.m_dataFormat    = AE_FMT_S16NE;
200     }
201     else if (hasU8)
202     {
203       m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_U8;
204       format.m_dataFormat    = AE_FMT_U8;
205     }
206     else if (hasUnknownFormat)
207     {
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.");
212     }
213     else
214     {
215       CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec (%s)", m_CodecName.c_str());
216       return false;
217     }
218   }
219
220   m_CodecCtx->channels = BuildChannelLayout(m_CodecCtx->channel_layout, m_Layout);
221
222   /* open the codec */
223   if (m_dllAvCodec.avcodec_open2(m_CodecCtx, codec, NULL))
224   {
225     m_dllAvUtil.av_freep(&m_CodecCtx);
226     return false;
227   }
228
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;
233
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;
239
240   if (m_NeedConversion)
241   {
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,
245                       0, NULL);
246     if (!m_SwrCtx || m_dllSwResample.swr_init(m_SwrCtx) < 0)
247     {
248       CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler.");
249       return false;
250     }
251   }
252   CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - %s encoder ready", m_CodecName.c_str());
253   return true;
254 }
255
256 void CAEEncoderFFmpeg::Reset()
257 {
258   m_BufferSize = 0;
259 }
260
261 unsigned int CAEEncoderFFmpeg::GetBitRate()
262 {
263   return m_BitRate;
264 }
265
266 AVCodecID CAEEncoderFFmpeg::GetCodecID()
267 {
268   return m_CodecID;
269 }
270
271 unsigned int CAEEncoderFFmpeg::GetFrames()
272 {
273   return m_NeededFrames;
274 }
275
276 int CAEEncoderFFmpeg::Encode(float *data, unsigned int frames)
277 {
278   int got_output;
279   AVFrame *frame;
280   const uint8_t *input = (const uint8_t*) data;
281
282   if (!m_CodecCtx || frames < m_NeededFrames)
283     return 0;
284
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);
288   assert(buf_size>0);
289
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();
295   if (!frame)
296     return 0;
297
298   frame->nb_samples     = m_CodecCtx->frame_size;
299   frame->format         = m_CodecCtx->sample_fmt;
300   frame->channel_layout = m_CodecCtx->channel_layout;
301
302   if (m_NeedConversion)
303   {
304     if (!m_ResampBuffer || buf_size > m_ResampBufferSize)
305     {
306       m_ResampBuffer = (uint8_t*)m_dllAvUtil.av_realloc(m_ResampBuffer, buf_size);
307       if (!m_ResampBuffer)
308       {
309         CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Failed to allocate %i bytes buffer for resampling", buf_size);
310         m_dllAvCodec.avcodec_free_frame(&frame);
311         return 0;
312       }
313       m_ResampBufferSize = buf_size;
314     }
315
316     m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt, m_ResampBuffer, buf_size, 0);
317
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)
323     {
324       CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Resampling failed");
325       m_dllAvCodec.avcodec_free_frame(&frame);
326       return 0;
327     }
328   }
329   else
330     m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt,
331                     input, buf_size, 0);
332
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;
337
338   /* encode it */
339   int ret = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
340
341   /* free temporary data */
342   m_dllAvCodec.avcodec_free_frame(&frame);
343
344   if (ret < 0 || !got_output)
345   {
346     CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed");
347     return 0;
348   }
349
350   /* pack it into an IEC958 frame */
351   m_BufferSize = m_PackFunc(NULL, m_Pkt.size, m_Buffer);
352   if (m_BufferSize != m_OutputSize)
353   {
354     m_OutputSize  = m_BufferSize;
355     m_OutputRatio = (double)m_NeededFrames / m_OutputSize;
356   }
357
358   /* free the packet */
359   m_dllAvCodec.av_free_packet(&m_Pkt);
360
361   /* return the number of frames used */
362   return m_NeededFrames;
363 }
364
365 int CAEEncoderFFmpeg::Encode(uint8_t *in, int in_size, uint8_t *out, int out_size)
366 {
367   int got_output;
368   AVFrame *frame;
369
370   if (!m_CodecCtx)
371     return 0;
372
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();
378   if (!frame)
379     return 0;
380
381   frame->nb_samples     = m_CodecCtx->frame_size;
382   frame->format         = m_CodecCtx->sample_fmt;
383   frame->channel_layout = m_CodecCtx->channel_layout;
384
385   m_dllAvCodec.avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt,
386                     in, in_size, 0);
387
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;
392
393   /* encode it */
394   int ret = m_dllAvCodec.avcodec_encode_audio2(m_CodecCtx, &m_Pkt, frame, &got_output);
395
396   /* free temporary data */
397   m_dllAvCodec.avcodec_free_frame(&frame);
398
399   if (ret < 0 || !got_output)
400   {
401     CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed");
402     return 0;
403   }
404
405   /* pack it into an IEC958 frame */
406   m_PackFunc(NULL, m_Pkt.size, out);
407
408   /* free the packet */
409   m_dllAvCodec.av_free_packet(&m_Pkt);
410
411   /* return the number of frames used */
412   return m_NeededFrames;
413 }
414
415
416 int CAEEncoderFFmpeg::GetData(uint8_t **data)
417 {
418   int size;
419   *data = m_Buffer;
420   size  = m_BufferSize;
421   m_BufferSize = 0;
422   return size;
423 }
424
425 double CAEEncoderFFmpeg::GetDelay(unsigned int bufferSize)
426 {
427   if (!m_CodecCtx)
428     return 0;
429
430   int frames = m_CodecCtx->delay;
431   if (m_BufferSize)
432     frames += m_NeededFrames;
433
434   return ((double)frames + ((double)bufferSize * m_OutputRatio)) * m_SampleRateMul;
435 }
436