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
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)
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.
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/>.
23 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
25 #elif defined(TARGET_WINDOWS)
30 #include "Application.h"
31 #include "utils/log.h"
33 #define CLASSNAME "COMXAudio"
35 #include "linux/XMemUtils.h"
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"
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};
49 static const uint16_t DTSFSCod [] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0};
51 //////////////////////////////////////////////////////////////////////
52 // Construction/Destruction
53 //////////////////////////////////////////////////////////////////////
54 //***********************************************************************************************
55 COMXAudio::COMXAudio() :
57 m_Initialized (false ),
61 m_Passthrough (false ),
67 m_OutputChannels (0 ),
70 m_amplification (1.0f ),
71 m_attenuation (1.0f ),
75 m_settings_changed(false ),
76 m_setStartTime (false ),
79 m_eEncoding (OMX_AUDIO_CodingPCM),
82 m_last_pts (DVD_NOPTS_VALUE),
83 m_submitted_eos (false ),
86 CAEFactory::Suspend();
87 while (!CAEFactory::IsSuspended())
91 COMXAudio::~COMXAudio()
98 bool COMXAudio::PortSettingsChanged()
100 CSingleLock lock (m_critSection);
101 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
103 if (m_settings_changed)
105 m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
106 m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
112 if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit))
115 if(CSettings::Get().GetBool("audiooutput.dualaudio"))
117 if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
120 if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue")
122 if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
125 if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue")
127 if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
131 SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
134 if( m_omx_mixer.IsInitialized() )
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)
142 CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder GetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
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"));
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)
156 CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
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"));
164 if( m_omx_splitter.IsInitialized() )
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)
170 CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
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)
178 CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
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)
185 CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
190 if( m_omx_render_analog.IsInitialized() )
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)
196 CLog::Log(LOGERROR, "%s::%s - error m_omx_render_analog SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
201 if( m_omx_render_hdmi.IsInitialized() )
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)
207 CLog::Log(LOGERROR, "%s::%s - error m_omx_render_hdmi SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
212 if( m_omx_render_analog.IsInitialized() )
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);
217 omx_err = m_omx_tunnel_clock_analog.Establish();
218 if(omx_err != OMX_ErrorNone)
220 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_analog.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
223 m_omx_render_analog.ResetEos();
225 if( m_omx_render_hdmi.IsInitialized() )
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);
230 omx_err = m_omx_tunnel_clock_hdmi.Establish();
231 if(omx_err != OMX_ErrorNone)
233 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_hdmi.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
236 m_omx_render_hdmi.ResetEos();
239 if( m_omx_render_analog.IsInitialized() )
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"))
245 OMX_CONFIG_BOOLEANTYPE configBool;
246 OMX_INIT_STRUCTURE(configBool);
247 configBool.bEnabled = OMX_FALSE;
249 omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
250 if (omx_err != OMX_ErrorNone)
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)
260 CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
265 if( m_omx_render_hdmi.IsInitialized() )
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"))
271 OMX_CONFIG_BOOLEANTYPE configBool;
272 OMX_INIT_STRUCTURE(configBool);
273 configBool.bEnabled = OMX_FALSE;
275 omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
276 if (omx_err != OMX_ErrorNone)
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)
286 CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
291 if( m_omx_splitter.IsInitialized() )
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)
297 CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_analog.Establish 0x%08x", omx_err);
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)
305 CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_hdmi.Establish 0x%08x", omx_err);
309 if( m_omx_mixer.IsInitialized() )
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() )
314 m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_splitter, m_omx_splitter.GetInputPort());
318 if( m_omx_render_analog.IsInitialized() )
320 m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
322 if( m_omx_render_hdmi.IsInitialized() )
324 m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
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);
332 if( m_omx_render_analog.IsInitialized() )
334 m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
336 else if( m_omx_render_hdmi.IsInitialized() )
338 m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
340 CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d passthrough", CLASSNAME, __func__,
344 omx_err = m_omx_tunnel_decoder.Establish();
345 if(omx_err != OMX_ErrorNone)
347 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
351 if( m_omx_mixer.IsInitialized() )
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);
360 if( m_omx_mixer.IsInitialized() )
362 omx_err = m_omx_tunnel_mixer.Establish();
363 if(omx_err != OMX_ErrorNone)
365 CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
370 if( m_omx_splitter.IsInitialized() )
372 omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting);
373 if(omx_err != OMX_ErrorNone)
375 CLog::Log(LOGERROR, "%s::%s - m_omx_splitter OMX_StateExecuting 0x%08x", CLASSNAME, __func__, omx_err);
379 if( m_omx_render_analog.IsInitialized() )
381 omx_err = m_omx_render_analog.SetStateForComponent(OMX_StateExecuting);
382 if(omx_err != OMX_ErrorNone)
384 CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
388 if( m_omx_render_hdmi.IsInitialized() )
390 omx_err = m_omx_render_hdmi.SetStateForComponent(OMX_StateExecuting);
391 if(omx_err != OMX_ErrorNone)
393 CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
398 m_settings_changed = true;
402 static unsigned count_bits(int64_t value)
410 bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, uint64_t channelMap, bool bUsePassthrough, bool bUseHWDecode)
412 CSingleLock lock (m_critSection);
413 OMX_ERRORTYPE omx_err;
417 if(!m_dllAvUtil.Load())
420 m_HWDecode = bUseHWDecode;
421 m_Passthrough = bUsePassthrough;
423 m_InputChannels = count_bits(channelMap);
426 if(m_InputChannels == 0)
429 if(hints.samplerate == 0)
437 /* passthrough overwrites hw decode */
444 /* check again if we are capable to hw decode the format */
445 m_HWDecode = CanHWDecode(hints.codec);
447 SetCodingType(format.m_dataFormat);
449 if(hints.extrasize > 0 && hints.extradata != NULL)
451 m_extrasize = hints.extrasize;
452 m_extradata = (uint8_t *)malloc(m_extrasize);
453 memcpy(m_extradata, hints.extradata, hints.extrasize);
456 m_omx_clock = m_av_clock->GetOMXClock();
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));
464 m_wave_header.Format.nChannels = 2;
465 m_wave_header.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
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;
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));
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));
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;
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;
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;
521 if(!m_omx_decoder.Initialize("OMX.broadcom.audio_decode", OMX_IndexParamAudioInit))
524 OMX_CONFIG_BOOLEANTYPE boolType;
525 OMX_INIT_STRUCTURE(boolType);
527 boolType.bEnabled = OMX_TRUE;
529 boolType.bEnabled = OMX_FALSE;
530 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmDecoderPassThrough, &boolType);
531 if(omx_err != OMX_ErrorNone)
533 CLog::Log(LOGERROR, "COMXAudio::Initialize - Error OMX_IndexParamBrcmDecoderPassThrough 0x%08x", omx_err);
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();
542 omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
543 if(omx_err != OMX_ErrorNone)
545 CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)\n", omx_err);
549 port_param.format.audio.eEncoding = m_eEncoding;
551 port_param.nBufferSize = m_ChunkLen;
552 port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, 16U);
554 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
555 if(omx_err != OMX_ErrorNone)
557 CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (intput) omx_err(0x%08x)\n", omx_err);
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();
565 omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
566 if(omx_err != OMX_ErrorNone)
568 CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
572 port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, m_BufferLen / port_param.nBufferSize);
574 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
575 if(omx_err != OMX_ErrorNone)
577 CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
582 OMX_AUDIO_PARAM_PORTFORMATTYPE formatType;
583 OMX_INIT_STRUCTURE(formatType);
584 formatType.nPortIndex = m_omx_decoder.GetInputPort();
586 formatType.eEncoding = m_eEncoding;
588 omx_err = m_omx_decoder.SetParameter(OMX_IndexParamAudioPortFormat, &formatType);
589 if(omx_err != OMX_ErrorNone)
591 CLog::Log(LOGERROR, "COMXAudio::Initialize error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
596 omx_err = m_omx_decoder.AllocInputBuffers();
597 if(omx_err != OMX_ErrorNone)
599 CLog::Log(LOGERROR, "COMXAudio::Initialize - Error alloc buffers 0x%08x", omx_err);
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);
610 if(m_eEncoding == OMX_AUDIO_CodingPCM)
612 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
613 if(omx_buffer == NULL)
615 CLog::Log(LOGERROR, "COMXAudio::Initialize - buffer error 0x%08x", omx_err);
619 omx_buffer->nOffset = 0;
620 omx_buffer->nFilledLen = sizeof(m_wave_header);
621 if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
623 CLog::Log(LOGERROR, "COMXAudio::Initialize - omx_buffer->nFilledLen > omx_buffer->nAllocLen");
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;
630 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
631 if (omx_err != OMX_ErrorNone)
633 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
639 // send decoder config
640 if(m_extrasize > 0 && m_extradata != NULL)
642 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
644 if(omx_buffer == NULL)
646 CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
650 omx_buffer->nOffset = 0;
651 omx_buffer->nFilledLen = m_extrasize;
652 if(omx_buffer->nFilledLen > omx_buffer->nAllocLen)
654 CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__);
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;
662 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
663 if (omx_err != OMX_ErrorNone)
665 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
671 /* return on decoder error so m_Initialized stays false */
672 if(m_omx_decoder.BadState())
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;
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);
693 //***********************************************************************************************
694 bool COMXAudio::Deinitialize()
696 CSingleLock lock (m_critSection);
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();
703 // ignore expected errors on teardown
704 if ( m_omx_mixer.IsInitialized() )
705 m_omx_mixer.IgnoreNextError(OMX_ErrorPortUnpopulated);
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);
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();
722 m_omx_decoder.FlushInput();
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();
740 m_Initialized = false;
749 m_dllAvUtil.Unload();
751 while(!m_ampqueue.empty())
752 m_ampqueue.pop_front();
754 m_last_pts = DVD_NOPTS_VALUE;
761 void COMXAudio::Flush()
763 CSingleLock lock (m_critSection);
767 m_omx_decoder.FlushAll();
769 if ( m_omx_mixer.IsInitialized() )
770 m_omx_mixer.FlushAll();
772 if ( m_omx_splitter.IsInitialized() )
773 m_omx_splitter.FlushAll();
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();
780 m_last_pts = DVD_NOPTS_VALUE;
784 m_setStartTime = true;
787 //***********************************************************************************************
788 void COMXAudio::SetDynamicRangeCompression(long drc)
790 CSingleLock lock (m_critSection);
791 m_amplification = powf(10.0f, (float)drc / 2000.0f);
792 if (m_settings_changed)
796 //***********************************************************************************************
797 void COMXAudio::SetMute(bool bMute)
799 CSingleLock lock (m_critSection);
801 if (m_settings_changed)
805 //***********************************************************************************************
806 void COMXAudio::SetVolume(float fVolume)
808 CSingleLock lock (m_critSection);
809 m_CurrentVolume = fVolume;
810 if (m_settings_changed)
814 //***********************************************************************************************
815 bool COMXAudio::ApplyVolume(void)
817 CSingleLock lock (m_critSection);
819 if (!m_Initialized || m_Passthrough)
822 float fVolume = m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
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);
827 const float* coeff = m_downmix_matrix;
829 OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix;
830 OMX_INIT_STRUCTURE(mix);
831 OMX_ERRORTYPE omx_err;
833 assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64);
835 if (m_amplification != 1.0)
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));
841 mix.nPortIndex = m_omx_decoder.GetInputPort();
842 omx_err = m_omx_decoder.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
843 if(omx_err != OMX_ErrorNone)
845 CLog::Log(LOGERROR, "%s::%s - error setting decoder OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
846 CLASSNAME, __func__, omx_err);
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));
853 mix.nPortIndex = m_omx_mixer.GetInputPort();
854 omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
855 if(omx_err != OMX_ErrorNone)
857 CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
858 CLASSNAME, __func__, omx_err);
861 CLog::Log(LOGINFO, "%s::%s - Volume=%.2f (* %.2f * %.2f)\n", CLASSNAME, __func__, fVolume, m_amplification, m_attenuation);
865 //***********************************************************************************************
866 unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
868 return AddPackets(data, len, 0, 0);
871 //***********************************************************************************************
872 unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts)
874 CSingleLock lock (m_critSection);
878 CLog::Log(LOGERROR,"COMXAudio::AddPackets - sanity failed. no valid play handle!");
882 if(m_eEncoding == OMX_AUDIO_CodingDTS && m_LostSync && (m_Passthrough || m_HWDecode))
884 int skip = SyncDTS((uint8_t *)data, len);
889 if(m_eEncoding == OMX_AUDIO_CodingDDP && m_LostSync && (m_Passthrough || m_HWDecode))
891 int skip = SyncAC3((uint8_t *)data, len);
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;
901 OMX_ERRORTYPE omx_err;
903 OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
905 while(demuxer_samples_sent < demuxer_samples)
908 omx_buffer = m_omx_decoder.GetInputBuffer(200);
910 if(omx_buffer == NULL)
912 CLog::Log(LOGERROR, "COMXAudio::Decode timeout\n");
916 omx_buffer->nOffset = 0;
917 omx_buffer->nFlags = 0;
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);
923 omx_buffer->nFilledLen = samples * pitch;
925 if (samples < demuxer_samples && m_BitsPerSample==32 && !(m_Passthrough || m_HWDecode))
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++)
932 memcpy(dst, src, omx_buffer->nFilledLen / m_InputChannels);
933 dst += omx_buffer->nFilledLen / m_InputChannels;
934 src += demuxer_samples * (m_BitsPerSample >> 3);
936 assert(dst <= omx_buffer->pBuffer + m_ChunkLen);
940 uint8_t *dst = omx_buffer->pBuffer;
941 uint8_t *src = demuxer_content + demuxer_samples_sent * pitch;
942 memcpy(dst, src, omx_buffer->nFilledLen);
945 uint64_t val = (uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts;
949 omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
950 if(pts == DVD_NOPTS_VALUE)
951 omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
955 CLog::Log(LOGDEBUG, "COMXAudio::Decode ADec : setStartTime %f\n", (float)val / DVD_TIME_BASE);
956 m_setStartTime = false;
960 if(pts == DVD_NOPTS_VALUE)
962 omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
965 else if (m_last_pts != pts)
970 omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;;
972 else if (m_last_pts == pts)
974 omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
978 omx_buffer->nTimeStamp = ToOMXTime(val);
980 demuxer_samples_sent += samples;
982 if(demuxer_samples_sent == demuxer_samples)
983 omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
988 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
989 if (omx_err == OMX_ErrorNone)
991 //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len);
996 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
1001 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__);
1006 omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0);
1007 if (omx_err == OMX_ErrorNone)
1009 if(!PortSettingsChanged())
1011 CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err);
1015 m_submitted += (float)demuxer_samples / m_SampleRate;
1016 if (m_amplification != 1.0)
1017 UpdateAttenuation();
1021 void COMXAudio::UpdateAttenuation()
1023 // always called with m_critSection lock held
1024 if (!m_Initialized || m_Passthrough)
1027 if (m_amplification == 1.0)
1033 double level_pts = 0.0;
1034 float level = GetMaxLevel(level_pts);
1035 if (level_pts != 0.0)
1040 m_ampqueue.push_back(v);
1042 double stamp = m_av_clock->OMXMediaTime();
1043 // discard too old data
1044 while(!m_ampqueue.empty())
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();
1052 float maxlevel = 0.0f, imminent_maxlevel = 0.0f;
1053 for (int i=0; i < (int)m_ampqueue.size(); i++)
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);
1062 if (maxlevel != 0.0)
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
1076 m_maxLevel = decay * m_maxLevel + (1.0f-decay ) * maxlevel;
1078 // want m_maxLevel * amp -> 1.0
1079 float amp = m_amplification * m_attenuation;
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;
1088 m_attenuation = 1.0f/m_amplification;
1093 //***********************************************************************************************
1094 unsigned int COMXAudio::GetSpace()
1096 int free = m_omx_decoder.GetInputBufferSpace();
1100 float COMXAudio::GetDelay()
1102 unsigned int free = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
1103 return m_BytesPerSec ? (float)free / (float)m_BytesPerSec : 0.0f;
1106 float COMXAudio::GetCacheTime()
1108 float fBufferLenFull = (float)m_BufferLen - (float)GetSpace();
1109 if(fBufferLenFull < 0)
1111 float ret = m_BytesPerSec ? fBufferLenFull / (float)m_BytesPerSec : 0.0f;
1115 float COMXAudio::GetCacheTotal()
1117 return m_BytesPerSec ? (float)m_BufferLen / (float)m_BytesPerSec : 0.0f;
1120 //***********************************************************************************************
1121 unsigned int COMXAudio::GetChunkLen()
1125 //***********************************************************************************************
1126 int COMXAudio::SetPlaySpeed(int iSpeed)
1131 void COMXAudio::RegisterAudioCallback(IAudioCallback *pCallback)
1133 CSingleLock lock (m_critSection);
1134 if(!m_Passthrough && !m_HWDecode)
1136 m_pCallback = pCallback;
1138 m_pCallback->OnInitialize(2, m_SampleRate, 32);
1144 void COMXAudio::UnRegisterAudioCallback()
1146 CSingleLock lock (m_critSection);
1150 unsigned int COMXAudio::GetAudioRenderingLatency()
1152 CSingleLock lock (m_critSection);
1157 OMX_PARAM_U32TYPE param;
1158 OMX_INIT_STRUCTURE(param);
1160 if(m_omx_render_analog.IsInitialized())
1162 param.nPortIndex = m_omx_render_analog.GetInputPort();
1164 OMX_ERRORTYPE omx_err = m_omx_render_analog.GetConfig(OMX_IndexConfigAudioRenderingLatency, ¶m);
1166 if(omx_err != OMX_ErrorNone)
1168 CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
1169 CLASSNAME, __func__, omx_err);
1173 else if(m_omx_render_hdmi.IsInitialized())
1175 param.nPortIndex = m_omx_render_hdmi.GetInputPort();
1177 OMX_ERRORTYPE omx_err = m_omx_render_hdmi.GetConfig(OMX_IndexConfigAudioRenderingLatency, ¶m);
1179 if(omx_err != OMX_ErrorNone)
1181 CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
1182 CLASSNAME, __func__, omx_err);
1190 float COMXAudio::GetMaxLevel(double &pts)
1192 CSingleLock lock (m_critSection);
1197 OMX_CONFIG_BRCMAUDIOMAXSAMPLE param;
1198 OMX_INIT_STRUCTURE(param);
1200 if(m_omx_decoder.IsInitialized())
1202 param.nPortIndex = m_omx_decoder.GetInputPort();
1204 OMX_ERRORTYPE omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigBrcmAudioMaxSample, ¶m);
1206 if(omx_err != OMX_ErrorNone)
1208 CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigBrcmAudioMaxSample error 0x%08x\n",
1209 CLASSNAME, __func__, omx_err);
1213 pts = FromOMXTime(param.nTimeStamp);
1214 return (float)param.nMaxSample * (100.0f / (1<<15));
1217 void COMXAudio::SubmitEOS()
1219 CSingleLock lock (m_critSection);
1224 m_submitted_eos = true;
1225 m_failed_eos = false;
1227 OMX_ERRORTYPE omx_err = OMX_ErrorNone;
1228 OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000);
1230 if(omx_buffer == NULL)
1232 CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
1233 m_failed_eos = true;
1237 omx_buffer->nOffset = 0;
1238 omx_buffer->nFilledLen = 0;
1239 omx_buffer->nTimeStamp = ToOMXTime(0LL);
1241 omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
1243 omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
1244 if (omx_err != OMX_ErrorNone)
1246 CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
1249 CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
1252 bool COMXAudio::IsEOS()
1256 unsigned int latency = GetAudioRenderingLatency();
1257 CSingleLock lock (m_critSection);
1259 if (!m_failed_eos && !(m_omx_decoder.IsEOS() && latency == 0))
1262 if (m_submitted_eos)
1264 CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
1265 m_submitted_eos = false;
1270 void COMXAudio::SwitchChannels(int iAudioStream, bool bAudioOnAllSpeakers)
1275 void COMXAudio::SetCodingType(AEDataFormat dataFormat)
1280 CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDTS\n");
1281 m_eEncoding = OMX_AUDIO_CodingDTS;
1285 CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDDP\n");
1286 m_eEncoding = OMX_AUDIO_CodingDDP;
1289 CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingPCM\n");
1290 m_eEncoding = OMX_AUDIO_CodingPCM;
1295 bool COMXAudio::CanHWDecode(AVCodecID codec)
1300 case AV_CODEC_ID_DTS:
1301 CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDTS\n");
1304 case AV_CODEC_ID_AC3:
1305 case AV_CODEC_ID_EAC3:
1306 CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDDP\n");
1310 CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingPCM\n");
1318 void COMXAudio::PrintChannels(OMX_AUDIO_CHANNELTYPE eChannelMapping[])
1320 for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
1322 switch(eChannelMapping[i])
1324 case OMX_AUDIO_ChannelLF:
1325 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLF\n");
1327 case OMX_AUDIO_ChannelRF:
1328 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRF\n");
1330 case OMX_AUDIO_ChannelCF:
1331 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCF\n");
1333 case OMX_AUDIO_ChannelLS:
1334 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLS\n");
1336 case OMX_AUDIO_ChannelRS:
1337 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRS\n");
1339 case OMX_AUDIO_ChannelLFE:
1340 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLFE\n");
1342 case OMX_AUDIO_ChannelCS:
1343 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCS\n");
1345 case OMX_AUDIO_ChannelLR:
1346 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLR\n");
1348 case OMX_AUDIO_ChannelRR:
1349 CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRR\n");
1351 case OMX_AUDIO_ChannelNone:
1352 case OMX_AUDIO_ChannelKhronosExtensions:
1353 case OMX_AUDIO_ChannelVendorStartUnused:
1354 case OMX_AUDIO_ChannelMax:
1361 void COMXAudio::PrintPCM(OMX_AUDIO_PARAM_PCMMODETYPE *pcm, std::string direction)
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);
1373 PrintChannels(pcm->eChannelMapping);
1376 void COMXAudio::PrintDDP(OMX_AUDIO_PARAM_DDPTYPE *ddparm)
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);
1386 PrintChannels(ddparm->eChannelMapping);
1389 void COMXAudio::PrintDTS(OMX_AUDIO_PARAM_DTSTYPE *dtsparam)
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);
1399 PrintChannels(dtsparam->eChannelMapping);
1402 /* ========================== SYNC FUNCTIONS ========================== */
1403 unsigned int COMXAudio::SyncDTS(BYTE* pData, unsigned int iSize)
1405 OMX_INIT_STRUCTURE(m_dtsParam);
1408 unsigned int srCode;
1409 unsigned int dtsBlocks;
1412 for(skip = 0; iSize - skip > 8; ++skip, ++pData)
1414 if (pData[0] == 0x7F && pData[1] == 0xFE && pData[2] == 0x80 && pData[3] == 0x01)
1417 littleEndian = true;
1418 dtsBlocks = ((pData[4] >> 2) & 0x7f) + 1;
1419 m_dtsParam.nFormat = 0x1 | 0x2;
1421 else if (pData[0] == 0x1F && pData[1] == 0xFF && pData[2] == 0xE8 && pData[3] == 0x00 && pData[4] == 0x07 && (pData[5] & 0xF0) == 0xF0)
1424 littleEndian = true;
1425 dtsBlocks = (((pData[4] & 0x7) << 4) | (pData[7] & 0x3C) >> 2) + 1;
1426 m_dtsParam.nFormat = 0x1 | 0x0;
1428 else if (pData[1] == 0x7F && pData[0] == 0xFE && pData[3] == 0x80 && pData[2] == 0x01)
1431 littleEndian = false;
1432 dtsBlocks = ((pData[5] >> 2) & 0x7f) + 1;
1433 m_dtsParam.nFormat = 0x0 | 0x2;
1435 else if (pData[1] == 0x1F && pData[0] == 0xFF && pData[3] == 0xE8 && pData[2] == 0x00 && pData[5] == 0x07 && (pData[4] & 0xF0) == 0xF0)
1438 littleEndian = false;
1439 dtsBlocks = (((pData[5] & 0x7) << 4) | (pData[6] & 0x3C) >> 2) + 1;
1440 m_dtsParam.nFormat = 0x0 | 0x0;
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)
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;
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)
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;
1468 /* make sure the framesize is sane */
1469 if (m_dtsParam.nDtsFrameSizeBytes < 96 || m_dtsParam.nDtsFrameSizeBytes > 16384)
1472 m_dtsParam.nSampleRate = DTSFSCod[srCode];
1474 switch(dtsBlocks << 5)
1477 m_dtsParam.nDtsType = 1;
1480 m_dtsParam.nDtsType = 2;
1483 m_dtsParam.nDtsType = 3;
1486 m_dtsParam.nDtsType = 0;
1490 //m_dtsParam.nFormat = 1;
1491 m_dtsParam.nDtsType = 1;
1502 unsigned int COMXAudio::SyncAC3(BYTE* pData, unsigned int iSize)
1504 unsigned int skip = 0;
1506 for(skip = 0; iSize - skip > 6; ++skip, ++pData)
1508 /* search for an ac3 sync word */
1509 if(pData[0] != 0x0b || pData[1] != 0x77)
1512 uint8_t fscod = pData[4] >> 6;
1513 uint8_t frmsizecod = pData[4] & 0x3F;
1514 uint8_t bsid = pData[5] >> 3;
1516 /* sanity checks on the header */
1523 /* get the details we need to check crc1 and framesize */
1524 uint16_t bitrate = AC3Bitrates[frmsizecod >> 1];
1525 unsigned int framesize = 0;
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;
1533 m_SampleRate = AC3FSCod[fscod];
1535 /* dont do extensive testing if we have not lost sync */
1536 if (!m_LostSync && skip == 0)
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;
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))
1549 /* if we get here, we can sync */
1554 /* if we get here, the entire packet is invalid and we have lost sync */
1559 void COMXAudio::CheckOutputBufferSize(void **buffer, int *oldSize, int newSize)
1561 if (newSize > *oldSize)
1564 _aligned_free(*buffer);
1565 *buffer = _aligned_malloc(newSize, 16);
1568 memset(*buffer, 0x0, *oldSize);
1571 void COMXAudio::BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout)
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;
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)
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;
1609 while (index<OMX_AUDIO_MAXCHANNELS)
1610 channelMap[index++] = PCM_INVALID;
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;
1619 void COMXAudio::BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE * channelMap, uint64_t layout)
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;
1643 while (index<OMX_AUDIO_MAXCHANNELS)
1644 channelMap[index++] = OMX_AUDIO_ChannelNone;
1647 uint64_t COMXAudio::GetChannelLayout(enum PCMLayout layout)
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
1661 return (int)layout < 10 ? layouts[(int)layout] : 0;
1664 CAEChannelInfo COMXAudio::GetAEChannelLayout(uint64_t layout)
1666 CAEChannelInfo m_channelLayout;
1667 m_channelLayout.Reset();
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;