Merge pull request #4314 from MartijnKaijser/beta1
[vuplus_xbmc] / xbmc / cores / omxplayer / OMXAudio.cpp
1 /*
2  *      Copyright (c) 2002 d7o3g4q and RUNTiME
3  *      Portions Copyright (c) by the authors of ffmpeg and xvid
4  *      Copyright (C) 2012-2013 Team XBMC
5  *      http://xbmc.org
6  *
7  *  This Program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  This Program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with XBMC; see the file COPYING.  If not, see
19  *  <http://www.gnu.org/licenses/>.
20  *
21  */
22
23 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
24   #include "config.h"
25 #elif defined(TARGET_WINDOWS)
26 #include "system.h"
27 #endif
28
29 #include "OMXAudio.h"
30 #include "Application.h"
31 #include "utils/log.h"
32
33 #define CLASSNAME "COMXAudio"
34
35 #include "linux/XMemUtils.h"
36
37 #include "settings/AdvancedSettings.h"
38 #include "settings/MediaSettings.h"
39 #include "settings/Settings.h"
40 #include "guilib/LocalizeStrings.h"
41 #include "cores/AudioEngine/Utils/AEConvert.h"
42 #include "cores/AudioEngine/AEFactory.h"
43
44 using namespace std;
45
46 static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
47 static const uint16_t AC3FSCod   [] = {48000, 44100, 32000, 0};
48
49 static const uint16_t DTSFSCod   [] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0};
50
51 //////////////////////////////////////////////////////////////////////
52 // Construction/Destruction
53 //////////////////////////////////////////////////////////////////////
54 //***********************************************************************************************
55 COMXAudio::COMXAudio() :
56   m_pCallback       (NULL   ),
57   m_Initialized     (false  ),
58   m_CurrentVolume   (0      ),
59   m_Mute            (false  ),
60   m_drc             (0      ),
61   m_Passthrough     (false  ),
62   m_HWDecode        (false  ),
63   m_BytesPerSec     (0      ),
64   m_BufferLen       (0      ),
65   m_ChunkLen        (0      ),
66   m_InputChannels   (0      ),
67   m_OutputChannels  (0      ),
68   m_BitsPerSample   (0      ),
69   m_maxLevel        (0.0f   ),
70   m_amplification   (1.0f   ),
71   m_attenuation     (1.0f   ),
72   m_submitted       (0.0f   ),
73   m_omx_clock       (NULL   ),
74   m_av_clock        (NULL   ),
75   m_settings_changed(false  ),
76   m_setStartTime    (false  ),
77   m_LostSync        (true   ),
78   m_SampleRate      (0      ),
79   m_eEncoding       (OMX_AUDIO_CodingPCM),
80   m_extradata       (NULL   ),
81   m_extrasize       (0      ),
82   m_last_pts        (DVD_NOPTS_VALUE),
83   m_submitted_eos   (false  ),
84   m_failed_eos      (false  )
85 {
86   CAEFactory::Suspend();
87   while (!CAEFactory::IsSuspended())
88     Sleep(10);
89 }
90
91 COMXAudio::~COMXAudio()
92 {
93   Deinitialize();
94
95   CAEFactory::Resume();
96 }
97
98 bool COMXAudio::PortSettingsChanged()
99 {
100   CSingleLock lock (m_critSection);
101   OMX_ERRORTYPE omx_err   = OMX_ErrorNone;
102
103   if (m_settings_changed)
104   {
105     m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
106     m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
107     return true;
108   }
109
110   if(!m_Passthrough)
111   {
112     if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit))
113       return false;
114   }
115   if(CSettings::Get().GetBool("audiooutput.dualaudio"))
116   {
117     if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
118       return false;
119   }
120   if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue")
121   {
122     if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
123       return false;
124   }
125   if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue")
126   {
127     if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
128       return false;
129   }
130
131   SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
132   UpdateAttenuation();
133
134   if( m_omx_mixer.IsInitialized() )
135   {
136     /* setup mixer output */
137     OMX_INIT_STRUCTURE(m_pcm_output);
138     m_pcm_output.nPortIndex = m_omx_decoder.GetOutputPort();
139     omx_err = m_omx_decoder.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
140     if(omx_err != OMX_ErrorNone)
141     {
142       CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder GetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
143       return false;
144     }
145
146     memcpy(m_pcm_output.eChannelMapping, m_output_channels, sizeof(m_output_channels));
147     // round up to power of 2
148     m_pcm_output.nChannels = m_OutputChannels > 4 ? 8 : m_OutputChannels > 2 ? 4 : m_OutputChannels;
149     /* limit samplerate (through resampling) if requested */
150     m_pcm_output.nSamplingRate = std::min(std::max((int)m_pcm_output.nSamplingRate, 8000), CSettings::Get().GetInt("audiooutput.samplerate"));
151
152     m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort();
153     omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
154     if(omx_err != OMX_ErrorNone)
155     {
156       CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
157       return false;
158     }
159
160     CLog::Log(LOGDEBUG, "%s::%s - Output bps %d samplerate %d channels %d buffer size %d bytes per second %d",
161         CLASSNAME, __func__, (int)m_pcm_output.nBitPerSample, (int)m_pcm_output.nSamplingRate, (int)m_pcm_output.nChannels, m_BufferLen, m_BytesPerSec);
162     PrintPCM(&m_pcm_output, std::string("output"));
163
164     if( m_omx_splitter.IsInitialized() )
165     {
166       m_pcm_output.nPortIndex = m_omx_splitter.GetInputPort();
167       omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
168       if(omx_err != OMX_ErrorNone)
169       {
170         CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
171         return false;
172       }
173
174       m_pcm_output.nPortIndex = m_omx_splitter.GetOutputPort();
175       omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
176       if(omx_err != OMX_ErrorNone)
177       {
178         CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
179         return false;
180       }
181       m_pcm_output.nPortIndex = m_omx_splitter.GetOutputPort() + 1;
182       omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
183       if(omx_err != OMX_ErrorNone)
184       {
185         CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
186         return false;
187       }
188     }
189
190     if( m_omx_render_analog.IsInitialized() )
191     {
192       m_pcm_output.nPortIndex = m_omx_render_analog.GetInputPort();
193       omx_err = m_omx_render_analog.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
194       if(omx_err != OMX_ErrorNone)
195       {
196         CLog::Log(LOGERROR, "%s::%s - error m_omx_render_analog SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
197         return false;
198       }
199     }
200
201     if( m_omx_render_hdmi.IsInitialized() )
202     {
203       m_pcm_output.nPortIndex = m_omx_render_hdmi.GetInputPort();
204       omx_err = m_omx_render_hdmi.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
205       if(omx_err != OMX_ErrorNone)
206       {
207         CLog::Log(LOGERROR, "%s::%s - error m_omx_render_hdmi SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
208         return false;
209       }
210     }
211   }
212   if( m_omx_render_analog.IsInitialized() )
213   {
214     m_omx_tunnel_clock_analog.Initialize(m_omx_clock, m_omx_clock->GetInputPort(),
215       &m_omx_render_analog, m_omx_render_analog.GetInputPort()+1);
216
217     omx_err = m_omx_tunnel_clock_analog.Establish();
218     if(omx_err != OMX_ErrorNone)
219     {
220       CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_analog.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
221       return false;
222     }
223     m_omx_render_analog.ResetEos();
224   }
225   if( m_omx_render_hdmi.IsInitialized() )
226   {
227     m_omx_tunnel_clock_hdmi.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + (m_omx_render_analog.IsInitialized() ? 2 : 0),
228       &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort()+1);
229
230     omx_err = m_omx_tunnel_clock_hdmi.Establish();
231     if(omx_err != OMX_ErrorNone)
232     {
233       CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_hdmi.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
234       return false;
235     }
236     m_omx_render_hdmi.ResetEos();
237   }
238
239   if( m_omx_render_analog.IsInitialized() )
240   {
241     // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
242     // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
243     if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
244     {
245       OMX_CONFIG_BOOLEANTYPE configBool;
246       OMX_INIT_STRUCTURE(configBool);
247       configBool.bEnabled = OMX_FALSE;
248
249       omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
250       if (omx_err != OMX_ErrorNone)
251          return false;
252     }
253
254     OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
255     OMX_INIT_STRUCTURE(audioDest);
256     strncpy((char *)audioDest.sName, "local", strlen("local"));
257     omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
258     if (omx_err != OMX_ErrorNone)
259     {
260       CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
261       return false;
262     }
263   }
264
265   if( m_omx_render_hdmi.IsInitialized() )
266   {
267     // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
268     // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
269     if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
270     {
271       OMX_CONFIG_BOOLEANTYPE configBool;
272       OMX_INIT_STRUCTURE(configBool);
273       configBool.bEnabled = OMX_FALSE;
274
275       omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
276       if (omx_err != OMX_ErrorNone)
277          return false;
278     }
279
280     OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
281     OMX_INIT_STRUCTURE(audioDest);
282     strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi"));
283     omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
284     if (omx_err != OMX_ErrorNone)
285     {
286       CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
287       return false;
288     }
289   }
290
291   if( m_omx_splitter.IsInitialized() )
292   {
293     m_omx_tunnel_splitter_analog.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
294     omx_err = m_omx_tunnel_splitter_analog.Establish();
295     if(omx_err != OMX_ErrorNone)
296     {
297       CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_analog.Establish 0x%08x", omx_err);
298       return false;
299     }
300
301     m_omx_tunnel_splitter_hdmi.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort() + 1, &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
302     omx_err = m_omx_tunnel_splitter_hdmi.Establish();
303     if(omx_err != OMX_ErrorNone)
304     {
305       CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_hdmi.Establish 0x%08x", omx_err);
306       return false;
307     }
308   }
309   if( m_omx_mixer.IsInitialized() )
310   {
311     m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_mixer, m_omx_mixer.GetInputPort());
312     if( m_omx_splitter.IsInitialized() )
313     {
314       m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_splitter, m_omx_splitter.GetInputPort());
315     }
316     else
317     {
318       if( m_omx_render_analog.IsInitialized() )
319       {
320         m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
321       }
322       if( m_omx_render_hdmi.IsInitialized() )
323       {
324         m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
325       }
326     }
327     CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d nopassthrough", CLASSNAME, __func__,
328             (int)m_pcm_input.nBitPerSample, m_pcm_input.ePCMMode, (int)m_pcm_input.nChannels, (int)m_pcm_input.nSamplingRate);
329   }
330   else
331   {
332     if( m_omx_render_analog.IsInitialized() )
333     {
334       m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
335     }
336     else if( m_omx_render_hdmi.IsInitialized() )
337     {
338       m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
339     }
340     CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d passthrough", CLASSNAME, __func__,
341             0, 0, 0, 0);
342   }
343
344   omx_err = m_omx_tunnel_decoder.Establish();
345   if(omx_err != OMX_ErrorNone)
346   {
347     CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
348     return false;
349   }
350
351   if( m_omx_mixer.IsInitialized() )
352   {
353     omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting);
354     if(omx_err != OMX_ErrorNone) {
355       CLog::Log(LOGERROR, "%s::%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
356       return false;
357     }
358   }
359
360   if( m_omx_mixer.IsInitialized() )
361   {
362     omx_err = m_omx_tunnel_mixer.Establish();
363     if(omx_err != OMX_ErrorNone)
364     {
365       CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
366       return false;
367     }
368   }
369
370   if( m_omx_splitter.IsInitialized() )
371   {
372     omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting);
373     if(omx_err != OMX_ErrorNone)
374     {
375       CLog::Log(LOGERROR, "%s::%s - m_omx_splitter OMX_StateExecuting 0x%08x", CLASSNAME, __func__, omx_err);
376      return false;
377     }
378   }
379   if( m_omx_render_analog.IsInitialized() )
380   {
381     omx_err = m_omx_render_analog.SetStateForComponent(OMX_StateExecuting);
382     if(omx_err != OMX_ErrorNone)
383     {
384       CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
385       return false;
386     }
387   }
388   if( m_omx_render_hdmi.IsInitialized() )
389   {
390     omx_err = m_omx_render_hdmi.SetStateForComponent(OMX_StateExecuting);
391     if(omx_err != OMX_ErrorNone)
392     {
393       CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
394       return false;
395     }
396   }
397
398   m_settings_changed = true;
399   return true;
400 }
401
402 static unsigned count_bits(int64_t value)
403 {
404   unsigned bits = 0;
405   for(;value;++bits)
406     value &= value - 1;
407   return bits;
408 }
409
410 bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, uint64_t channelMap, bool bUsePassthrough, bool bUseHWDecode)
411 {
412   CSingleLock lock (m_critSection);
413   OMX_ERRORTYPE omx_err;
414
415   Deinitialize();
416
417   if(!m_dllAvUtil.Load())
418     return false;
419
420   m_HWDecode    = bUseHWDecode;
421   m_Passthrough = bUsePassthrough;
422
423   m_InputChannels = count_bits(channelMap);
424   m_format = format;
425
426   if(m_InputChannels == 0)
427     return false;
428
429   if(hints.samplerate == 0)
430     return false;
431
432   m_av_clock = clock;
433
434   if(!m_av_clock)
435     return false;
436
437   /* passthrough overwrites hw decode */
438   if(m_Passthrough)
439   {
440     m_HWDecode = false;
441   }
442   else if(m_HWDecode)
443   {
444     /* check again if we are capable to hw decode the format */
445     m_HWDecode = CanHWDecode(hints.codec);
446   }
447   SetCodingType(format.m_dataFormat);
448
449   if(hints.extrasize > 0 && hints.extradata != NULL)
450   {
451     m_extrasize = hints.extrasize;
452     m_extradata = (uint8_t *)malloc(m_extrasize);
453     memcpy(m_extradata, hints.extradata, hints.extrasize);
454   }
455
456   m_omx_clock   = m_av_clock->GetOMXClock();
457
458   m_drc         = 0;
459
460   memset(m_input_channels, 0x0, sizeof(m_input_channels));
461   memset(m_output_channels, 0x0, sizeof(m_output_channels));
462   memset(&m_wave_header, 0x0, sizeof(m_wave_header));
463
464   m_wave_header.Format.nChannels  = 2;
465   m_wave_header.dwChannelMask     = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
466
467   if (!m_Passthrough)
468   {
469     enum PCMChannels inLayout[OMX_AUDIO_MAXCHANNELS];
470     enum PCMChannels outLayout[OMX_AUDIO_MAXCHANNELS];
471     enum PCMLayout layout = (enum PCMLayout)std::max(0, CSettings::Get().GetInt("audiooutput.channels")-1);
472     // ignore layout setting for analogue
473     if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue")
474       layout = PCM_LAYOUT_2_0;
475
476     // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix
477     if (channelMap == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) || channelMap == AV_CH_FRONT_CENTER)
478       layout = PCM_LAYOUT_2_0;
479     BuildChannelMap(inLayout, channelMap);
480     m_OutputChannels = BuildChannelMapCEA(outLayout, GetChannelLayout(layout));
481     CPCMRemap m_remap;
482     m_remap.Reset();
483     /*outLayout = */m_remap.SetInputFormat (m_InputChannels, inLayout, CAEUtil::DataFormatToBits(m_format.m_dataFormat) / 8, m_format.m_sampleRate, layout);
484     m_remap.SetOutputFormat(m_OutputChannels, outLayout);
485     m_remap.GetDownmixMatrix(m_downmix_matrix);
486     m_wave_header.dwChannelMask = channelMap;
487     BuildChannelMapOMX(m_input_channels, channelMap);
488     BuildChannelMapOMX(m_output_channels, GetChannelLayout(layout));
489   }
490
491   m_SampleRate    = m_format.m_sampleRate;
492   m_BitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
493   m_BufferLen     = m_BytesPerSec = m_format.m_sampleRate * (16 >> 3) * m_InputChannels;
494   m_BufferLen     *= AUDIO_BUFFER_SECONDS;
495   // the audio_decode output buffer size is 32K, and typically we convert from
496   // 6 channel 32bpp float to 8 channel 16bpp in, so a full 48K input buffer will fit the outbut buffer
497   m_ChunkLen      = 48*1024;
498
499   m_wave_header.Samples.wSamplesPerBlock    = 0;
500   m_wave_header.Format.nChannels            = m_InputChannels;
501   m_wave_header.Format.nBlockAlign          = m_InputChannels * (m_BitsPerSample >> 3);
502   // 0x8000 is custom format interpreted by GPU as WAVE_FORMAT_IEEE_FLOAT_PLANAR
503   m_wave_header.Format.wFormatTag           = m_BitsPerSample == 32 ? 0x8000 : WAVE_FORMAT_PCM;
504   m_wave_header.Format.nSamplesPerSec       = m_format.m_sampleRate;
505   m_wave_header.Format.nAvgBytesPerSec      = m_BytesPerSec;
506   m_wave_header.Format.wBitsPerSample       = m_BitsPerSample;
507   m_wave_header.Samples.wValidBitsPerSample = m_BitsPerSample;
508   m_wave_header.Format.cbSize               = 0;
509   m_wave_header.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
510
511   OMX_INIT_STRUCTURE(m_pcm_input);
512   memcpy(m_pcm_input.eChannelMapping, m_input_channels, sizeof(m_input_channels));
513   m_pcm_input.eNumData              = OMX_NumericalDataSigned;
514   m_pcm_input.eEndian               = OMX_EndianLittle;
515   m_pcm_input.bInterleaved          = OMX_TRUE;
516   m_pcm_input.nBitPerSample         = m_BitsPerSample;
517   m_pcm_input.ePCMMode              = OMX_AUDIO_PCMModeLinear;
518   m_pcm_input.nChannels             = m_InputChannels;
519   m_pcm_input.nSamplingRate         = m_format.m_sampleRate;
520
521   if(!m_omx_decoder.Initialize("OMX.broadcom.audio_decode", OMX_IndexParamAudioInit))
522     return false;
523
524   OMX_CONFIG_BOOLEANTYPE boolType;
525   OMX_INIT_STRUCTURE(boolType);
526   if(m_Passthrough)
527     boolType.bEnabled = OMX_TRUE;
528   else
529     boolType.bEnabled = OMX_FALSE;
530   omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmDecoderPassThrough, &boolType);
531   if(omx_err != OMX_ErrorNone)
532   {
533     CLog::Log(LOGERROR, "COMXAudio::Initialize - Error OMX_IndexParamBrcmDecoderPassThrough 0x%08x", omx_err);
534     return false;
535   }
536
537   // set up the number/size of buffers for decoder input
538   OMX_PARAM_PORTDEFINITIONTYPE port_param;
539   OMX_INIT_STRUCTURE(port_param);
540   port_param.nPortIndex = m_omx_decoder.GetInputPort();
541
542   omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
543   if(omx_err != OMX_ErrorNone)
544   {
545     CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)\n", omx_err);
546     return false;
547   }
548
549   port_param.format.audio.eEncoding = m_eEncoding;
550
551   port_param.nBufferSize = m_ChunkLen;
552   port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, 16U);
553
554   omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
555   if(omx_err != OMX_ErrorNone)
556   {
557     CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (intput) omx_err(0x%08x)\n", omx_err);
558     return false;
559   }
560
561   // set up the number/size of buffers for decoder output
562   OMX_INIT_STRUCTURE(port_param);
563   port_param.nPortIndex = m_omx_decoder.GetOutputPort();
564
565   omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
566   if(omx_err != OMX_ErrorNone)
567   {
568     CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
569     return false;
570   }
571
572   port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, m_BufferLen / port_param.nBufferSize);
573
574   omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
575   if(omx_err != OMX_ErrorNone)
576   {
577     CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
578     return false;
579   }
580
581   {
582     OMX_AUDIO_PARAM_PORTFORMATTYPE formatType;
583     OMX_INIT_STRUCTURE(formatType);
584     formatType.nPortIndex = m_omx_decoder.GetInputPort();
585
586     formatType.eEncoding = m_eEncoding;
587
588     omx_err = m_omx_decoder.SetParameter(OMX_IndexParamAudioPortFormat, &formatType);
589     if(omx_err != OMX_ErrorNone)
590     {
591       CLog::Log(LOGERROR, "COMXAudio::Initialize error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
592       return false;
593     }
594   }
595
596   omx_err = m_omx_decoder.AllocInputBuffers();
597   if(omx_err != OMX_ErrorNone) 
598   {
599     CLog::Log(LOGERROR, "COMXAudio::Initialize - Error alloc buffers 0x%08x", omx_err);
600     return false;
601   }
602
603   omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
604   if(omx_err != OMX_ErrorNone) {
605     CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
606     return false;
607   }
608
609
610   if(m_eEncoding == OMX_AUDIO_CodingPCM)
611   {
612     OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
613     if(omx_buffer == NULL)
614     {
615       CLog::Log(LOGERROR, "COMXAudio::Initialize - buffer error 0x%08x", omx_err);
616       return false;
617     }
618
619     omx_buffer->nOffset = 0;
620     omx_buffer->nFilledLen = sizeof(m_wave_header);
621     if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
622     {
623       CLog::Log(LOGERROR, "COMXAudio::Initialize - omx_buffer->nFilledLen > omx_buffer->nAllocLen");
624       return false;
625     }
626     memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
627     memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen);
628     omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
629
630     omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
631     if (omx_err != OMX_ErrorNone)
632     {
633       CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
634       return false;
635     }
636   } 
637   else if(m_HWDecode)
638   {
639     // send decoder config
640     if(m_extrasize > 0 && m_extradata != NULL)
641     {
642       OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
643   
644       if(omx_buffer == NULL)
645       {
646         CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
647         return false;
648       }
649   
650       omx_buffer->nOffset = 0;
651       omx_buffer->nFilledLen = m_extrasize;
652       if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
653       {
654         CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__);
655         return false;
656       }
657
658       memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
659       memcpy((unsigned char *)omx_buffer->pBuffer, m_extradata, omx_buffer->nFilledLen);
660       omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
661   
662       omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
663       if (omx_err != OMX_ErrorNone)
664       {
665         CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
666         return false;
667       }
668     }
669   }
670
671   /* return on decoder error so m_Initialized stays false */
672   if(m_omx_decoder.BadState())
673     return false;
674
675   m_Initialized   = true;
676   m_settings_changed = false;
677   m_setStartTime = true;
678   m_submitted_eos = false;
679   m_failed_eos = false;
680   m_last_pts      = DVD_NOPTS_VALUE;
681   m_submitted     = 0.0f;
682   m_maxLevel      = 0.0f;
683
684   CLog::Log(LOGDEBUG, "COMXAudio::Initialize Input bps %d samplerate %d channels %d buffer size %d bytes per second %d",
685       (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_BytesPerSec);
686   PrintPCM(&m_pcm_input, std::string("input"));
687   CLog::Log(LOGDEBUG, "COMXAudio::Initialize device passthrough %d hwdecode %d",
688      m_Passthrough, m_HWDecode);
689
690   return true;
691 }
692
693 //***********************************************************************************************
694 bool COMXAudio::Deinitialize()
695 {
696   CSingleLock lock (m_critSection);
697
698   if ( m_omx_tunnel_clock_analog.IsInitialized() )
699     m_omx_tunnel_clock_analog.Deestablish();
700   if ( m_omx_tunnel_clock_hdmi.IsInitialized() )
701     m_omx_tunnel_clock_hdmi.Deestablish();
702
703   // ignore expected errors on teardown
704   if ( m_omx_mixer.IsInitialized() )
705     m_omx_mixer.IgnoreNextError(OMX_ErrorPortUnpopulated);
706   else
707   {
708     if ( m_omx_render_hdmi.IsInitialized() )
709       m_omx_render_hdmi.IgnoreNextError(OMX_ErrorPortUnpopulated);
710     if ( m_omx_render_analog.IsInitialized() )
711       m_omx_render_analog.IgnoreNextError(OMX_ErrorPortUnpopulated);
712   }
713
714   m_omx_tunnel_decoder.Deestablish();
715   if ( m_omx_tunnel_mixer.IsInitialized() )
716     m_omx_tunnel_mixer.Deestablish();
717   if ( m_omx_tunnel_splitter_hdmi.IsInitialized() )
718     m_omx_tunnel_splitter_hdmi.Deestablish();
719   if ( m_omx_tunnel_splitter_analog.IsInitialized() )
720     m_omx_tunnel_splitter_analog.Deestablish();
721
722   m_omx_decoder.FlushInput();
723
724   m_omx_decoder.Deinitialize();
725   if ( m_omx_mixer.IsInitialized() )
726     m_omx_mixer.Deinitialize();
727   if ( m_omx_splitter.IsInitialized() )
728     m_omx_splitter.Deinitialize();
729   if ( m_omx_render_hdmi.IsInitialized() )
730     m_omx_render_hdmi.Deinitialize();
731   if ( m_omx_render_analog.IsInitialized() )
732     m_omx_render_analog.Deinitialize();
733
734   m_BytesPerSec = 0;
735   m_BufferLen   = 0;
736
737   m_omx_clock = NULL;
738   m_av_clock  = NULL;
739
740   m_Initialized = false;
741   m_LostSync    = true;
742   m_HWDecode    = false;
743
744   if(m_extradata)
745     free(m_extradata);
746   m_extradata = NULL;
747   m_extrasize = 0;
748
749   m_dllAvUtil.Unload();
750
751   while(!m_ampqueue.empty())
752     m_ampqueue.pop_front();
753
754   m_last_pts      = DVD_NOPTS_VALUE;
755   m_submitted     = 0.0f;
756   m_maxLevel      = 0.0f;
757
758   return true;
759 }
760
761 void COMXAudio::Flush()
762 {
763   CSingleLock lock (m_critSection);
764   if(!m_Initialized)
765     return;
766
767   m_omx_decoder.FlushAll();
768
769   if ( m_omx_mixer.IsInitialized() )
770     m_omx_mixer.FlushAll();
771
772   if ( m_omx_splitter.IsInitialized() )
773     m_omx_splitter.FlushAll();
774
775   if ( m_omx_render_analog.IsInitialized() )
776     m_omx_render_analog.FlushAll();
777   if ( m_omx_render_hdmi.IsInitialized() )
778     m_omx_render_hdmi.FlushAll();
779
780   m_last_pts      = DVD_NOPTS_VALUE;
781   m_submitted     = 0.0f;
782   m_maxLevel      = 0.0f;
783   m_LostSync      = true;
784   m_setStartTime  = true;
785 }
786
787 //***********************************************************************************************
788 void COMXAudio::SetDynamicRangeCompression(long drc)
789 {
790   CSingleLock lock (m_critSection);
791   m_amplification = powf(10.0f, (float)drc / 2000.0f);
792   if (m_settings_changed)
793     UpdateAttenuation();
794 }
795
796 //***********************************************************************************************
797 void COMXAudio::SetMute(bool bMute)
798 {
799   CSingleLock lock (m_critSection);
800   m_Mute = bMute;
801   if (m_settings_changed)
802     UpdateAttenuation();
803 }
804
805 //***********************************************************************************************
806 void COMXAudio::SetVolume(float fVolume)
807 {
808   CSingleLock lock (m_critSection);
809   m_CurrentVolume = fVolume;
810   if (m_settings_changed)
811     UpdateAttenuation();
812 }
813
814 //***********************************************************************************************
815 bool COMXAudio::ApplyVolume(void)
816 {
817   CSingleLock lock (m_critSection);
818
819   if (!m_Initialized || m_Passthrough)
820     return false;
821
822   float fVolume = m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
823
824   // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion) (deprecated)
825   double gain = pow(10, (g_advancedSettings.m_ac3Gain - 12.0f) / 20.0);
826
827   const float* coeff = m_downmix_matrix;
828
829   OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix;
830   OMX_INIT_STRUCTURE(mix);
831   OMX_ERRORTYPE omx_err;
832
833   assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64);
834
835   if (m_amplification != 1.0)
836   {
837     // reduce scaling so overflow can be seen
838     for(size_t i = 0; i < 8*8; ++i)
839       mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * gain * 0.01f));
840
841     mix.nPortIndex = m_omx_decoder.GetInputPort();
842     omx_err = m_omx_decoder.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
843     if(omx_err != OMX_ErrorNone)
844     {
845       CLog::Log(LOGERROR, "%s::%s - error setting decoder OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
846                 CLASSNAME, __func__, omx_err);
847       return false;
848     }
849   }
850   for(size_t i = 0; i < 8*8; ++i)
851     mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * gain * fVolume * m_amplification * m_attenuation));
852
853   mix.nPortIndex = m_omx_mixer.GetInputPort();
854   omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
855   if(omx_err != OMX_ErrorNone)
856   {
857     CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
858               CLASSNAME, __func__, omx_err);
859     return false;
860   }
861   CLog::Log(LOGINFO, "%s::%s - Volume=%.2f (* %.2f * %.2f)\n", CLASSNAME, __func__, fVolume, m_amplification, m_attenuation);
862   return true;
863 }
864
865 //***********************************************************************************************
866 unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
867 {
868   return AddPackets(data, len, 0, 0);
869 }
870
871 //***********************************************************************************************
872 unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts)
873 {
874   CSingleLock lock (m_critSection);
875
876   if(!m_Initialized)
877   {
878     CLog::Log(LOGERROR,"COMXAudio::AddPackets - sanity failed. no valid play handle!");
879     return len;
880   }
881
882   if(m_eEncoding == OMX_AUDIO_CodingDTS && m_LostSync && (m_Passthrough || m_HWDecode))
883   {
884     int skip = SyncDTS((uint8_t *)data, len);
885     if(skip > 0)
886       return len;
887   }
888
889   if(m_eEncoding == OMX_AUDIO_CodingDDP && m_LostSync && (m_Passthrough || m_HWDecode))
890   {
891     int skip = SyncAC3((uint8_t *)data, len);
892     if(skip > 0)
893       return len;
894   }
895
896   unsigned pitch = (m_Passthrough || m_HWDecode) ? 1:(m_BitsPerSample >> 3) * m_InputChannels;
897   unsigned int demuxer_samples = len / pitch;
898   unsigned int demuxer_samples_sent = 0;
899   uint8_t *demuxer_content = (uint8_t *)data;
900
901   OMX_ERRORTYPE omx_err;
902
903   OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
904
905   while(demuxer_samples_sent < demuxer_samples)
906   {
907     // 200ms timeout
908     omx_buffer = m_omx_decoder.GetInputBuffer(200);
909
910     if(omx_buffer == NULL)
911     {
912       CLog::Log(LOGERROR, "COMXAudio::Decode timeout\n");
913       return len;
914     }
915
916     omx_buffer->nOffset = 0;
917     omx_buffer->nFlags  = 0;
918
919     unsigned int remaining = demuxer_samples-demuxer_samples_sent;
920     unsigned int samples_space = omx_buffer->nAllocLen/pitch;
921     unsigned int samples = std::min(remaining, samples_space);
922
923     omx_buffer->nFilledLen = samples * pitch;
924
925     if (samples < demuxer_samples && m_BitsPerSample==32 && !(m_Passthrough || m_HWDecode))
926     {
927        uint8_t *dst = omx_buffer->pBuffer;
928        uint8_t *src = demuxer_content + demuxer_samples_sent * (m_BitsPerSample >> 3);
929        // we need to extract samples from planar audio, so the copying needs to be done per plane
930        for (int i=0; i<(int)m_InputChannels; i++)
931        {
932          memcpy(dst, src, omx_buffer->nFilledLen / m_InputChannels);
933          dst += omx_buffer->nFilledLen / m_InputChannels;
934          src += demuxer_samples * (m_BitsPerSample >> 3);
935        }
936        assert(dst <= omx_buffer->pBuffer + m_ChunkLen);
937     }
938     else
939     {
940        uint8_t *dst = omx_buffer->pBuffer;
941        uint8_t *src = demuxer_content + demuxer_samples_sent * pitch;
942        memcpy(dst, src, omx_buffer->nFilledLen);
943     }
944
945     uint64_t val  = (uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts;
946
947     if(m_setStartTime)
948     {
949       omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
950       if(pts == DVD_NOPTS_VALUE)
951         omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
952
953       m_last_pts = pts;
954
955       CLog::Log(LOGDEBUG, "COMXAudio::Decode ADec : setStartTime %f\n", (float)val / DVD_TIME_BASE);
956       m_setStartTime = false;
957     }
958     else
959     {
960       if(pts == DVD_NOPTS_VALUE)
961       {
962         omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
963         m_last_pts = pts;
964       }
965       else if (m_last_pts != pts)
966       {
967         if(pts > m_last_pts)
968           m_last_pts = pts;
969         else
970           omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;;
971       }
972       else if (m_last_pts == pts)
973       {
974         omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
975       }
976     }
977
978     omx_buffer->nTimeStamp = ToOMXTime(val);
979
980     demuxer_samples_sent += samples;
981
982     if(demuxer_samples_sent == demuxer_samples)
983       omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
984
985     int nRetry = 0;
986     while(true)
987     {
988       omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
989       if (omx_err == OMX_ErrorNone)
990       {
991         //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len);
992         break;
993       }
994       else
995       {
996         CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
997         nRetry++;
998       }
999       if(nRetry == 5)
1000       {
1001         CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__);
1002         return 0;
1003       }
1004     }
1005
1006     omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0);
1007     if (omx_err == OMX_ErrorNone)
1008     {
1009       if(!PortSettingsChanged())
1010       {
1011         CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err);
1012       }
1013     }
1014   }
1015   m_submitted += (float)demuxer_samples / m_SampleRate;
1016   if (m_amplification != 1.0)
1017     UpdateAttenuation();
1018   return len;
1019 }
1020
1021 void COMXAudio::UpdateAttenuation()
1022 {
1023   // always called with m_critSection lock held
1024   if (!m_Initialized || m_Passthrough)
1025     return;
1026
1027   if (m_amplification == 1.0)
1028   {
1029     ApplyVolume();
1030     return;
1031   }
1032
1033   double level_pts = 0.0;
1034   float level = GetMaxLevel(level_pts);
1035   if (level_pts != 0.0)
1036   {
1037     amplitudes_t v;
1038     v.level = level;
1039     v.pts = level_pts;
1040     m_ampqueue.push_back(v);
1041   }
1042   double stamp = m_av_clock->OMXMediaTime();
1043   // discard too old data
1044   while(!m_ampqueue.empty())
1045   {
1046     amplitudes_t &v = m_ampqueue.front();
1047     /* we'll also consume if queue gets unexpectedly long to avoid filling memory */
1048     if (v.pts == DVD_NOPTS_VALUE || v.pts < stamp || v.pts - stamp > DVD_SEC_TO_TIME(15.0))
1049       m_ampqueue.pop_front();
1050     else break;
1051   }
1052   float maxlevel = 0.0f, imminent_maxlevel = 0.0f;
1053   for (int i=0; i < (int)m_ampqueue.size(); i++)
1054   {
1055     amplitudes_t &v = m_ampqueue[i];
1056     maxlevel = std::max(maxlevel, v.level);
1057     // check for maximum volume in next 200ms
1058     if (v.pts != DVD_NOPTS_VALUE && v.pts < stamp + DVD_SEC_TO_TIME(0.2))
1059       imminent_maxlevel = std::max(imminent_maxlevel, v.level);
1060   }
1061
1062   if (maxlevel != 0.0)
1063   {
1064     float alpha_h = -1.0f/(0.025f*log10f(0.999f));
1065     float alpha_r = -1.0f/(0.100f*log10f(0.900f));
1066     float decay  = powf(10.0f, -1.0f / (alpha_h * g_advancedSettings.m_limiterHold));
1067     float attack = powf(10.0f, -1.0f / (alpha_r * g_advancedSettings.m_limiterRelease));
1068     // if we are going to clip imminently then deal with it now
1069     if (imminent_maxlevel > m_maxLevel)
1070       m_maxLevel = imminent_maxlevel;
1071     // clip but not imminently can ramp up more slowly
1072     else if (maxlevel > m_maxLevel)
1073       m_maxLevel = attack * m_maxLevel + (1.0f-attack) * maxlevel;
1074     // not clipping, decay more slowly
1075     else
1076       m_maxLevel = decay  * m_maxLevel + (1.0f-decay ) * maxlevel;
1077
1078     // want m_maxLevel * amp -> 1.0
1079     float amp = m_amplification * m_attenuation;
1080
1081     // We fade in the attenuation over first couple of seconds
1082     float start = std::min(std::max((m_submitted-1.0f), 0.0f), 1.0f);
1083     float attenuation = std::min(1.0f, std::max(m_attenuation / (amp * m_maxLevel), 1.0f/m_amplification));
1084     m_attenuation = (1.0f - start) * 1.0f/m_amplification + start * attenuation;
1085   }
1086   else
1087   {
1088     m_attenuation = 1.0f/m_amplification;
1089   }
1090   ApplyVolume();
1091 }
1092
1093 //***********************************************************************************************
1094 unsigned int COMXAudio::GetSpace()
1095 {
1096   int free = m_omx_decoder.GetInputBufferSpace();
1097   return free;
1098 }
1099
1100 float COMXAudio::GetDelay()
1101 {
1102   unsigned int free = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
1103   return m_BytesPerSec ? (float)free / (float)m_BytesPerSec : 0.0f;
1104 }
1105
1106 float COMXAudio::GetCacheTime()
1107 {
1108   float fBufferLenFull = (float)m_BufferLen - (float)GetSpace();
1109   if(fBufferLenFull < 0)
1110     fBufferLenFull = 0;
1111   float ret = m_BytesPerSec ? fBufferLenFull / (float)m_BytesPerSec : 0.0f;
1112   return ret;
1113 }
1114
1115 float COMXAudio::GetCacheTotal()
1116 {
1117   return m_BytesPerSec ? (float)m_BufferLen / (float)m_BytesPerSec : 0.0f;
1118 }
1119
1120 //***********************************************************************************************
1121 unsigned int COMXAudio::GetChunkLen()
1122 {
1123   return m_ChunkLen;
1124 }
1125 //***********************************************************************************************
1126 int COMXAudio::SetPlaySpeed(int iSpeed)
1127 {
1128   return 0;
1129 }
1130
1131 void COMXAudio::RegisterAudioCallback(IAudioCallback *pCallback)
1132 {
1133   CSingleLock lock (m_critSection);
1134   if(!m_Passthrough && !m_HWDecode)
1135   {
1136     m_pCallback = pCallback;
1137     if (m_pCallback)
1138       m_pCallback->OnInitialize(2, m_SampleRate, 32);
1139   }
1140   else
1141     m_pCallback = NULL;
1142 }
1143
1144 void COMXAudio::UnRegisterAudioCallback()
1145 {
1146   CSingleLock lock (m_critSection);
1147   m_pCallback = NULL;
1148 }
1149
1150 unsigned int COMXAudio::GetAudioRenderingLatency()
1151 {
1152   CSingleLock lock (m_critSection);
1153
1154   if(!m_Initialized)
1155     return 0;
1156
1157   OMX_PARAM_U32TYPE param;
1158   OMX_INIT_STRUCTURE(param);
1159
1160   if(m_omx_render_analog.IsInitialized())
1161   {
1162     param.nPortIndex = m_omx_render_analog.GetInputPort();
1163
1164     OMX_ERRORTYPE omx_err = m_omx_render_analog.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
1165
1166     if(omx_err != OMX_ErrorNone)
1167     {
1168       CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
1169         CLASSNAME, __func__, omx_err);
1170       return 0;
1171     }
1172   }
1173   else if(m_omx_render_hdmi.IsInitialized())
1174   {
1175     param.nPortIndex = m_omx_render_hdmi.GetInputPort();
1176
1177     OMX_ERRORTYPE omx_err = m_omx_render_hdmi.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
1178
1179     if(omx_err != OMX_ErrorNone)
1180     {
1181       CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
1182         CLASSNAME, __func__, omx_err);
1183       return 0;
1184     }
1185   }
1186
1187   return param.nU32;
1188 }
1189
1190 float COMXAudio::GetMaxLevel(double &pts)
1191 {
1192   CSingleLock lock (m_critSection);
1193
1194   if(!m_Initialized)
1195     return 0;
1196
1197   OMX_CONFIG_BRCMAUDIOMAXSAMPLE param;
1198   OMX_INIT_STRUCTURE(param);
1199
1200   if(m_omx_decoder.IsInitialized())
1201   {
1202     param.nPortIndex = m_omx_decoder.GetInputPort();
1203
1204     OMX_ERRORTYPE omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigBrcmAudioMaxSample, &param);
1205
1206     if(omx_err != OMX_ErrorNone)
1207     {
1208       CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigBrcmAudioMaxSample error 0x%08x\n",
1209         CLASSNAME, __func__, omx_err);
1210       return 0;
1211     }
1212   }
1213   pts = FromOMXTime(param.nTimeStamp);
1214   return (float)param.nMaxSample * (100.0f / (1<<15));
1215 }
1216
1217 void COMXAudio::SubmitEOS()
1218 {
1219   CSingleLock lock (m_critSection);
1220
1221   if(!m_Initialized)
1222     return;
1223
1224   m_submitted_eos = true;
1225   m_failed_eos = false;
1226
1227   OMX_ERRORTYPE omx_err = OMX_ErrorNone;
1228   OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000);
1229
1230   if(omx_buffer == NULL)
1231   {
1232     CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
1233     m_failed_eos = true;
1234     return;
1235   }
1236
1237   omx_buffer->nOffset     = 0;
1238   omx_buffer->nFilledLen  = 0;
1239   omx_buffer->nTimeStamp  = ToOMXTime(0LL);
1240
1241   omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
1242
1243   omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
1244   if (omx_err != OMX_ErrorNone)
1245   {
1246     CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
1247     return;
1248   }
1249   CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
1250 }
1251
1252 bool COMXAudio::IsEOS()
1253 {
1254   if(!m_Initialized)
1255     return true;
1256   unsigned int latency = GetAudioRenderingLatency();
1257   CSingleLock lock (m_critSection);
1258
1259   if (!m_failed_eos && !(m_omx_decoder.IsEOS() && latency == 0))
1260     return false;
1261
1262   if (m_submitted_eos)
1263   {
1264     CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
1265     m_submitted_eos = false;
1266   }
1267   return true;
1268 }
1269
1270 void COMXAudio::SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers)
1271 {
1272     return ;
1273 }
1274
1275 void COMXAudio::SetCodingType(AEDataFormat dataFormat)
1276 {
1277   switch(dataFormat)
1278   { 
1279     case AE_FMT_DTS:
1280       CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDTS\n");
1281       m_eEncoding = OMX_AUDIO_CodingDTS;
1282       break;
1283     case AE_FMT_AC3:
1284     case AE_FMT_EAC3:
1285       CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDDP\n");
1286       m_eEncoding = OMX_AUDIO_CodingDDP;
1287       break;
1288     default:
1289       CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingPCM\n");
1290       m_eEncoding = OMX_AUDIO_CodingPCM;
1291       break;
1292   } 
1293 }
1294
1295 bool COMXAudio::CanHWDecode(AVCodecID codec)
1296 {
1297   bool ret = false;
1298   switch(codec)
1299   { 
1300     case AV_CODEC_ID_DTS:
1301       CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDTS\n");
1302       ret = true;
1303       break;
1304     case AV_CODEC_ID_AC3:
1305     case AV_CODEC_ID_EAC3:
1306       CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDDP\n");
1307       ret = true;
1308       break;
1309     default:
1310       CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingPCM\n");
1311       ret = false;
1312       break;
1313   } 
1314
1315   return ret;
1316 }
1317
1318 void COMXAudio::PrintChannels(OMX_AUDIO_CHANNELTYPE eChannelMapping[])
1319 {
1320   for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
1321   {
1322     switch(eChannelMapping[i])
1323     {
1324       case OMX_AUDIO_ChannelLF:
1325         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLF\n");
1326         break;
1327       case OMX_AUDIO_ChannelRF:
1328         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRF\n");
1329         break;
1330       case OMX_AUDIO_ChannelCF:
1331         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCF\n");
1332         break;
1333       case OMX_AUDIO_ChannelLS:
1334         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLS\n");
1335         break;
1336       case OMX_AUDIO_ChannelRS:
1337         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRS\n");
1338         break;
1339       case OMX_AUDIO_ChannelLFE:
1340         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLFE\n");
1341         break;
1342       case OMX_AUDIO_ChannelCS:
1343         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCS\n");
1344         break;
1345       case OMX_AUDIO_ChannelLR:
1346         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLR\n");
1347         break;
1348       case OMX_AUDIO_ChannelRR:
1349         CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRR\n");
1350         break;
1351       case OMX_AUDIO_ChannelNone:
1352       case OMX_AUDIO_ChannelKhronosExtensions:
1353       case OMX_AUDIO_ChannelVendorStartUnused:
1354       case OMX_AUDIO_ChannelMax:
1355       default:
1356         break;
1357     }
1358   }
1359 }
1360
1361 void COMXAudio::PrintPCM(OMX_AUDIO_PARAM_PCMMODETYPE *pcm, std::string direction)
1362 {
1363   CLog::Log(LOGDEBUG, "pcm->direction      : %s\n", direction.c_str());
1364   CLog::Log(LOGDEBUG, "pcm->nPortIndex     : %d\n", (int)pcm->nPortIndex);
1365   CLog::Log(LOGDEBUG, "pcm->eNumData       : %d\n", pcm->eNumData);
1366   CLog::Log(LOGDEBUG, "pcm->eEndian        : %d\n", pcm->eEndian);
1367   CLog::Log(LOGDEBUG, "pcm->bInterleaved   : %d\n", (int)pcm->bInterleaved);
1368   CLog::Log(LOGDEBUG, "pcm->nBitPerSample  : %d\n", (int)pcm->nBitPerSample);
1369   CLog::Log(LOGDEBUG, "pcm->ePCMMode       : %d\n", pcm->ePCMMode);
1370   CLog::Log(LOGDEBUG, "pcm->nChannels      : %d\n", (int)pcm->nChannels);
1371   CLog::Log(LOGDEBUG, "pcm->nSamplingRate  : %d\n", (int)pcm->nSamplingRate);
1372
1373   PrintChannels(pcm->eChannelMapping);
1374 }
1375
1376 void COMXAudio::PrintDDP(OMX_AUDIO_PARAM_DDPTYPE *ddparm)
1377 {
1378   CLog::Log(LOGDEBUG, "ddparm->nPortIndex         : %d\n", (int)ddparm->nPortIndex);
1379   CLog::Log(LOGDEBUG, "ddparm->nChannels          : %d\n", (int)ddparm->nChannels);
1380   CLog::Log(LOGDEBUG, "ddparm->nBitRate           : %d\n", (int)ddparm->nBitRate);
1381   CLog::Log(LOGDEBUG, "ddparm->nSampleRate        : %d\n", (int)ddparm->nSampleRate);
1382   CLog::Log(LOGDEBUG, "ddparm->eBitStreamId       : %d\n", (int)ddparm->eBitStreamId);
1383   CLog::Log(LOGDEBUG, "ddparm->eBitStreamMode     : %d\n", (int)ddparm->eBitStreamMode);
1384   CLog::Log(LOGDEBUG, "ddparm->eDolbySurroundMode : %d\n", (int)ddparm->eDolbySurroundMode);
1385
1386   PrintChannels(ddparm->eChannelMapping);
1387 }
1388
1389 void COMXAudio::PrintDTS(OMX_AUDIO_PARAM_DTSTYPE *dtsparam)
1390 {
1391   CLog::Log(LOGDEBUG, "dtsparam->nPortIndex         : %d\n", (int)dtsparam->nPortIndex);
1392   CLog::Log(LOGDEBUG, "dtsparam->nChannels          : %d\n", (int)dtsparam->nChannels);
1393   CLog::Log(LOGDEBUG, "dtsparam->nBitRate           : %d\n", (int)dtsparam->nBitRate);
1394   CLog::Log(LOGDEBUG, "dtsparam->nSampleRate        : %d\n", (int)dtsparam->nSampleRate);
1395   CLog::Log(LOGDEBUG, "dtsparam->nFormat            : 0x%08x\n", (int)dtsparam->nFormat);
1396   CLog::Log(LOGDEBUG, "dtsparam->nDtsType           : %d\n", (int)dtsparam->nDtsType);
1397   CLog::Log(LOGDEBUG, "dtsparam->nDtsFrameSizeBytes : %d\n", (int)dtsparam->nDtsFrameSizeBytes);
1398
1399   PrintChannels(dtsparam->eChannelMapping);
1400 }
1401
1402 /* ========================== SYNC FUNCTIONS ========================== */
1403 unsigned int COMXAudio::SyncDTS(BYTE* pData, unsigned int iSize)
1404 {
1405   OMX_INIT_STRUCTURE(m_dtsParam);
1406
1407   unsigned int skip;
1408   unsigned int srCode;
1409   unsigned int dtsBlocks;
1410   bool littleEndian;
1411
1412   for(skip = 0; iSize - skip > 8; ++skip, ++pData)
1413   {
1414     if (pData[0] == 0x7F && pData[1] == 0xFE && pData[2] == 0x80 && pData[3] == 0x01) 
1415     {
1416       /* 16bit le */
1417       littleEndian = true; 
1418       dtsBlocks    = ((pData[4] >> 2) & 0x7f) + 1;
1419       m_dtsParam.nFormat = 0x1 | 0x2;
1420     }
1421     else if (pData[0] == 0x1F && pData[1] == 0xFF && pData[2] == 0xE8 && pData[3] == 0x00 && pData[4] == 0x07 && (pData[5] & 0xF0) == 0xF0) 
1422     {
1423       /* 14bit le */
1424       littleEndian = true;
1425       dtsBlocks    = (((pData[4] & 0x7) << 4) | (pData[7] & 0x3C) >> 2) + 1;
1426       m_dtsParam.nFormat = 0x1 | 0x0;
1427     }
1428     else if (pData[1] == 0x7F && pData[0] == 0xFE && pData[3] == 0x80 && pData[2] == 0x01) 
1429     {
1430       /* 16bit be */ 
1431       littleEndian = false;
1432       dtsBlocks    = ((pData[5] >> 2) & 0x7f) + 1;
1433       m_dtsParam.nFormat = 0x0 | 0x2;
1434     }
1435     else if (pData[1] == 0x1F && pData[0] == 0xFF && pData[3] == 0xE8 && pData[2] == 0x00 && pData[5] == 0x07 && (pData[4] & 0xF0) == 0xF0) 
1436     {
1437       /* 14bit be */
1438       littleEndian = false; 
1439       dtsBlocks    = (((pData[5] & 0x7) << 4) | (pData[6] & 0x3C) >> 2) + 1;
1440       m_dtsParam.nFormat = 0x0 | 0x0;
1441     }
1442     else
1443     {
1444       continue;
1445     }
1446
1447     if (littleEndian)
1448     {
1449       /* if it is not a termination frame, check the next 6 bits are set */
1450       if ((pData[4] & 0x80) == 0x80 && (pData[4] & 0x7C) != 0x7C)
1451         continue;
1452
1453       /* get the frame size */
1454       m_dtsParam.nDtsFrameSizeBytes = ((((pData[5] & 0x3) << 8 | pData[6]) << 4) | ((pData[7] & 0xF0) >> 4)) + 1;
1455       srCode = (pData[8] & 0x3C) >> 2;
1456    }
1457    else
1458    {
1459       /* if it is not a termination frame, check the next 6 bits are set */
1460       if ((pData[5] & 0x80) == 0x80 && (pData[5] & 0x7C) != 0x7C)
1461         continue;
1462
1463       /* get the frame size */
1464       m_dtsParam.nDtsFrameSizeBytes = ((((pData[4] & 0x3) << 8 | pData[7]) << 4) | ((pData[6] & 0xF0) >> 4)) + 1;
1465       srCode = (pData[9] & 0x3C) >> 2;
1466    }
1467
1468     /* make sure the framesize is sane */
1469     if (m_dtsParam.nDtsFrameSizeBytes < 96 || m_dtsParam.nDtsFrameSizeBytes > 16384)
1470       continue;
1471
1472     m_dtsParam.nSampleRate = DTSFSCod[srCode];
1473
1474     switch(dtsBlocks << 5)
1475     {
1476       case 512 : 
1477         m_dtsParam.nDtsType = 1;
1478         break;
1479       case 1024: 
1480         m_dtsParam.nDtsType = 2;
1481         break;
1482       case 2048: 
1483         m_dtsParam.nDtsType = 3;
1484         break;
1485       default:
1486         m_dtsParam.nDtsType = 0;
1487         break;
1488     }
1489
1490     //m_dtsParam.nFormat = 1;
1491     m_dtsParam.nDtsType = 1;
1492
1493     m_LostSync = false;
1494
1495     return skip;
1496   }
1497
1498   m_LostSync = true;
1499   return iSize;
1500 }
1501
1502 unsigned int COMXAudio::SyncAC3(BYTE* pData, unsigned int iSize)
1503 {
1504   unsigned int skip = 0;
1505
1506   for(skip = 0; iSize - skip > 6; ++skip, ++pData)
1507   {
1508     /* search for an ac3 sync word */
1509     if(pData[0] != 0x0b || pData[1] != 0x77)
1510       continue;
1511
1512     uint8_t fscod      = pData[4] >> 6;
1513     uint8_t frmsizecod = pData[4] & 0x3F;
1514     uint8_t bsid       = pData[5] >> 3;
1515
1516     /* sanity checks on the header */
1517     if (
1518         fscod      ==   3 ||
1519         frmsizecod >   37 ||
1520         bsid       > 0x11
1521     ) continue;
1522
1523     /* get the details we need to check crc1 and framesize */
1524     uint16_t     bitrate   = AC3Bitrates[frmsizecod >> 1];
1525     unsigned int framesize = 0;
1526     switch(fscod)
1527     {
1528       case 0: framesize = bitrate * 2; break;
1529       case 1: framesize = (320 * bitrate / 147 + (frmsizecod & 1 ? 1 : 0)); break;
1530       case 2: framesize = bitrate * 4; break;
1531     }
1532
1533     m_SampleRate = AC3FSCod[fscod];
1534
1535     /* dont do extensive testing if we have not lost sync */
1536     if (!m_LostSync && skip == 0)
1537       return 0;
1538
1539     unsigned int crc_size;
1540     /* if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) */
1541     if (framesize <= iSize - skip)
1542          crc_size = framesize - 1;
1543     else crc_size = (framesize >> 1) + (framesize >> 3) - 1;
1544
1545     if (crc_size <= iSize - skip)
1546       if(m_dllAvUtil.av_crc(m_dllAvUtil.av_crc_get_table(AV_CRC_16_ANSI), 0, &pData[2], crc_size * 2))
1547         continue;
1548
1549     /* if we get here, we can sync */
1550     m_LostSync = false;
1551     return skip;
1552   }
1553
1554   /* if we get here, the entire packet is invalid and we have lost sync */
1555   m_LostSync = true;
1556   return iSize;
1557 }
1558
1559 void COMXAudio::CheckOutputBufferSize(void **buffer, int *oldSize, int newSize)
1560 {
1561   if (newSize > *oldSize)
1562   {
1563     if (*buffer)
1564       _aligned_free(*buffer);
1565     *buffer = _aligned_malloc(newSize, 16);
1566     *oldSize = newSize;
1567   }
1568   memset(*buffer, 0x0, *oldSize);
1569 }
1570
1571 void COMXAudio::BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout)
1572 {
1573   int index = 0;
1574   if (layout & AV_CH_FRONT_LEFT           ) channelMap[index++] = PCM_FRONT_LEFT           ;
1575   if (layout & AV_CH_FRONT_RIGHT          ) channelMap[index++] = PCM_FRONT_RIGHT          ;
1576   if (layout & AV_CH_FRONT_CENTER         ) channelMap[index++] = PCM_FRONT_CENTER         ;
1577   if (layout & AV_CH_LOW_FREQUENCY        ) channelMap[index++] = PCM_LOW_FREQUENCY        ;
1578   if (layout & AV_CH_BACK_LEFT            ) channelMap[index++] = PCM_BACK_LEFT            ;
1579   if (layout & AV_CH_BACK_RIGHT           ) channelMap[index++] = PCM_BACK_RIGHT           ;
1580   if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
1581   if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
1582   if (layout & AV_CH_BACK_CENTER          ) channelMap[index++] = PCM_BACK_CENTER          ;
1583   if (layout & AV_CH_SIDE_LEFT            ) channelMap[index++] = PCM_SIDE_LEFT            ;
1584   if (layout & AV_CH_SIDE_RIGHT           ) channelMap[index++] = PCM_SIDE_RIGHT           ;
1585   if (layout & AV_CH_TOP_CENTER           ) channelMap[index++] = PCM_TOP_CENTER           ;
1586   if (layout & AV_CH_TOP_FRONT_LEFT       ) channelMap[index++] = PCM_TOP_FRONT_LEFT       ;
1587   if (layout & AV_CH_TOP_FRONT_CENTER     ) channelMap[index++] = PCM_TOP_FRONT_CENTER     ;
1588   if (layout & AV_CH_TOP_FRONT_RIGHT      ) channelMap[index++] = PCM_TOP_FRONT_RIGHT      ;
1589   if (layout & AV_CH_TOP_BACK_LEFT        ) channelMap[index++] = PCM_TOP_BACK_LEFT        ;
1590   if (layout & AV_CH_TOP_BACK_CENTER      ) channelMap[index++] = PCM_TOP_BACK_CENTER      ;
1591   if (layout & AV_CH_TOP_BACK_RIGHT       ) channelMap[index++] = PCM_TOP_BACK_RIGHT       ;
1592   while (index<OMX_AUDIO_MAXCHANNELS)
1593     channelMap[index++] = PCM_INVALID;
1594 }
1595
1596 // See CEA spec: Table 20, Audio InfoFrame data byte 4 for the ordering here
1597 int COMXAudio::BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout)
1598 {
1599   int index = 0;
1600   if (layout & AV_CH_FRONT_LEFT           ) channelMap[index++] = PCM_FRONT_LEFT;
1601   if (layout & AV_CH_FRONT_RIGHT          ) channelMap[index++] = PCM_FRONT_RIGHT;
1602   if (layout & AV_CH_LOW_FREQUENCY        ) channelMap[index++] = PCM_LOW_FREQUENCY;
1603   if (layout & AV_CH_FRONT_CENTER         ) channelMap[index++] = PCM_FRONT_CENTER;
1604   if (layout & AV_CH_BACK_LEFT            ) channelMap[index++] = PCM_BACK_LEFT;
1605   if (layout & AV_CH_BACK_RIGHT           ) channelMap[index++] = PCM_BACK_RIGHT;
1606   if (layout & AV_CH_SIDE_LEFT            ) channelMap[index++] = PCM_SIDE_LEFT;
1607   if (layout & AV_CH_SIDE_RIGHT           ) channelMap[index++] = PCM_SIDE_RIGHT;
1608
1609   while (index<OMX_AUDIO_MAXCHANNELS)
1610     channelMap[index++] = PCM_INVALID;
1611
1612   int num_channels = 0;
1613   for (index=0; index<OMX_AUDIO_MAXCHANNELS; index++)
1614     if (channelMap[index] != PCM_INVALID)
1615        num_channels = index+1;
1616   return num_channels;
1617 }
1618
1619 void COMXAudio::BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE * channelMap, uint64_t layout)
1620 {
1621   int index = 0;
1622
1623   if (layout & AV_CH_FRONT_LEFT           ) channelMap[index++] = OMX_AUDIO_ChannelLF;
1624   if (layout & AV_CH_FRONT_RIGHT          ) channelMap[index++] = OMX_AUDIO_ChannelRF;
1625   if (layout & AV_CH_FRONT_CENTER         ) channelMap[index++] = OMX_AUDIO_ChannelCF;
1626   if (layout & AV_CH_LOW_FREQUENCY        ) channelMap[index++] = OMX_AUDIO_ChannelLFE;
1627   if (layout & AV_CH_BACK_LEFT            ) channelMap[index++] = OMX_AUDIO_ChannelLR;
1628   if (layout & AV_CH_BACK_RIGHT           ) channelMap[index++] = OMX_AUDIO_ChannelRR;
1629   if (layout & AV_CH_SIDE_LEFT            ) channelMap[index++] = OMX_AUDIO_ChannelLS;
1630   if (layout & AV_CH_SIDE_RIGHT           ) channelMap[index++] = OMX_AUDIO_ChannelRS;
1631   if (layout & AV_CH_BACK_CENTER          ) channelMap[index++] = OMX_AUDIO_ChannelCS;
1632   // following are not in openmax spec, but gpu does accept them
1633   if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)10;
1634   if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)11;
1635   if (layout & AV_CH_TOP_CENTER           ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)12;
1636   if (layout & AV_CH_TOP_FRONT_LEFT       ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)13;
1637   if (layout & AV_CH_TOP_FRONT_CENTER     ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)14;
1638   if (layout & AV_CH_TOP_FRONT_RIGHT      ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)15;
1639   if (layout & AV_CH_TOP_BACK_LEFT        ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)16;
1640   if (layout & AV_CH_TOP_BACK_CENTER      ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)17;
1641   if (layout & AV_CH_TOP_BACK_RIGHT       ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)18;
1642
1643   while (index<OMX_AUDIO_MAXCHANNELS)
1644     channelMap[index++] = OMX_AUDIO_ChannelNone;
1645 }
1646
1647 uint64_t COMXAudio::GetChannelLayout(enum PCMLayout layout)
1648 {
1649   uint64_t layouts[] = {
1650     /* 2.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT,
1651     /* 2.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_LOW_FREQUENCY,
1652     /* 3.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER,
1653     /* 3.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_LOW_FREQUENCY,
1654     /* 4.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
1655     /* 4.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY,
1656     /* 5.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
1657     /* 5.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY,
1658     /* 7.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_SIDE_LEFT | 1<<PCM_SIDE_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
1659     /* 7.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_SIDE_LEFT | 1<<PCM_SIDE_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY
1660   };
1661   return (int)layout < 10 ? layouts[(int)layout] : 0;
1662 }
1663
1664 CAEChannelInfo COMXAudio::GetAEChannelLayout(uint64_t layout)
1665 {
1666   CAEChannelInfo m_channelLayout;
1667   m_channelLayout.Reset();
1668
1669   if (layout & AV_CH_FRONT_LEFT           ) m_channelLayout += AE_CH_FL  ;
1670   if (layout & AV_CH_FRONT_RIGHT          ) m_channelLayout += AE_CH_FR  ;
1671   if (layout & AV_CH_FRONT_CENTER         ) m_channelLayout += AE_CH_FC  ;
1672   if (layout & AV_CH_LOW_FREQUENCY        ) m_channelLayout += AE_CH_LFE ;
1673   if (layout & AV_CH_BACK_LEFT            ) m_channelLayout += AE_CH_BL  ;
1674   if (layout & AV_CH_BACK_RIGHT           ) m_channelLayout += AE_CH_BR  ;
1675   if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelLayout += AE_CH_FLOC;
1676   if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelLayout += AE_CH_FROC;
1677   if (layout & AV_CH_BACK_CENTER          ) m_channelLayout += AE_CH_BC  ;
1678   if (layout & AV_CH_SIDE_LEFT            ) m_channelLayout += AE_CH_SL  ;
1679   if (layout & AV_CH_SIDE_RIGHT           ) m_channelLayout += AE_CH_SR  ;
1680   if (layout & AV_CH_TOP_CENTER           ) m_channelLayout += AE_CH_TC  ;
1681   if (layout & AV_CH_TOP_FRONT_LEFT       ) m_channelLayout += AE_CH_TFL ;
1682   if (layout & AV_CH_TOP_FRONT_CENTER     ) m_channelLayout += AE_CH_TFC ;
1683   if (layout & AV_CH_TOP_FRONT_RIGHT      ) m_channelLayout += AE_CH_TFR ;
1684   if (layout & AV_CH_TOP_BACK_LEFT        ) m_channelLayout += AE_CH_BL  ;
1685   if (layout & AV_CH_TOP_BACK_CENTER      ) m_channelLayout += AE_CH_BC  ;
1686   if (layout & AV_CH_TOP_BACK_RIGHT       ) m_channelLayout += AE_CH_BR  ;
1687   return m_channelLayout;
1688 }