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