OMXAudio.cpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. /*
  2. * XBMC Media Center
  3. * Copyright (c) 2002 d7o3g4q and RUNTiME
  4. * Portions Copyright (c) by the authors of ffmpeg and xvid
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #if (defined HAVE_CONFIG_H) && (!defined WIN32)
  21. #include "config.h"
  22. #elif defined(_WIN32)
  23. #include "system.h"
  24. #endif
  25. #include "OMXAudio.h"
  26. #include "utils/log.h"
  27. #define CLASSNAME "COMXAudio"
  28. #include "linux/XMemUtils.h"
  29. #ifndef VOLUME_MINIMUM
  30. #define VOLUME_MINIMUM 0
  31. #endif
  32. #include <algorithm>
  33. using namespace std;
  34. // the size of the audio_render output port buffers
  35. #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
  36. static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3};
  37. //////////////////////////////////////////////////////////////////////
  38. // Construction/Destruction
  39. //////////////////////////////////////////////////////////////////////
  40. //***********************************************************************************************
  41. COMXAudio::COMXAudio() :
  42. m_Initialized (false ),
  43. m_CurrentVolume (0 ),
  44. m_Mute (false ),
  45. m_drc (0 ),
  46. m_BytesPerSec (0 ),
  47. m_InputBytesPerSec(0 ),
  48. m_BufferLen (0 ),
  49. m_ChunkLen (0 ),
  50. m_InputChannels (0 ),
  51. m_OutputChannels (0 ),
  52. m_BitsPerSample (0 ),
  53. m_maxLevel (0.0f ),
  54. m_amplification (1.0f ),
  55. m_attenuation (1.0f ),
  56. m_submitted (0.0f ),
  57. m_omx_clock (NULL ),
  58. m_av_clock (NULL ),
  59. m_settings_changed(false ),
  60. m_setStartTime (false ),
  61. m_eEncoding (OMX_AUDIO_CodingPCM),
  62. m_last_pts (DVD_NOPTS_VALUE),
  63. m_submitted_eos (false ),
  64. m_failed_eos (false )
  65. {
  66. }
  67. COMXAudio::~COMXAudio()
  68. {
  69. Deinitialize();
  70. }
  71. bool COMXAudio::PortSettingsChanged()
  72. {
  73. CSingleLock lock (m_critSection);
  74. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  75. if (m_settings_changed)
  76. {
  77. m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
  78. m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
  79. return true;
  80. }
  81. if(!m_config.passthrough)
  82. {
  83. if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit))
  84. return false;
  85. }
  86. if(m_config.device == "omx:both")
  87. {
  88. if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
  89. return false;
  90. }
  91. if (m_config.device == "omx:both" || m_config.device == "omx:local")
  92. {
  93. if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
  94. return false;
  95. }
  96. if (m_config.device == "omx:both" || m_config.device == "omx:hdmi")
  97. {
  98. if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
  99. return false;
  100. }
  101. if (m_config.device == "omx:alsa")
  102. {
  103. if(!m_omx_render_analog.Initialize("OMX.alsa.audio_render", OMX_IndexParamAudioInit))
  104. return false;
  105. }
  106. UpdateAttenuation();
  107. if( m_omx_mixer.IsInitialized() )
  108. {
  109. /* setup mixer output */
  110. OMX_INIT_STRUCTURE(m_pcm_output);
  111. m_pcm_output.nPortIndex = m_omx_decoder.GetOutputPort();
  112. omx_err = m_omx_decoder.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  113. if(omx_err != OMX_ErrorNone)
  114. {
  115. CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder GetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  116. return false;
  117. }
  118. memcpy(m_pcm_output.eChannelMapping, m_output_channels, sizeof(m_output_channels));
  119. // round up to power of 2
  120. m_pcm_output.nChannels = m_OutputChannels > 4 ? 8 : m_OutputChannels > 2 ? 4 : m_OutputChannels;
  121. /* limit samplerate (through resampling) if requested */
  122. m_pcm_output.nSamplingRate = std::min(std::max((int)m_pcm_output.nSamplingRate, 8000), 192000);
  123. m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort();
  124. omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  125. if(omx_err != OMX_ErrorNone)
  126. {
  127. CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  128. return false;
  129. }
  130. CLog::Log(LOGDEBUG, "%s::%s - Output bps %d samplerate %d channels %d buffer size %d bytes per second %d",
  131. CLASSNAME, __func__, (int)m_pcm_output.nBitPerSample, (int)m_pcm_output.nSamplingRate, (int)m_pcm_output.nChannels, m_BufferLen, m_BytesPerSec);
  132. PrintPCM(&m_pcm_output, std::string("output"));
  133. if( m_omx_splitter.IsInitialized() )
  134. {
  135. m_pcm_output.nPortIndex = m_omx_splitter.GetInputPort();
  136. omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  137. if(omx_err != OMX_ErrorNone)
  138. {
  139. CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  140. return false;
  141. }
  142. m_pcm_output.nPortIndex = m_omx_splitter.GetOutputPort();
  143. omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  144. if(omx_err != OMX_ErrorNone)
  145. {
  146. CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  147. return false;
  148. }
  149. m_pcm_output.nPortIndex = m_omx_splitter.GetOutputPort() + 1;
  150. omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  151. if(omx_err != OMX_ErrorNone)
  152. {
  153. CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  154. return false;
  155. }
  156. }
  157. if( m_omx_render_analog.IsInitialized() )
  158. {
  159. m_pcm_output.nPortIndex = m_omx_render_analog.GetInputPort();
  160. omx_err = m_omx_render_analog.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  161. if(omx_err != OMX_ErrorNone)
  162. {
  163. CLog::Log(LOGERROR, "%s::%s - error m_omx_render_analog SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  164. return false;
  165. }
  166. }
  167. if( m_omx_render_hdmi.IsInitialized() )
  168. {
  169. m_pcm_output.nPortIndex = m_omx_render_hdmi.GetInputPort();
  170. omx_err = m_omx_render_hdmi.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  171. if(omx_err != OMX_ErrorNone)
  172. {
  173. CLog::Log(LOGERROR, "%s::%s - error m_omx_render_hdmi SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  174. return false;
  175. }
  176. }
  177. }
  178. if( m_omx_render_analog.IsInitialized() )
  179. {
  180. m_omx_tunnel_clock_analog.Initialize(m_omx_clock, m_omx_clock->GetInputPort(),
  181. &m_omx_render_analog, m_omx_render_analog.GetInputPort()+1);
  182. omx_err = m_omx_tunnel_clock_analog.Establish();
  183. if(omx_err != OMX_ErrorNone)
  184. {
  185. CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_analog.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  186. return false;
  187. }
  188. m_omx_render_analog.ResetEos();
  189. }
  190. if( m_omx_render_hdmi.IsInitialized() )
  191. {
  192. m_omx_tunnel_clock_hdmi.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + (m_omx_render_analog.IsInitialized() ? 2 : 0),
  193. &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort()+1);
  194. omx_err = m_omx_tunnel_clock_hdmi.Establish();
  195. if(omx_err != OMX_ErrorNone)
  196. {
  197. CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_hdmi.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  198. return false;
  199. }
  200. m_omx_render_hdmi.ResetEos();
  201. }
  202. if( m_omx_render_analog.IsInitialized() )
  203. {
  204. // 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.
  205. // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
  206. // when in dual audio mode, make analogue the slave
  207. OMX_CONFIG_BOOLEANTYPE configBool;
  208. OMX_INIT_STRUCTURE(configBool);
  209. configBool.bEnabled = m_config.is_live || m_config.device == "omx:both" ? OMX_FALSE:OMX_TRUE;
  210. omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
  211. if (omx_err != OMX_ErrorNone)
  212. return false;
  213. OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
  214. OMX_INIT_STRUCTURE(audioDest);
  215. strncpy((char *)audioDest.sName, m_config.device == "omx:alsa" ? m_config.subdevice.c_str() : "local", sizeof(audioDest.sName));
  216. omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
  217. if (omx_err != OMX_ErrorNone)
  218. {
  219. CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  220. return false;
  221. }
  222. }
  223. if( m_omx_render_hdmi.IsInitialized() )
  224. {
  225. // 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.
  226. // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
  227. OMX_CONFIG_BOOLEANTYPE configBool;
  228. OMX_INIT_STRUCTURE(configBool);
  229. configBool.bEnabled = m_config.is_live ? OMX_FALSE:OMX_TRUE;
  230. omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
  231. if (omx_err != OMX_ErrorNone)
  232. return false;
  233. OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
  234. OMX_INIT_STRUCTURE(audioDest);
  235. strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi"));
  236. omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
  237. if (omx_err != OMX_ErrorNone)
  238. {
  239. CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  240. return false;
  241. }
  242. }
  243. if( m_omx_splitter.IsInitialized() )
  244. {
  245. m_omx_tunnel_splitter_analog.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
  246. omx_err = m_omx_tunnel_splitter_analog.Establish();
  247. if(omx_err != OMX_ErrorNone)
  248. {
  249. CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_analog.Establish 0x%08x", omx_err);
  250. return false;
  251. }
  252. m_omx_tunnel_splitter_hdmi.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort() + 1, &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
  253. omx_err = m_omx_tunnel_splitter_hdmi.Establish();
  254. if(omx_err != OMX_ErrorNone)
  255. {
  256. CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_hdmi.Establish 0x%08x", omx_err);
  257. return false;
  258. }
  259. }
  260. if( m_omx_mixer.IsInitialized() )
  261. {
  262. m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_mixer, m_omx_mixer.GetInputPort());
  263. if( m_omx_splitter.IsInitialized() )
  264. {
  265. m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_splitter, m_omx_splitter.GetInputPort());
  266. }
  267. else
  268. {
  269. if( m_omx_render_analog.IsInitialized() )
  270. {
  271. m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
  272. }
  273. if( m_omx_render_hdmi.IsInitialized() )
  274. {
  275. m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
  276. }
  277. }
  278. CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d nopassthrough", CLASSNAME, __func__,
  279. (int)m_pcm_input.nBitPerSample, m_pcm_input.ePCMMode, (int)m_pcm_input.nChannels, (int)m_pcm_input.nSamplingRate);
  280. }
  281. else
  282. {
  283. if( m_omx_render_analog.IsInitialized() )
  284. {
  285. m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
  286. }
  287. else if( m_omx_render_hdmi.IsInitialized() )
  288. {
  289. m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
  290. }
  291. CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d passthrough", CLASSNAME, __func__,
  292. 0, 0, 0, 0);
  293. }
  294. omx_err = m_omx_tunnel_decoder.Establish();
  295. if(omx_err != OMX_ErrorNone)
  296. {
  297. CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  298. return false;
  299. }
  300. if( m_omx_mixer.IsInitialized() )
  301. {
  302. omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting);
  303. if(omx_err != OMX_ErrorNone) {
  304. CLog::Log(LOGERROR, "%s::%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  305. return false;
  306. }
  307. }
  308. if( m_omx_mixer.IsInitialized() )
  309. {
  310. omx_err = m_omx_tunnel_mixer.Establish();
  311. if(omx_err != OMX_ErrorNone)
  312. {
  313. CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  314. return false;
  315. }
  316. }
  317. if( m_omx_splitter.IsInitialized() )
  318. {
  319. omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting);
  320. if(omx_err != OMX_ErrorNone)
  321. {
  322. CLog::Log(LOGERROR, "%s::%s - m_omx_splitter OMX_StateExecuting 0x%08x", CLASSNAME, __func__, omx_err);
  323. return false;
  324. }
  325. }
  326. if( m_omx_render_analog.IsInitialized() )
  327. {
  328. omx_err = m_omx_render_analog.SetStateForComponent(OMX_StateExecuting);
  329. if(omx_err != OMX_ErrorNone)
  330. {
  331. CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  332. return false;
  333. }
  334. }
  335. if( m_omx_render_hdmi.IsInitialized() )
  336. {
  337. omx_err = m_omx_render_hdmi.SetStateForComponent(OMX_StateExecuting);
  338. if(omx_err != OMX_ErrorNone)
  339. {
  340. CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  341. return false;
  342. }
  343. }
  344. m_settings_changed = true;
  345. return true;
  346. }
  347. static unsigned count_bits(uint64_t value)
  348. {
  349. unsigned bits = 0;
  350. for(;value;++bits)
  351. value &= value - 1;
  352. return bits;
  353. }
  354. bool COMXAudio::Initialize(OMXClock *clock, const OMXAudioConfig &config, uint64_t channelMap, unsigned int uiBitsPerSample)
  355. {
  356. CSingleLock lock (m_critSection);
  357. OMX_ERRORTYPE omx_err;
  358. Deinitialize();
  359. if(!m_dllAvUtil.Load())
  360. return false;
  361. m_config = config;
  362. m_InputChannels = count_bits(channelMap);
  363. if(m_InputChannels == 0)
  364. return false;
  365. if(m_config.hints.samplerate == 0)
  366. return false;
  367. m_av_clock = clock;
  368. if(!m_av_clock)
  369. return false;
  370. /* passthrough overwrites hw decode */
  371. if(m_config.passthrough)
  372. {
  373. m_config.hwdecode = false;
  374. }
  375. else if(m_config.hwdecode)
  376. {
  377. /* check again if we are capable to hw decode the format */
  378. m_config.hwdecode = CanHWDecode(m_config.hints.codec);
  379. }
  380. if(m_config.passthrough || m_config.hwdecode)
  381. SetCodingType(m_config.hints.codec);
  382. else
  383. SetCodingType(AV_CODEC_ID_PCM_S16LE);
  384. m_omx_clock = m_av_clock->GetOMXClock();
  385. m_drc = 0;
  386. memset(m_input_channels, 0x0, sizeof(m_input_channels));
  387. memset(m_output_channels, 0x0, sizeof(m_output_channels));
  388. memset(&m_wave_header, 0x0, sizeof(m_wave_header));
  389. m_wave_header.Format.nChannels = 2;
  390. m_wave_header.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
  391. // set the input format, and get the channel layout so we know what we need to open
  392. if (!m_config.passthrough && channelMap)
  393. {
  394. enum PCMChannels inLayout[OMX_AUDIO_MAXCHANNELS];
  395. enum PCMChannels outLayout[OMX_AUDIO_MAXCHANNELS];
  396. // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix
  397. if (channelMap == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) || channelMap == AV_CH_FRONT_CENTER)
  398. m_config.layout = PCM_LAYOUT_2_0;
  399. BuildChannelMap(inLayout, channelMap);
  400. m_OutputChannels = BuildChannelMapCEA(outLayout, GetChannelLayout(m_config.layout));
  401. CPCMRemap m_remap;
  402. m_remap.Reset();
  403. /*outLayout = */m_remap.SetInputFormat (m_InputChannels, inLayout, uiBitsPerSample / 8, m_config.hints.samplerate, m_config.layout, m_config.boostOnDownmix);
  404. m_remap.SetOutputFormat(m_OutputChannels, outLayout);
  405. m_remap.GetDownmixMatrix(m_downmix_matrix);
  406. m_wave_header.dwChannelMask = channelMap;
  407. BuildChannelMapOMX(m_input_channels, channelMap);
  408. BuildChannelMapOMX(m_output_channels, GetChannelLayout(m_config.layout));
  409. }
  410. m_BitsPerSample = uiBitsPerSample;
  411. m_BytesPerSec = m_config.hints.samplerate * 2 << rounded_up_channels_shift[m_InputChannels];
  412. m_BufferLen = m_BytesPerSec * AUDIO_BUFFER_SECONDS;
  413. m_InputBytesPerSec = m_config.hints.samplerate * m_BitsPerSample * m_InputChannels >> 3;
  414. // should be big enough that common formats (e.g. 6 channel DTS) fit in a single packet.
  415. // we don't mind less common formats being split (e.g. ape/wma output large frames)
  416. // 6 channel 32bpp float to 8 channel 16bpp in, so a full 48K input buffer will fit the output buffer
  417. m_ChunkLen = AUDIO_DECODE_OUTPUT_BUFFER * (m_InputChannels * m_BitsPerSample) >> (rounded_up_channels_shift[m_InputChannels] + 4);
  418. m_wave_header.Samples.wSamplesPerBlock = 0;
  419. m_wave_header.Format.nChannels = m_InputChannels;
  420. m_wave_header.Format.nBlockAlign = m_InputChannels *
  421. (m_BitsPerSample >> 3);
  422. // 0x8000 is custom format interpreted by GPU as WAVE_FORMAT_IEEE_FLOAT_PLANAR
  423. m_wave_header.Format.wFormatTag = m_BitsPerSample == 32 ? 0x8000 : WAVE_FORMAT_PCM;
  424. m_wave_header.Format.nSamplesPerSec = m_config.hints.samplerate;
  425. m_wave_header.Format.nAvgBytesPerSec = m_BytesPerSec;
  426. m_wave_header.Format.wBitsPerSample = m_BitsPerSample;
  427. m_wave_header.Samples.wValidBitsPerSample = m_BitsPerSample;
  428. m_wave_header.Format.cbSize = 0;
  429. m_wave_header.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  430. if(!m_omx_decoder.Initialize("OMX.broadcom.audio_decode", OMX_IndexParamAudioInit))
  431. return false;
  432. OMX_CONFIG_BOOLEANTYPE boolType;
  433. OMX_INIT_STRUCTURE(boolType);
  434. if(m_config.passthrough)
  435. boolType.bEnabled = OMX_TRUE;
  436. else
  437. boolType.bEnabled = OMX_FALSE;
  438. omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmDecoderPassThrough, &boolType);
  439. if(omx_err != OMX_ErrorNone)
  440. {
  441. CLog::Log(LOGERROR, "COMXAudio::Initialize - Error OMX_IndexParamBrcmDecoderPassThrough 0x%08x", omx_err);
  442. printf("OMX_IndexParamBrcmDecoderPassThrough omx_err(0x%08x)\n", omx_err);
  443. return false;
  444. }
  445. // set up the number/size of buffers for decoder input
  446. OMX_PARAM_PORTDEFINITIONTYPE port_param;
  447. OMX_INIT_STRUCTURE(port_param);
  448. port_param.nPortIndex = m_omx_decoder.GetInputPort();
  449. omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
  450. if(omx_err != OMX_ErrorNone)
  451. {
  452. CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)\n", omx_err);
  453. return false;
  454. }
  455. port_param.format.audio.eEncoding = m_eEncoding;
  456. port_param.nBufferSize = m_ChunkLen;
  457. port_param.nBufferCountActual = std::max(port_param.nBufferCountMin, 16U);
  458. omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
  459. if(omx_err != OMX_ErrorNone)
  460. {
  461. CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (intput) omx_err(0x%08x)\n", omx_err);
  462. return false;
  463. }
  464. // set up the number/size of buffers for decoder output
  465. OMX_INIT_STRUCTURE(port_param);
  466. port_param.nPortIndex = m_omx_decoder.GetOutputPort();
  467. omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_param);
  468. if(omx_err != OMX_ErrorNone)
  469. {
  470. CLog::Log(LOGERROR, "COMXAudio::Initialize error get OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
  471. return false;
  472. }
  473. port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, m_BufferLen / port_param.nBufferSize);
  474. omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_param);
  475. if(omx_err != OMX_ErrorNone)
  476. {
  477. CLog::Log(LOGERROR, "COMXAudio::Initialize error set OMX_IndexParamPortDefinition (output) omx_err(0x%08x)\n", omx_err);
  478. return false;
  479. }
  480. {
  481. OMX_AUDIO_PARAM_PORTFORMATTYPE formatType;
  482. OMX_INIT_STRUCTURE(formatType);
  483. formatType.nPortIndex = m_omx_decoder.GetInputPort();
  484. formatType.eEncoding = m_eEncoding;
  485. omx_err = m_omx_decoder.SetParameter(OMX_IndexParamAudioPortFormat, &formatType);
  486. if(omx_err != OMX_ErrorNone)
  487. {
  488. CLog::Log(LOGERROR, "COMXAudio::Initialize error OMX_IndexParamAudioPortFormat omx_err(0x%08x)\n", omx_err);
  489. return false;
  490. }
  491. }
  492. omx_err = m_omx_decoder.AllocInputBuffers();
  493. if(omx_err != OMX_ErrorNone)
  494. {
  495. CLog::Log(LOGERROR, "COMXAudio::Initialize - Error alloc buffers 0x%08x", omx_err);
  496. return false;
  497. }
  498. omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
  499. if(omx_err != OMX_ErrorNone) {
  500. CLog::Log(LOGERROR, "COMXAudio::Initialize - Error setting OMX_StateExecuting 0x%08x", omx_err);
  501. return false;
  502. }
  503. if(m_eEncoding == OMX_AUDIO_CodingPCM)
  504. {
  505. OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
  506. if(omx_buffer == NULL)
  507. {
  508. CLog::Log(LOGERROR, "COMXAudio::Initialize - buffer error 0x%08x", omx_err);
  509. return false;
  510. }
  511. omx_buffer->nOffset = 0;
  512. omx_buffer->nFilledLen = std::min(sizeof(m_wave_header), omx_buffer->nAllocLen);
  513. memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
  514. memcpy((unsigned char *)omx_buffer->pBuffer, &m_wave_header, omx_buffer->nFilledLen);
  515. omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
  516. omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  517. if (omx_err != OMX_ErrorNone)
  518. {
  519. CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
  520. m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer);
  521. return false;
  522. }
  523. }
  524. else if(m_config.hwdecode)
  525. {
  526. // send decoder config
  527. if(m_config.hints.extrasize > 0 && m_config.hints.extradata != NULL)
  528. {
  529. OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
  530. if(omx_buffer == NULL)
  531. {
  532. CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
  533. return false;
  534. }
  535. omx_buffer->nOffset = 0;
  536. omx_buffer->nFilledLen = std::min((OMX_U32)m_config.hints.extrasize, omx_buffer->nAllocLen);
  537. memset((unsigned char *)omx_buffer->pBuffer, 0x0, omx_buffer->nAllocLen);
  538. memcpy((unsigned char *)omx_buffer->pBuffer, m_config.hints.extradata, omx_buffer->nFilledLen);
  539. omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
  540. omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  541. if (omx_err != OMX_ErrorNone)
  542. {
  543. CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
  544. m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer);
  545. return false;
  546. }
  547. }
  548. }
  549. /* return on decoder error so m_Initialized stays false */
  550. if(m_omx_decoder.BadState())
  551. return false;
  552. OMX_INIT_STRUCTURE(m_pcm_input);
  553. m_pcm_input.nPortIndex = m_omx_decoder.GetInputPort();
  554. memcpy(m_pcm_input.eChannelMapping, m_input_channels, sizeof(m_input_channels));
  555. m_pcm_input.eNumData = OMX_NumericalDataSigned;
  556. m_pcm_input.eEndian = OMX_EndianLittle;
  557. m_pcm_input.bInterleaved = OMX_TRUE;
  558. m_pcm_input.nBitPerSample = m_BitsPerSample;
  559. m_pcm_input.ePCMMode = OMX_AUDIO_PCMModeLinear;
  560. m_pcm_input.nChannels = m_InputChannels;
  561. m_pcm_input.nSamplingRate = m_config.hints.samplerate;
  562. m_Initialized = true;
  563. m_settings_changed = false;
  564. m_setStartTime = true;
  565. m_submitted_eos = false;
  566. m_failed_eos = false;
  567. m_last_pts = DVD_NOPTS_VALUE;
  568. m_submitted = 0.0f;
  569. m_maxLevel = 0.0f;
  570. CLog::Log(LOGDEBUG, "COMXAudio::Initialize Input bps %d samplerate %d channels %d buffer size %d bytes per second %d",
  571. (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_InputBytesPerSec);
  572. PrintPCM(&m_pcm_input, std::string("input"));
  573. CLog::Log(LOGDEBUG, "COMXAudio::Initialize device %s passthrough %d hwdecode %d",
  574. m_config.device.c_str(), m_config.passthrough, m_config.hwdecode);
  575. return true;
  576. }
  577. //***********************************************************************************************
  578. bool COMXAudio::Deinitialize()
  579. {
  580. CSingleLock lock (m_critSection);
  581. if ( m_omx_tunnel_clock_analog.IsInitialized() )
  582. m_omx_tunnel_clock_analog.Deestablish();
  583. if ( m_omx_tunnel_clock_hdmi.IsInitialized() )
  584. m_omx_tunnel_clock_hdmi.Deestablish();
  585. // ignore expected errors on teardown
  586. if ( m_omx_mixer.IsInitialized() )
  587. m_omx_mixer.IgnoreNextError(OMX_ErrorPortUnpopulated);
  588. else
  589. {
  590. if ( m_omx_render_hdmi.IsInitialized() )
  591. m_omx_render_hdmi.IgnoreNextError(OMX_ErrorPortUnpopulated);
  592. if ( m_omx_render_analog.IsInitialized() )
  593. m_omx_render_analog.IgnoreNextError(OMX_ErrorPortUnpopulated);
  594. }
  595. m_omx_tunnel_decoder.Deestablish();
  596. if ( m_omx_tunnel_mixer.IsInitialized() )
  597. m_omx_tunnel_mixer.Deestablish();
  598. if ( m_omx_tunnel_splitter_hdmi.IsInitialized() )
  599. m_omx_tunnel_splitter_hdmi.Deestablish();
  600. if ( m_omx_tunnel_splitter_analog.IsInitialized() )
  601. m_omx_tunnel_splitter_analog.Deestablish();
  602. m_omx_decoder.FlushInput();
  603. m_omx_decoder.Deinitialize();
  604. if ( m_omx_mixer.IsInitialized() )
  605. m_omx_mixer.Deinitialize();
  606. if ( m_omx_splitter.IsInitialized() )
  607. m_omx_splitter.Deinitialize();
  608. if ( m_omx_render_hdmi.IsInitialized() )
  609. m_omx_render_hdmi.Deinitialize();
  610. if ( m_omx_render_analog.IsInitialized() )
  611. m_omx_render_analog.Deinitialize();
  612. m_BytesPerSec = 0;
  613. m_BufferLen = 0;
  614. m_omx_clock = NULL;
  615. m_av_clock = NULL;
  616. m_Initialized = false;
  617. m_dllAvUtil.Unload();
  618. while(!m_ampqueue.empty())
  619. m_ampqueue.pop_front();
  620. m_last_pts = DVD_NOPTS_VALUE;
  621. m_submitted = 0.0f;
  622. m_maxLevel = 0.0f;
  623. return true;
  624. }
  625. void COMXAudio::Flush()
  626. {
  627. CSingleLock lock (m_critSection);
  628. if(!m_Initialized)
  629. return;
  630. m_omx_decoder.FlushAll();
  631. if ( m_omx_mixer.IsInitialized() )
  632. m_omx_mixer.FlushAll();
  633. if ( m_omx_splitter.IsInitialized() )
  634. m_omx_splitter.FlushAll();
  635. if ( m_omx_render_analog.IsInitialized() )
  636. m_omx_render_analog.FlushAll();
  637. if ( m_omx_render_hdmi.IsInitialized() )
  638. m_omx_render_hdmi.FlushAll();
  639. while(!m_ampqueue.empty())
  640. m_ampqueue.pop_front();
  641. if( m_omx_render_analog.IsInitialized() )
  642. m_omx_render_analog.ResetEos();
  643. if( m_omx_render_hdmi.IsInitialized() )
  644. m_omx_render_hdmi.ResetEos();
  645. m_last_pts = DVD_NOPTS_VALUE;
  646. m_submitted = 0.0f;
  647. m_maxLevel = 0.0f;
  648. m_setStartTime = true;
  649. }
  650. //***********************************************************************************************
  651. void COMXAudio::SetDynamicRangeCompression(long drc)
  652. {
  653. CSingleLock lock (m_critSection);
  654. m_amplification = powf(10.0f, (float)drc / 2000.0f);
  655. if (m_settings_changed)
  656. UpdateAttenuation();
  657. }
  658. //***********************************************************************************************
  659. void COMXAudio::SetMute(bool bMute)
  660. {
  661. CSingleLock lock (m_critSection);
  662. m_Mute = bMute;
  663. if (m_settings_changed)
  664. UpdateAttenuation();
  665. }
  666. //***********************************************************************************************
  667. void COMXAudio::SetVolume(float fVolume)
  668. {
  669. CSingleLock lock (m_critSection);
  670. m_CurrentVolume = fVolume;
  671. if (m_settings_changed)
  672. UpdateAttenuation();
  673. }
  674. float COMXAudio::GetVolume()
  675. {
  676. return m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
  677. }
  678. //***********************************************************************************************
  679. bool COMXAudio::ApplyVolume(void)
  680. {
  681. float m_ac3Gain = 12.0f;
  682. CSingleLock lock (m_critSection);
  683. if(!m_Initialized || m_config.passthrough)
  684. return false;
  685. float fVolume = m_Mute ? VOLUME_MINIMUM : m_CurrentVolume;
  686. // the analogue volume is too quiet for some. Allow use of an advancedsetting to boost this (at risk of distortion) (deprecated)
  687. double gain = pow(10, (m_ac3Gain - 12.0f) / 20.0);
  688. const float* coeff = m_downmix_matrix;
  689. OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix;
  690. OMX_INIT_STRUCTURE(mix);
  691. OMX_ERRORTYPE omx_err;
  692. assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64);
  693. if (m_amplification != 1.0)
  694. {
  695. // reduce scaling so overflow can be seen
  696. for(size_t i = 0; i < 8*8; ++i)
  697. mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * gain * 0.01f));
  698. mix.nPortIndex = m_omx_decoder.GetInputPort();
  699. omx_err = m_omx_decoder.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
  700. if(omx_err != OMX_ErrorNone)
  701. {
  702. CLog::Log(LOGERROR, "%s::%s - error setting decoder OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
  703. CLASSNAME, __func__, omx_err);
  704. return false;
  705. }
  706. }
  707. for(size_t i = 0; i < 8*8; ++i)
  708. mix.coeff[i] = static_cast<unsigned int>(0x10000 * (coeff[i] * gain * fVolume * m_amplification * m_attenuation));
  709. mix.nPortIndex = m_omx_mixer.GetInputPort();
  710. omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
  711. if(omx_err != OMX_ErrorNone)
  712. {
  713. CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
  714. CLASSNAME, __func__, omx_err);
  715. return false;
  716. }
  717. CLog::Log(LOGINFO, "%s::%s - Volume=%.2f (* %.2f * %.2f)\n", CLASSNAME, __func__, fVolume, m_amplification, m_attenuation);
  718. return true;
  719. }
  720. //***********************************************************************************************
  721. unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
  722. {
  723. return AddPackets(data, len, 0, 0, 0);
  724. }
  725. //***********************************************************************************************
  726. unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts, unsigned int frame_size)
  727. {
  728. CSingleLock lock (m_critSection);
  729. if(!m_Initialized)
  730. {
  731. CLog::Log(LOGERROR,"COMXAudio::AddPackets - sanity failed. no valid play handle!");
  732. return len;
  733. }
  734. unsigned pitch = (m_config.passthrough || m_config.hwdecode) ? 1:(m_BitsPerSample >> 3) * m_InputChannels;
  735. unsigned int demuxer_samples = len / pitch;
  736. unsigned int demuxer_samples_sent = 0;
  737. uint8_t *demuxer_content = (uint8_t *)data;
  738. OMX_ERRORTYPE omx_err;
  739. OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
  740. while(demuxer_samples_sent < demuxer_samples)
  741. {
  742. // 200ms timeout
  743. omx_buffer = m_omx_decoder.GetInputBuffer(200);
  744. if(omx_buffer == NULL)
  745. {
  746. CLog::Log(LOGERROR, "COMXAudio::Decode timeout\n");
  747. printf("COMXAudio::Decode timeout\n");
  748. return len;
  749. }
  750. omx_buffer->nOffset = 0;
  751. omx_buffer->nFlags = 0;
  752. // we want audio_decode output buffer size to be no more than AUDIO_DECODE_OUTPUT_BUFFER.
  753. // it will be 16-bit and rounded up to next power of 2 in channels
  754. unsigned int max_buffer = AUDIO_DECODE_OUTPUT_BUFFER * (m_InputChannels * m_BitsPerSample) >> (rounded_up_channels_shift[m_InputChannels] + 4);
  755. unsigned int remaining = demuxer_samples-demuxer_samples_sent;
  756. unsigned int samples_space = std::min(max_buffer, omx_buffer->nAllocLen)/pitch;
  757. unsigned int samples = std::min(remaining, samples_space);
  758. omx_buffer->nFilledLen = samples * pitch;
  759. unsigned int frames = frame_size ? len/frame_size:0;
  760. if ((samples < demuxer_samples || frames > 1) && m_BitsPerSample==32 && !(m_config.passthrough || m_config.hwdecode))
  761. {
  762. const unsigned int sample_pitch = m_BitsPerSample >> 3;
  763. const unsigned int frame_samples = frame_size / pitch;
  764. const unsigned int plane_size = frame_samples * sample_pitch;
  765. const unsigned int out_plane_size = samples * sample_pitch;
  766. //CLog::Log(LOGDEBUG, "%s::%s samples:%d/%d ps:%d ops:%d fs:%d pitch:%d filled:%d frames=%d", CLASSNAME, __func__, samples, demuxer_samples, plane_size, out_plane_size, frame_size, pitch, omx_buffer
  767. for (unsigned int sample = 0; sample < samples; )
  768. {
  769. unsigned int frame = (demuxer_samples_sent + sample) / frame_samples;
  770. unsigned int sample_in_frame = (demuxer_samples_sent + sample) - frame * frame_samples;
  771. int out_remaining = std::min(std::min(frame_samples - sample_in_frame, samples), samples-sample);
  772. uint8_t *src = demuxer_content + frame*frame_size + sample_in_frame * sample_pitch;
  773. uint8_t *dst = (uint8_t *)omx_buffer->pBuffer + sample * sample_pitch;
  774. for (unsigned int channel = 0; channel < m_InputChannels; channel++)
  775. {
  776. //CLog::Log(LOGDEBUG, "%s::%s copy(%d,%d,%d) (s:%d f:%d sin:%d c:%d)", CLASSNAME, __func__, dst-(uint8_t *)omx_buffer->pBuffer, src-demuxer_content, out_remaining, sample, frame, sample_in_frame
  777. memcpy(dst, src, out_remaining * sample_pitch);
  778. src += plane_size;
  779. dst += out_plane_size;
  780. }
  781. sample += out_remaining;
  782. }
  783. }
  784. else
  785. {
  786. uint8_t *dst = omx_buffer->pBuffer;
  787. uint8_t *src = demuxer_content + demuxer_samples_sent * pitch;
  788. memcpy(dst, src, omx_buffer->nFilledLen);
  789. }
  790. uint64_t val = (uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts;
  791. if(m_setStartTime)
  792. {
  793. omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
  794. m_last_pts = pts;
  795. CLog::Log(LOGDEBUG, "COMXAudio::Decode ADec : setStartTime %f\n", (float)val / DVD_TIME_BASE);
  796. m_setStartTime = false;
  797. }
  798. else
  799. {
  800. if(pts == DVD_NOPTS_VALUE)
  801. {
  802. omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
  803. m_last_pts = pts;
  804. }
  805. else if (m_last_pts != pts)
  806. {
  807. if(pts > m_last_pts)
  808. m_last_pts = pts;
  809. else
  810. omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
  811. }
  812. else if (m_last_pts == pts)
  813. {
  814. omx_buffer->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
  815. }
  816. }
  817. omx_buffer->nTimeStamp = ToOMXTime(val);
  818. demuxer_samples_sent += samples;
  819. if(demuxer_samples_sent == demuxer_samples)
  820. omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
  821. omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  822. if (omx_err != OMX_ErrorNone)
  823. {
  824. CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
  825. printf("%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
  826. m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer);
  827. return 0;
  828. }
  829. //CLog::Log(LOGINFO, "AudiD: dts:%.0f pts:%.0f size:%d\n", dts, pts, len);
  830. omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0);
  831. if (omx_err == OMX_ErrorNone)
  832. {
  833. if(!PortSettingsChanged())
  834. {
  835. CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err);
  836. }
  837. }
  838. }
  839. m_submitted += (float)demuxer_samples / m_config.hints.samplerate;
  840. UpdateAttenuation();
  841. return len;
  842. }
  843. void COMXAudio::UpdateAttenuation()
  844. {
  845. if (m_amplification == 1.0)
  846. {
  847. ApplyVolume();
  848. return;
  849. }
  850. double level_pts = 0.0;
  851. float level = GetMaxLevel(level_pts);
  852. if (level_pts != 0.0)
  853. {
  854. amplitudes_t v;
  855. v.level = level;
  856. v.pts = level_pts;
  857. m_ampqueue.push_back(v);
  858. }
  859. double stamp = m_av_clock->OMXMediaTime();
  860. // discard too old data
  861. while(!m_ampqueue.empty())
  862. {
  863. amplitudes_t &v = m_ampqueue.front();
  864. /* we'll also consume if queue gets unexpectedly long to avoid filling memory */
  865. if (v.pts == DVD_NOPTS_VALUE || v.pts < stamp || v.pts - stamp > DVD_SEC_TO_TIME(15.0))
  866. m_ampqueue.pop_front();
  867. else break;
  868. }
  869. float maxlevel = 0.0f, imminent_maxlevel = 0.0f;
  870. for (int i=0; i < (int)m_ampqueue.size(); i++)
  871. {
  872. amplitudes_t &v = m_ampqueue[i];
  873. maxlevel = std::max(maxlevel, v.level);
  874. // check for maximum volume in next 200ms
  875. if (v.pts != DVD_NOPTS_VALUE && v.pts < stamp + DVD_SEC_TO_TIME(0.2))
  876. imminent_maxlevel = std::max(imminent_maxlevel, v.level);
  877. }
  878. if (maxlevel != 0.0)
  879. {
  880. float m_limiterHold = 0.025f;
  881. float m_limiterRelease = 0.100f;
  882. float alpha_h = -1.0f/(0.025f*log10f(0.999f));
  883. float alpha_r = -1.0f/(0.100f*log10f(0.900f));
  884. float decay = powf(10.0f, -1.0f / (alpha_h * m_limiterHold));
  885. float attack = powf(10.0f, -1.0f / (alpha_r * m_limiterRelease));
  886. // if we are going to clip imminently then deal with it now
  887. if (imminent_maxlevel > m_maxLevel)
  888. m_maxLevel = imminent_maxlevel;
  889. // clip but not imminently can ramp up more slowly
  890. else if (maxlevel > m_maxLevel)
  891. m_maxLevel = attack * m_maxLevel + (1.0f-attack) * maxlevel;
  892. // not clipping, decay more slowly
  893. else
  894. m_maxLevel = decay * m_maxLevel + (1.0f-decay ) * maxlevel;
  895. // want m_maxLevel * amp -> 1.0
  896. float amp = m_amplification * m_attenuation;
  897. // We fade in the attenuation over first couple of seconds
  898. float start = std::min(std::max((m_submitted-1.0f), 0.0f), 1.0f);
  899. float attenuation = std::min(1.0f, std::max(m_attenuation / (amp * m_maxLevel), 1.0f/m_amplification));
  900. m_attenuation = (1.0f - start) * 1.0f/m_amplification + start * attenuation;
  901. }
  902. else
  903. {
  904. m_attenuation = 1.0f/m_amplification;
  905. }
  906. ApplyVolume();
  907. }
  908. //***********************************************************************************************
  909. unsigned int COMXAudio::GetSpace()
  910. {
  911. int free = m_omx_decoder.GetInputBufferSpace();
  912. return free;
  913. }
  914. float COMXAudio::GetDelay()
  915. {
  916. CSingleLock lock (m_critSection);
  917. double stamp = DVD_NOPTS_VALUE;
  918. double ret = 0.0;
  919. if (m_last_pts != DVD_NOPTS_VALUE && m_av_clock)
  920. stamp = m_av_clock->OMXMediaTime();
  921. // if possible the delay is current media time - time of last submitted packet
  922. if (stamp != DVD_NOPTS_VALUE)
  923. {
  924. ret = (m_last_pts - stamp) * (1.0 / DVD_TIME_BASE);
  925. //CLog::Log(LOGINFO, "%s::%s - %.2f %.0f %.0f", CLASSNAME, __func__, ret, stamp, m_last_pts);
  926. }
  927. else // just measure the input fifo
  928. {
  929. unsigned int used = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
  930. ret = m_InputBytesPerSec ? (float)used / (float)m_InputBytesPerSec : 0.0f;
  931. //CLog::Log(LOGINFO, "%s::%s - %.2f %d, %d, %d", CLASSNAME, __func__, ret, used, m_omx_decoder.GetInputBufferSize(), m_omx_decoder.GetInputBufferSpace());
  932. }
  933. return ret;
  934. }
  935. float COMXAudio::GetCacheTime()
  936. {
  937. return GetDelay();
  938. }
  939. float COMXAudio::GetCacheTotal()
  940. {
  941. float audioplus_buffer = m_config.hints.samplerate ? 32.0f * 512.0f / m_config.hints.samplerate : 0.0f;
  942. float input_buffer = m_InputBytesPerSec ? (float)m_omx_decoder.GetInputBufferSize() / (float)m_InputBytesPerSec : 0;
  943. return AUDIO_BUFFER_SECONDS + input_buffer + audioplus_buffer;
  944. }
  945. //***********************************************************************************************
  946. unsigned int COMXAudio::GetChunkLen()
  947. {
  948. return m_ChunkLen;
  949. }
  950. unsigned int COMXAudio::GetAudioRenderingLatency()
  951. {
  952. CSingleLock lock (m_critSection);
  953. if(!m_Initialized)
  954. return 0;
  955. OMX_PARAM_U32TYPE param;
  956. OMX_INIT_STRUCTURE(param);
  957. if(m_omx_render_analog.IsInitialized())
  958. {
  959. param.nPortIndex = m_omx_render_analog.GetInputPort();
  960. OMX_ERRORTYPE omx_err = m_omx_render_analog.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
  961. if(omx_err != OMX_ErrorNone)
  962. {
  963. CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
  964. CLASSNAME, __func__, omx_err);
  965. return 0;
  966. }
  967. }
  968. else if(m_omx_render_hdmi.IsInitialized())
  969. {
  970. param.nPortIndex = m_omx_render_hdmi.GetInputPort();
  971. OMX_ERRORTYPE omx_err = m_omx_render_hdmi.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
  972. if(omx_err != OMX_ErrorNone)
  973. {
  974. CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
  975. CLASSNAME, __func__, omx_err);
  976. return 0;
  977. }
  978. }
  979. return param.nU32;
  980. }
  981. float COMXAudio::GetMaxLevel(double &pts)
  982. {
  983. CSingleLock lock (m_critSection);
  984. if(!m_Initialized)
  985. return 0;
  986. OMX_CONFIG_BRCMAUDIOMAXSAMPLE param;
  987. OMX_INIT_STRUCTURE(param);
  988. if(m_omx_decoder.IsInitialized())
  989. {
  990. param.nPortIndex = m_omx_decoder.GetInputPort();
  991. OMX_ERRORTYPE omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigBrcmAudioMaxSample, &param);
  992. if(omx_err != OMX_ErrorNone)
  993. {
  994. CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigBrcmAudioMaxSample error 0x%08x\n",
  995. CLASSNAME, __func__, omx_err);
  996. return 0;
  997. }
  998. }
  999. pts = FromOMXTime(param.nTimeStamp);
  1000. return (float)param.nMaxSample * (100.0f / (1<<15));
  1001. }
  1002. void COMXAudio::SubmitEOS()
  1003. {
  1004. CSingleLock lock (m_critSection);
  1005. if(!m_Initialized)
  1006. return;
  1007. m_submitted_eos = true;
  1008. m_failed_eos = false;
  1009. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  1010. OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(1000);
  1011. if(omx_buffer == NULL)
  1012. {
  1013. CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
  1014. m_failed_eos = true;
  1015. return;
  1016. }
  1017. omx_buffer->nOffset = 0;
  1018. omx_buffer->nFilledLen = 0;
  1019. omx_buffer->nTimeStamp = ToOMXTime(0LL);
  1020. omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
  1021. omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  1022. if (omx_err != OMX_ErrorNone)
  1023. {
  1024. CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
  1025. m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer);
  1026. return;
  1027. }
  1028. CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  1029. }
  1030. bool COMXAudio::IsEOS()
  1031. {
  1032. if(!m_Initialized)
  1033. return true;
  1034. unsigned int latency = GetAudioRenderingLatency();
  1035. CSingleLock lock (m_critSection);
  1036. if (!m_failed_eos && !(m_omx_decoder.IsEOS() && latency == 0))
  1037. return false;
  1038. if (m_submitted_eos)
  1039. {
  1040. CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  1041. m_submitted_eos = false;
  1042. }
  1043. return true;
  1044. }
  1045. void COMXAudio::SetCodingType(AVCodecID codec)
  1046. {
  1047. switch(codec)
  1048. {
  1049. case AV_CODEC_ID_DTS:
  1050. CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDTS\n");
  1051. m_eEncoding = OMX_AUDIO_CodingDTS;
  1052. break;
  1053. case AV_CODEC_ID_AC3:
  1054. case AV_CODEC_ID_EAC3:
  1055. CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingDDP\n");
  1056. m_eEncoding = OMX_AUDIO_CodingDDP;
  1057. break;
  1058. default:
  1059. CLog::Log(LOGDEBUG, "COMXAudio::SetCodingType OMX_AUDIO_CodingPCM\n");
  1060. m_eEncoding = OMX_AUDIO_CodingPCM;
  1061. break;
  1062. }
  1063. }
  1064. bool COMXAudio::CanHWDecode(AVCodecID codec)
  1065. {
  1066. switch(codec)
  1067. {
  1068. /*
  1069. case AV_CODEC_ID_VORBIS:
  1070. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingVORBIS\n");
  1071. m_eEncoding = OMX_AUDIO_CodingVORBIS;
  1072. m_config.hwdecode = true;
  1073. break;
  1074. case AV_CODEC_ID_AAC:
  1075. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingAAC\n");
  1076. m_eEncoding = OMX_AUDIO_CodingAAC;
  1077. m_config.hwdecode = true;
  1078. break;
  1079. */
  1080. case AV_CODEC_ID_MP2:
  1081. case AV_CODEC_ID_MP3:
  1082. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingMP3\n");
  1083. m_eEncoding = OMX_AUDIO_CodingMP3;
  1084. m_config.hwdecode = true;
  1085. break;
  1086. case AV_CODEC_ID_DTS:
  1087. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDTS\n");
  1088. m_eEncoding = OMX_AUDIO_CodingDTS;
  1089. m_config.hwdecode = true;
  1090. break;
  1091. case AV_CODEC_ID_AC3:
  1092. case AV_CODEC_ID_EAC3:
  1093. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingDDP\n");
  1094. m_eEncoding = OMX_AUDIO_CodingDDP;
  1095. m_config.hwdecode = true;
  1096. break;
  1097. default:
  1098. CLog::Log(LOGDEBUG, "COMXAudio::CanHWDecode OMX_AUDIO_CodingPCM\n");
  1099. m_eEncoding = OMX_AUDIO_CodingPCM;
  1100. m_config.hwdecode = false;
  1101. break;
  1102. }
  1103. return m_config.hwdecode;
  1104. }
  1105. bool COMXAudio::HWDecode(AVCodecID codec)
  1106. {
  1107. bool ret = false;
  1108. switch(codec)
  1109. {
  1110. /*
  1111. case AV_CODEC_ID_VORBIS:
  1112. CLog::Log(LOGDEBUG, "COMXAudio::HWDecode AV_CODEC_ID_VORBIS\n");
  1113. ret = true;
  1114. break;
  1115. case AV_CODEC_ID_AAC:
  1116. CLog::Log(LOGDEBUG, "COMXAudio::HWDecode AV_CODEC_ID_AAC\n");
  1117. ret = true;
  1118. break;
  1119. */
  1120. case AV_CODEC_ID_MP2:
  1121. case AV_CODEC_ID_MP3:
  1122. CLog::Log(LOGDEBUG, "COMXAudio::HWDecode AV_CODEC_ID_MP2 / AV_CODEC_ID_MP3\n");
  1123. ret = true;
  1124. break;
  1125. case AV_CODEC_ID_DTS:
  1126. CLog::Log(LOGDEBUG, "COMXAudio::HWDecode AV_CODEC_ID_DTS\n");
  1127. ret = true;
  1128. break;
  1129. case AV_CODEC_ID_AC3:
  1130. case AV_CODEC_ID_EAC3:
  1131. CLog::Log(LOGDEBUG, "COMXAudio::HWDecode AV_CODEC_ID_AC3 / AV_CODEC_ID_EAC3\n");
  1132. ret = true;
  1133. break;
  1134. default:
  1135. ret = false;
  1136. break;
  1137. }
  1138. return ret;
  1139. }
  1140. void COMXAudio::PrintChannels(OMX_AUDIO_CHANNELTYPE eChannelMapping[])
  1141. {
  1142. for(int i = 0; i < OMX_AUDIO_MAXCHANNELS; i++)
  1143. {
  1144. switch(eChannelMapping[i])
  1145. {
  1146. case OMX_AUDIO_ChannelLF:
  1147. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLF\n");
  1148. break;
  1149. case OMX_AUDIO_ChannelRF:
  1150. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRF\n");
  1151. break;
  1152. case OMX_AUDIO_ChannelCF:
  1153. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCF\n");
  1154. break;
  1155. case OMX_AUDIO_ChannelLS:
  1156. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLS\n");
  1157. break;
  1158. case OMX_AUDIO_ChannelRS:
  1159. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRS\n");
  1160. break;
  1161. case OMX_AUDIO_ChannelLFE:
  1162. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLFE\n");
  1163. break;
  1164. case OMX_AUDIO_ChannelCS:
  1165. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelCS\n");
  1166. break;
  1167. case OMX_AUDIO_ChannelLR:
  1168. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelLR\n");
  1169. break;
  1170. case OMX_AUDIO_ChannelRR:
  1171. CLog::Log(LOGDEBUG, "OMX_AUDIO_ChannelRR\n");
  1172. break;
  1173. case OMX_AUDIO_ChannelNone:
  1174. case OMX_AUDIO_ChannelKhronosExtensions:
  1175. case OMX_AUDIO_ChannelVendorStartUnused:
  1176. case OMX_AUDIO_ChannelMax:
  1177. default:
  1178. break;
  1179. }
  1180. }
  1181. }
  1182. void COMXAudio::PrintPCM(OMX_AUDIO_PARAM_PCMMODETYPE *pcm, std::string direction)
  1183. {
  1184. CLog::Log(LOGDEBUG, "pcm->direction : %s\n", direction.c_str());
  1185. CLog::Log(LOGDEBUG, "pcm->nPortIndex : %d\n", (int)pcm->nPortIndex);
  1186. CLog::Log(LOGDEBUG, "pcm->eNumData : %d\n", pcm->eNumData);
  1187. CLog::Log(LOGDEBUG, "pcm->eEndian : %d\n", pcm->eEndian);
  1188. CLog::Log(LOGDEBUG, "pcm->bInterleaved : %d\n", (int)pcm->bInterleaved);
  1189. CLog::Log(LOGDEBUG, "pcm->nBitPerSample : %d\n", (int)pcm->nBitPerSample);
  1190. CLog::Log(LOGDEBUG, "pcm->ePCMMode : %d\n", pcm->ePCMMode);
  1191. CLog::Log(LOGDEBUG, "pcm->nChannels : %d\n", (int)pcm->nChannels);
  1192. CLog::Log(LOGDEBUG, "pcm->nSamplingRate : %d\n", (int)pcm->nSamplingRate);
  1193. PrintChannels(pcm->eChannelMapping);
  1194. }
  1195. void COMXAudio::BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout)
  1196. {
  1197. int index = 0;
  1198. if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = PCM_FRONT_LEFT ;
  1199. if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = PCM_FRONT_RIGHT ;
  1200. if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = PCM_FRONT_CENTER ;
  1201. if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = PCM_LOW_FREQUENCY ;
  1202. if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = PCM_BACK_LEFT ;
  1203. if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = PCM_BACK_RIGHT ;
  1204. if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
  1205. if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
  1206. if (layout & AV_CH_BACK_CENTER ) channelMap[index++] = PCM_BACK_CENTER ;
  1207. if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = PCM_SIDE_LEFT ;
  1208. if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = PCM_SIDE_RIGHT ;
  1209. if (layout & AV_CH_TOP_CENTER ) channelMap[index++] = PCM_TOP_CENTER ;
  1210. if (layout & AV_CH_TOP_FRONT_LEFT ) channelMap[index++] = PCM_TOP_FRONT_LEFT ;
  1211. if (layout & AV_CH_TOP_FRONT_CENTER ) channelMap[index++] = PCM_TOP_FRONT_CENTER ;
  1212. if (layout & AV_CH_TOP_FRONT_RIGHT ) channelMap[index++] = PCM_TOP_FRONT_RIGHT ;
  1213. if (layout & AV_CH_TOP_BACK_LEFT ) channelMap[index++] = PCM_TOP_BACK_LEFT ;
  1214. if (layout & AV_CH_TOP_BACK_CENTER ) channelMap[index++] = PCM_TOP_BACK_CENTER ;
  1215. if (layout & AV_CH_TOP_BACK_RIGHT ) channelMap[index++] = PCM_TOP_BACK_RIGHT ;
  1216. while (index<OMX_AUDIO_MAXCHANNELS)
  1217. channelMap[index++] = PCM_INVALID;
  1218. }
  1219. // See CEA spec: Table 20, Audio InfoFrame data byte 4 for the ordering here
  1220. int COMXAudio::BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout)
  1221. {
  1222. int index = 0;
  1223. if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = PCM_FRONT_LEFT;
  1224. if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = PCM_FRONT_RIGHT;
  1225. if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = PCM_LOW_FREQUENCY;
  1226. if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = PCM_FRONT_CENTER;
  1227. if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = PCM_BACK_LEFT;
  1228. if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = PCM_BACK_RIGHT;
  1229. if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = PCM_SIDE_LEFT;
  1230. if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = PCM_SIDE_RIGHT;
  1231. while (index<OMX_AUDIO_MAXCHANNELS)
  1232. channelMap[index++] = PCM_INVALID;
  1233. int num_channels = 0;
  1234. for (index=0; index<OMX_AUDIO_MAXCHANNELS; index++)
  1235. if (channelMap[index] != PCM_INVALID)
  1236. num_channels = index+1;
  1237. // round up to power of 2
  1238. num_channels = num_channels > 4 ? 8 : num_channels > 2 ? 4 : num_channels;
  1239. return num_channels;
  1240. }
  1241. void COMXAudio::BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE * channelMap, uint64_t layout)
  1242. {
  1243. int index = 0;
  1244. if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLF;
  1245. if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRF;
  1246. if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = OMX_AUDIO_ChannelCF;
  1247. if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = OMX_AUDIO_ChannelLFE;
  1248. if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLR;
  1249. if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRR;
  1250. if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLS;
  1251. if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRS;
  1252. if (layout & AV_CH_BACK_CENTER ) channelMap[index++] = OMX_AUDIO_ChannelCS;
  1253. // following are not in openmax spec, but gpu does accept them
  1254. if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)10;
  1255. if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)11;
  1256. if (layout & AV_CH_TOP_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)12;
  1257. if (layout & AV_CH_TOP_FRONT_LEFT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)13;
  1258. if (layout & AV_CH_TOP_FRONT_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)14;
  1259. if (layout & AV_CH_TOP_FRONT_RIGHT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)15;
  1260. if (layout & AV_CH_TOP_BACK_LEFT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)16;
  1261. if (layout & AV_CH_TOP_BACK_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)17;
  1262. if (layout & AV_CH_TOP_BACK_RIGHT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)18;
  1263. while (index<OMX_AUDIO_MAXCHANNELS)
  1264. channelMap[index++] = OMX_AUDIO_ChannelNone;
  1265. }
  1266. uint64_t COMXAudio::GetChannelLayout(enum PCMLayout layout)
  1267. {
  1268. uint64_t layouts[] = {
  1269. /* 2.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT,
  1270. /* 2.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_LOW_FREQUENCY,
  1271. /* 3.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER,
  1272. /* 3.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_LOW_FREQUENCY,
  1273. /* 4.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
  1274. /* 4.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY,
  1275. /* 5.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
  1276. /* 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,
  1277. /* 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,
  1278. /* 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
  1279. };
  1280. return (int)layout < 10 ? layouts[(int)layout] : 0;
  1281. }