[rbp/omxplayer] Support both analogue and hdmi audio
authorpopcornmix <popcornmix@gmail.com>
Mon, 19 Aug 2013 20:45:20 +0000 (21:45 +0100)
committerpopcornmix <popcornmix@gmail.com>
Fri, 6 Sep 2013 17:15:17 +0000 (18:15 +0100)
Thanks to stupid-boy for the original implementation.

language/English/strings.po
system/settings/rbp.xml
xbmc/cores/omxplayer/OMXAudio.cpp
xbmc/cores/omxplayer/OMXAudio.h
xbmc/cores/omxplayer/OMXPlayerAudio.cpp

index b89ee27..3f957b0 100644 (file)
@@ -14332,6 +14332,11 @@ msgctxt "#36541"
 msgid "Allows volume control from AirPlay clients."
 msgstr ""
 
+#: system/settings/rbp.xml
+msgctxt "#36542"
+msgid "Output to both analogue (headphones) and HDMI"
+msgstr ""
+
 #reserved strings 365XX
 
 #: xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNavigator.cpp
@@ -14379,4 +14384,9 @@ msgstr ""
 #: system/settings/settings.xml
 msgctxt "#37016"
 msgid "Select this option if your receiver is capable of decoding E-AC3 streams."
-msgstr ""
\ No newline at end of file
+msgstr ""
+
+#: system/settings/rbp.xml
+msgctxt "#37017"
+msgid "Dual audio output"
+msgstr ""
index 0369c50..5293091 100644 (file)
         <setting id="audiooutput.dtshdpassthrough">
           <visible>false</visible>
         </setting>
+        <setting id="audiooutput.eac3passthrough">
+          <visible>false</visible>
+        </setting>
+        <setting id="audiooutput.ac3passthrough">
+          <default>true</default>
+          <dependencies>
+            <dependency type="enable">
+              <and>
+                <or>
+                  <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 -->
+                  <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI -->
+                </or>
+                <condition setting="audiooutput.dualaudio">false</condition>
+              </and>
+            </dependency>
+          </dependencies>
+        </setting>
+        <setting id="audiooutput.dtspassthrough">
+          <default>true</default>
+          <dependencies>
+            <dependency type="enable">
+              <and>
+                <or>
+                  <condition setting="audiooutput.mode">1</condition> <!-- AUDIO_IEC958 -->
+                  <condition setting="audiooutput.mode">2</condition> <!-- AUDIO_HDMI -->
+                </or>
+                <condition setting="audiooutput.dualaudio">false</condition>
+              </and>
+            </dependency>
+          </dependencies>
+        </setting>
+        <setting id="audiooutput.dualaudio" type="boolean" label="37017" help="36542">
+          <level>2</level>
+          <default>false</default>
+        </setting>
       </group>
       <group id="2">
         <visible>false</visible>
index cc1391f..d2864b9 100644 (file)
@@ -184,84 +184,224 @@ bool COMXAudio::PortSettingsChanged()
     if(!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit))
       return false;
   }
-
-  if(!m_omx_render.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
-    return false;
+  if(CSettings::Get().GetBool("audiooutput.dualaudio"))
+  {
+    if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
+      return false;
+  }
+  if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetInt("audiooutput.mode") == AUDIO_ANALOG)
+  {
+    if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
+      return false;
+  }
+  if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI)
+  {
+    if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
+      return false;
+  }
 
   ApplyVolume();
 
-  if(!m_Passthrough)
+  if( m_omx_mixer.IsInitialized() )
   {
     /* setup mixer output */
     OMX_INIT_STRUCTURE(m_pcm_output);
-    m_pcm_output.nPortIndex      = m_omx_decoder.GetOutputPort();
+    m_pcm_output.nPortIndex = m_omx_decoder.GetOutputPort();
     omx_err = m_omx_decoder.GetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
     if(omx_err != OMX_ErrorNone)
     {
-       CLog::Log(LOGERROR, "%s::%s - error SetParameter 1 output omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder GetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
     }
-    m_pcm_output.nPortIndex      = m_omx_mixer.GetOutputPort();
 
     /* mixer output is always stereo */
     m_pcm_output.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
     m_pcm_output.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
     m_pcm_output.nChannels = 2;
 
+    m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort();
     omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
     if(omx_err != OMX_ErrorNone)
     {
-      CLog::Log(LOGERROR, "%s::%s - error SetParameter 1 output omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
     }
+
     CLog::Log(LOGDEBUG, "%s::%s - Output bps %d samplerate %d channels %d buffer size %d bytes per second %d",
         CLASSNAME, __func__, (int)m_pcm_output.nBitPerSample, (int)m_pcm_output.nSamplingRate, (int)m_pcm_output.nChannels, m_BufferLen, m_BytesPerSec);
     PrintPCM(&m_pcm_output, std::string("output"));
-  }
 
-  m_omx_tunnel_clock.Initialize(m_omx_clock, m_omx_clock->GetInputPort(), &m_omx_render, m_omx_render.GetInputPort()+1);
+    if( m_omx_splitter.IsInitialized() )
+    {
+      m_pcm_output.nPortIndex = m_omx_splitter.GetInputPort();
+      omx_err = m_omx_splitter.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "%s::%s - error m_omx_splitter SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+        return false;
+      }
+
+      // Splitter will copy input params to output when input port is enabled.
+      omx_err = m_omx_splitter.SetStateForComponent(OMX_StateIdle);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "COMXAudio::AddPackets - Error setting OMX_StateIdle 0x%08x for m_omx_splitter", omx_err);
+        return false;
+      }
+      m_omx_splitter.EnablePort(m_omx_splitter.GetInputPort(), false);
+      m_omx_splitter.DisablePort(m_omx_splitter.GetInputPort(), false);
+    }
 
-  omx_err = m_omx_tunnel_clock.Establish(false);
-  if(omx_err != OMX_ErrorNone)
+    if( m_omx_render_analog.IsInitialized() )
+    {
+      m_pcm_output.nPortIndex = m_omx_render_analog.GetInputPort();
+      omx_err = m_omx_render_analog.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "%s::%s - error m_omx_render_analog SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+        return false;
+      }
+    }
+
+    if( m_omx_render_hdmi.IsInitialized() )
+    {
+      m_pcm_output.nPortIndex = m_omx_render_hdmi.GetInputPort();
+      omx_err = m_omx_render_hdmi.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "%s::%s - error m_omx_render_hdmi SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+        return false;
+      }
+    }
+  }
+  if( m_omx_render_analog.IsInitialized() )
   {
-    CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
-    return false;
+    m_omx_tunnel_clock_analog.Initialize(m_omx_clock, m_omx_clock->GetInputPort(),
+      &m_omx_render_analog, m_omx_render_analog.GetInputPort()+1);
+
+    omx_err = m_omx_tunnel_clock_analog.Establish(false);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_analog.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
+    m_omx_render_analog.ResetEos();
   }
+  if( m_omx_render_hdmi.IsInitialized() )
+  {
+    m_omx_tunnel_clock_hdmi.Initialize(m_omx_clock, m_omx_clock->GetInputPort() + (m_omx_render_analog.IsInitialized() ? 2 : 0),
+      &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort()+1);
 
-  m_omx_render.ResetEos();
+    omx_err = m_omx_tunnel_clock_hdmi.Establish(false);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_clock_hdmi.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
+    m_omx_render_hdmi.ResetEos();
+  }
 
-  // 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.
-  // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
-  if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
+  if( m_omx_render_analog.IsInitialized() )
   {
-    OMX_CONFIG_BOOLEANTYPE configBool;
-    OMX_INIT_STRUCTURE(configBool);
-    configBool.bEnabled = OMX_FALSE;
+    // 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.
+    // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
+    if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
+    {
+      OMX_CONFIG_BOOLEANTYPE configBool;
+      OMX_INIT_STRUCTURE(configBool);
+      configBool.bEnabled = OMX_FALSE;
 
-    omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
+      omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
+      if (omx_err != OMX_ErrorNone)
+         return false;
+    }
+
+    OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
+    OMX_INIT_STRUCTURE(audioDest);
+    strncpy((char *)audioDest.sName, "local", strlen("local"));
+    omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
     if (omx_err != OMX_ErrorNone)
-       return false;
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
   }
 
-  OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
-  OMX_INIT_STRUCTURE(audioDest);
-  strncpy((char *)audioDest.sName, m_deviceuse.c_str(), strlen(m_deviceuse.c_str()));
-
-  omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
-  if (omx_err != OMX_ErrorNone)
+  if( m_omx_render_hdmi.IsInitialized() )
   {
-    CLog::Log(LOGERROR, "%s::%s - m_omx_render.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
-    return false;
+    // 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.
+    // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
+    if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
+    {
+      OMX_CONFIG_BOOLEANTYPE configBool;
+      OMX_INIT_STRUCTURE(configBool);
+      configBool.bEnabled = OMX_FALSE;
+
+      omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmClockReferenceSource, &configBool);
+      if (omx_err != OMX_ErrorNone)
+         return false;
+    }
+
+    OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
+    OMX_INIT_STRUCTURE(audioDest);
+    strncpy((char *)audioDest.sName, "hdmi", strlen("hdmi"));
+    omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
+    if (omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi.SetConfig omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
   }
 
-  if(!m_Passthrough)
+  if( m_omx_splitter.IsInitialized() )
+  {
+    m_omx_tunnel_splitter_analog.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
+    omx_err = m_omx_tunnel_splitter_analog.Establish(false);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_analog.Establish 0x%08x", omx_err);
+      return false;
+    }
+
+    m_omx_tunnel_splitter_hdmi.Initialize(&m_omx_splitter, m_omx_splitter.GetOutputPort() + 1, &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
+    omx_err = m_omx_tunnel_splitter_hdmi.Establish(false);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "COMXAudio::Initialize - Error m_omx_tunnel_splitter_hdmi.Establish 0x%08x", omx_err);
+      return false;
+    }
+  }
+  if( m_omx_mixer.IsInitialized() )
   {
     m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_mixer, m_omx_mixer.GetInputPort());
-    m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort());
+    if( m_omx_splitter.IsInitialized() )
+    {
+      m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_splitter, m_omx_splitter.GetInputPort());
+    }
+    else
+    {
+      if( m_omx_render_analog.IsInitialized() )
+      {
+        m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
+      }
+      if( m_omx_render_hdmi.IsInitialized() )
+      {
+        m_omx_tunnel_mixer.Initialize(&m_omx_mixer, m_omx_mixer.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
+      }
+    }
     CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d nopassthrough", CLASSNAME, __func__,
             (int)m_pcm_input.nBitPerSample, m_pcm_input.ePCMMode, (int)m_pcm_input.nChannels, (int)m_pcm_input.nSamplingRate);
   }
   else
   {
-    m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render, m_omx_render.GetInputPort());
+    if( m_omx_render_analog.IsInitialized() )
+    {
+      m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_analog, m_omx_render_analog.GetInputPort());
+    }
+    else if( m_omx_render_hdmi.IsInitialized() )
+    {
+      m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_render_hdmi, m_omx_render_hdmi.GetInputPort());
+    }
     CLog::Log(LOGDEBUG, "%s::%s - bits:%d mode:%d channels:%d srate:%d passthrough", CLASSNAME, __func__,
             0, 0, 0, 0);
   }
@@ -272,13 +412,18 @@ bool COMXAudio::PortSettingsChanged()
     CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
     return false;
   }
-  if(!m_Passthrough)
+
+  if( m_omx_mixer.IsInitialized() )
   {
     omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting);
     if(omx_err != OMX_ErrorNone) {
       CLog::Log(LOGERROR, "%s::%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
       return false;
     }
+  }
+
+  if( m_omx_mixer.IsInitialized() )
+  {
     omx_err = m_omx_tunnel_mixer.Establish(false);
     if(omx_err != OMX_ErrorNone)
     {
@@ -287,18 +432,39 @@ bool COMXAudio::PortSettingsChanged()
     }
   }
 
-  omx_err = m_omx_render.SetStateForComponent(OMX_StateExecuting);
-  if(omx_err != OMX_ErrorNone)
+  if( m_omx_splitter.IsInitialized() )
   {
-    CLog::Log(LOGERROR, "%s::%s - m_omx_render OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
-    return false;
+    omx_err = m_omx_splitter.SetStateForComponent(OMX_StateExecuting);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_splitter OMX_StateExecuting 0x%08x", CLASSNAME, __func__, omx_err);
+     return false;
+    }
+  }
+  if( m_omx_render_analog.IsInitialized() )
+  {
+    omx_err = m_omx_render_analog.SetStateForComponent(OMX_StateExecuting);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_render_analog OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
+  }
+  if( m_omx_render_hdmi.IsInitialized() )
+  {
+    omx_err = m_omx_render_hdmi.SetStateForComponent(OMX_StateExecuting);
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - m_omx_render_hdmi OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
+      return false;
+    }
   }
 
   m_settings_changed = true;
   return true;
 }
 
-bool COMXAudio::Initialize(AEAudioFormat format, std::string& device, OMXClock *clock, CDVDStreamInfo &hints, bool bUsePassthrough, bool bUseHWDecode)
+bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, bool bUsePassthrough, bool bUseHWDecode)
 {
   CSingleLock lock (m_critSection);
   OMX_ERRORTYPE omx_err;
@@ -308,12 +474,6 @@ bool COMXAudio::Initialize(AEAudioFormat format, std::string& device, OMXClock *
   if(!m_dllAvUtil.Load())
     return false;
 
-  if(device == "hdmi") {
-    m_deviceuse = "hdmi";
-  } else {
-    m_deviceuse = "local";
-  }
-
   m_HWDecode    = bUseHWDecode;
   m_Passthrough = bUsePassthrough;
 
@@ -592,8 +752,8 @@ bool COMXAudio::Initialize(AEAudioFormat format, std::string& device, OMXClock *
   CLog::Log(LOGDEBUG, "COMXAudio::Initialize Input bps %d samplerate %d channels %d buffer size %d bytes per second %d", 
       (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_BytesPerSec);
   PrintPCM(&m_pcm_output, std::string("input"));
-  CLog::Log(LOGDEBUG, "COMXAudio::Initialize device %s passthrough %d hwdecode %d", 
-      device.c_str(), m_Passthrough, m_HWDecode);
+  CLog::Log(LOGDEBUG, "COMXAudio::Initialize device passthrough %d hwdecode %d",
+     m_Passthrough, m_HWDecode);
 
   return true;
 }
@@ -603,20 +763,27 @@ bool COMXAudio::Deinitialize()
 {
   CSingleLock lock (m_critSection);
 
-  m_omx_tunnel_decoder.Flush();
-  if(!m_Passthrough)
-    m_omx_tunnel_mixer.Flush();
-  m_omx_tunnel_clock.Flush();
-
-  m_omx_tunnel_clock.Deestablish();
-  if(!m_Passthrough)
+  Flush();
+
+  if ( m_omx_tunnel_clock_analog.IsInitialized() )
+    m_omx_tunnel_clock_analog.Deestablish();
+  if ( m_omx_tunnel_clock_hdmi.IsInitialized() )
+    m_omx_tunnel_clock_hdmi.Deestablish();
+  if ( m_omx_tunnel_splitter_analog.IsInitialized() )
+    m_omx_tunnel_splitter_analog.Deestablish();
+  if ( m_omx_tunnel_splitter_hdmi.IsInitialized() )
+    m_omx_tunnel_splitter_hdmi.Deestablish();
+  if ( m_omx_tunnel_mixer.IsInitialized() )
     m_omx_tunnel_mixer.Deestablish();
   m_omx_tunnel_decoder.Deestablish();
 
-  m_omx_decoder.FlushInput();
-
-  m_omx_render.Deinitialize(true);
-  if(!m_Passthrough)
+  if ( m_omx_render_analog.IsInitialized() )
+    m_omx_render_analog.Deinitialize(true);
+  if ( m_omx_render_hdmi.IsInitialized() )
+    m_omx_render_hdmi.Deinitialize(true);
+  if ( m_omx_splitter.IsInitialized() )
+    m_omx_splitter.Deinitialize(true);
+  if ( m_omx_mixer.IsInitialized() )
     m_omx_mixer.Deinitialize(true);
   m_omx_decoder.Deinitialize(true);
 
@@ -651,11 +818,26 @@ void COMXAudio::Flush()
   if(!m_Initialized)
     return;
 
-  m_omx_decoder.FlushInput();
+  m_omx_decoder.FlushAll();
   m_omx_tunnel_decoder.Flush();
-  if(!m_Passthrough)
+
+  if ( m_omx_mixer.IsInitialized() )
+    m_omx_mixer.FlushAll();
+  if( m_omx_tunnel_mixer.IsInitialized() )
     m_omx_tunnel_mixer.Flush();
-  
+
+  if ( m_omx_splitter.IsInitialized() )
+    m_omx_splitter.FlushAll();
+  if ( m_omx_tunnel_splitter_analog.IsInitialized() )
+    m_omx_tunnel_splitter_analog.Flush();
+  if ( m_omx_tunnel_splitter_hdmi.IsInitialized() )
+    m_omx_tunnel_splitter_hdmi.Flush();
+
+  if ( m_omx_render_analog.IsInitialized() )
+    m_omx_render_analog.FlushAll();
+  if ( m_omx_render_hdmi.IsInitialized() )
+    m_omx_render_hdmi.FlushAll();
+
   m_last_pts      = DVD_NOPTS_VALUE;
   m_LostSync      = true;
   m_setStartTime  = true;
@@ -746,19 +928,32 @@ bool COMXAudio::ApplyVolume(void)
   {
     OMX_AUDIO_CONFIG_VOLUMETYPE volume;
     OMX_INIT_STRUCTURE(volume);
-    volume.nPortIndex = m_omx_render.GetInputPort();
 
     volume.bLinear    = OMX_TRUE;
     float hardwareVolume = fVolume * gain * 100.0f;
     volume.sVolume.nValue = (int)(hardwareVolume + 0.5f);
 
-    OMX_ERRORTYPE omx_err =
-      m_omx_render.SetConfig(OMX_IndexConfigAudioVolume, &volume);
-    if(omx_err != OMX_ErrorNone)
+    if(m_omx_render_analog.IsInitialized())
     {
-      CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
+      volume.nPortIndex = m_omx_render_analog.GetInputPort();
+      OMX_ERRORTYPE omx_err = m_omx_render_analog.SetConfig(OMX_IndexConfigAudioVolume, &volume);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
                 CLASSNAME, __func__, omx_err);
-      return false;
+        return false;
+      }
+    }
+    if(m_omx_render_hdmi.IsInitialized())
+    {
+      volume.nPortIndex = m_omx_render_hdmi.GetInputPort();
+      OMX_ERRORTYPE omx_err = m_omx_render_hdmi.SetConfig(OMX_IndexConfigAudioVolume, &volume);
+      if(omx_err != OMX_ErrorNone)
+      {
+        CLog::Log(LOGERROR, "%s::%s - error setting OMX_IndexConfigAudioVolume, error 0x%08x\n",
+                CLASSNAME, __func__, omx_err);
+        return false;
+      }
     }
   }
   CLog::Log(LOGINFO, "%s::%s - Volume=%.2f\n", CLASSNAME, __func__, fVolume);
@@ -1043,16 +1238,32 @@ unsigned int COMXAudio::GetAudioRenderingLatency()
 
   OMX_PARAM_U32TYPE param;
   OMX_INIT_STRUCTURE(param);
-  param.nPortIndex = m_omx_render.GetInputPort();
 
-  OMX_ERRORTYPE omx_err =
-    m_omx_render.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
+  if(m_omx_render_analog.IsInitialized())
+  {
+    param.nPortIndex = m_omx_render_analog.GetInputPort();
+
+    OMX_ERRORTYPE omx_err = m_omx_render_analog.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
 
-  if(omx_err != OMX_ErrorNone)
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
+        CLASSNAME, __func__, omx_err);
+      return 0;
+    }
+  }
+  else if(m_omx_render_hdmi.IsInitialized())
   {
-    CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
-      CLASSNAME, __func__, omx_err);
-    return 0;
+    param.nPortIndex = m_omx_render_hdmi.GetInputPort();
+
+    OMX_ERRORTYPE omx_err = m_omx_render_hdmi.GetConfig(OMX_IndexConfigAudioRenderingLatency, &param);
+
+    if(omx_err != OMX_ErrorNone)
+    {
+      CLog::Log(LOGERROR, "%s::%s - error getting OMX_IndexConfigAudioRenderingLatency error 0x%08x\n",
+        CLASSNAME, __func__, omx_err);
+      return 0;
+    }
   }
 
   return param.nU32;
index 309dc75..09993e6 100644 (file)
@@ -60,7 +60,7 @@ public:
   float GetCacheTime();
   float GetCacheTotal();
   COMXAudio();
-  bool Initialize(AEAudioFormat format, std::string& device, OMXClock *clock, CDVDStreamInfo &hints, bool bUsePassthrough, bool bUseHWDecode);
+  bool Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, bool bUsePassthrough, bool bUseHWDecode);
   bool PortSettingsChanged();
   ~COMXAudio();
 
@@ -118,7 +118,6 @@ private:
   OMX_AUDIO_CODINGTYPE m_eEncoding;
   uint8_t       *m_extradata;
   int           m_extrasize;
-  std::string   m_deviceuse;
   // stuff for visualisation
   double        m_last_pts;
   int           m_vizBufferSize;
@@ -141,12 +140,17 @@ private:
   WAVEFORMATEXTENSIBLE        m_wave_header;
   AEAudioFormat m_format;
 protected:
-  COMXCoreComponent m_omx_render;
+  COMXCoreComponent m_omx_render_analog;
+  COMXCoreComponent m_omx_render_hdmi;
+  COMXCoreComponent m_omx_splitter;
   COMXCoreComponent m_omx_mixer;
   COMXCoreComponent m_omx_decoder;
-  COMXCoreTunel     m_omx_tunnel_clock;
+  COMXCoreTunel     m_omx_tunnel_clock_analog;
+  COMXCoreTunel     m_omx_tunnel_clock_hdmi;
   COMXCoreTunel     m_omx_tunnel_mixer;
   COMXCoreTunel     m_omx_tunnel_decoder;
+  COMXCoreTunel     m_omx_tunnel_splitter_analog;
+  COMXCoreTunel     m_omx_tunnel_splitter_hdmi;
   DllAvUtil         m_dllAvUtil;
 
   OMX_AUDIO_CHANNELTYPE m_input_channels[OMX_AUDIO_MAXCHANNELS];
index 8343d62..4121300 100644 (file)
@@ -146,7 +146,8 @@ void OMXPlayerAudio::OpenStream(CDVDStreamInfo &hints, COMXAudioCodecOMX *codec)
   m_flush           = false;
   m_nChannels       = 0;
   m_stalled         = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
-  m_use_passthrough = (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI) ? true : false ;
+  m_use_passthrough = (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI &&
+                      !CSettings::Get().GetBool("audiooutput.dualaudio")) ? true : false ;
   m_use_hw_decode   = g_advancedSettings.m_omxHWAudioDecode;
   m_format.m_dataFormat    = GetDataFormat(m_hints);
   m_format.m_sampleRate    = 0;
@@ -580,13 +581,6 @@ bool OMXPlayerAudio::OpenDecoder()
   /* GetDataFormat is setting up evrything */
   m_format.m_dataFormat = GetDataFormat(m_hints);
 
-  std::string device = "";
-  
-  if(CSettings::Get().GetInt("audiooutput.mode") == AUDIO_HDMI)
-    device = "hdmi";
-  else
-    device = "local";
-
   m_format.m_channelLayout.Reset();
   if (m_pAudioCodec && !m_passthrough)
     m_format.m_channelLayout = m_pAudioCodec->GetChannelMap();
@@ -601,7 +595,7 @@ bool OMXPlayerAudio::OpenDecoder()
     if (m_nChannels > 4 ) m_format.m_channelLayout += AE_CH_BL;
     if (m_nChannels > 5 ) m_format.m_channelLayout += AE_CH_BR;
   }
-  bool bAudioRenderOpen = m_omxAudio.Initialize(m_format, device, m_av_clock, m_hints, m_passthrough, m_hw_decode);
+  bool bAudioRenderOpen = m_omxAudio.Initialize(m_format, m_av_clock, m_hints, m_passthrough, m_hw_decode);
 
   m_codec_name = "";
   m_bad_state  = !bAudioRenderOpen;