Open scotthardwick opened 7 years ago
Not currently possible. Some discussion here: https://github.com/popcornmix/omxplayer/pull/463 @fabled may be explain exactly what is still required.
Well, pretty much all of the code works. It would just require specifying the command line parameters and implementing the small bit of glue code. The format it was originally was not good enough, so I'm open for suggestions. The current options are: local, hdmi, both and alsa. We'd need something to make both use alsa, or add new target name such as 'alsa+hdmi' to specify output on both. Suggestions?
-o alsa+hdmi
is good for me.
My personal thanks to both of you! Your coding skills and knowledge of how all this truly is beyond impressive to someone who is much better categorized as a "novice".
-o local -o hdmi -o hdmi+local (if you want to alias "both") -o alsa -o alsa+local -o alsa+hdmi
Fabled--- Could you please also add Alsa+local support? Thank You!
@scotthardwick alsa+local is slightly more complex. It would require setting up additional OMX switching logic. Also I wonder should alsa or local output be the clock master. @popcornmix Care to review the pull request for alsa+hdmi? Any suggestions how to do splitting and clocking for alsa+local output? Would we also need alsa+local+hdmi?
@fabled -- I would think alsa would be the clock master in that situation. But that is just my gut thought. Thank you for continuing to investigate this for me!
I have been hesitating to comment on this as I was already late at the party... But still seeing that it is not implemented/pulled in yet, I will give my comment for what it is worth :-)
Isn't it better to have a comma separated list of devices you want to use? E.g. -o local,hdmi
for both the local and hdmi, or -o alsa:snd2,local
for both local and alsa device named snd2.
The notation alsa+hdmi[:device]
looks more specifying the hdmi device, whereas specifying the alsa device is meant.
@jehutting Sounds good to me. @popcornmix Any suggestions how to modify to code the pass a list of sound outputs instead of single device name?
I'm happy with @jehutting's syntax.
I think I'd probably make the OMXAudioConfig.device become the comma separated string.
I'd remove the "omx:" prefix as I don't see that being essential for the omxplayer.cpp -> OMXAudio.cpp API.
Existing command line option -o both
would behave the same as -o hdmi,local
so internally I'd pass hdmi,local
and treat both
just as a shortcut that is expanded by omxplayer.cpp.
Code like
if (m_config.device == "omx:both" || m_config.device == "omx:hdmi")
{
if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
return false;
}
would become
if (m_config.device.find("hdmi") != std::string::npos)
{
if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
return false;
}
(a helper function for checking if m_config.device enables "hdmi" etc is also valid) Up to you if you now parse the alsa subdevice from the device string inside OMXAudio.cpp (perhaps with a helper function) rather than using subdevice.
I'm using (in my own, not-gihub'ed, not public'ed) omxplayer the following code:
// audio out device
{
std::vector<std::string> devices;
boost::split(devices, settings.device_string, boost::is_any_of(","), boost::token_compress_on);
m_config_audio.devices = OMXAudioConfig::AudioDevice::NONE;
for(auto it = devices.begin(); it != devices.end(); it++)
{
#define device (*it)
if(device == "both")
m_config_audio.devices |= (OMXAudioConfig::AudioDevice::LOCAL|OMXAudioConfig::AudioDevice::HDMI);
else if(device == "local")
m_config_audio.devices |= OMXAudioConfig::AudioDevice::LOCAL;
else if(device == "hdmi")
m_config_audio.devices |= OMXAudioConfig::AudioDevice::HDMI;
else if(device.substr(0, 4) == "alsa")
{
m_config_audio.devices |= OMXAudioConfig::AudioDevice::ALSA;
// check for alsa device name
if(device[4] == ':')
m_config_audio.alsa_device_name = device.substr(4+1/* to skip ':' */);
}
}
}
Changed to using string.find() -just for fun-:
// audio out device
m_config_audio.devices = OMXAudioConfig::AudioDevice::NONE;
if(settings.device_string.find("both") != std::string::npos)
m_config_audio.devices = (OMXAudioConfig::AudioDevice::LOCAL|OMXAudioConfig::AudioDevice::HDMI);
else
{
if(settings.device_string.find("local") != std::string::npos)
m_config_audio.devices = OMXAudioConfig::AudioDevice::LOCAL;
if(settings.device_string.find("hdmi") != std::string::npos)
m_config_audio.devices |= OMXAudioConfig::AudioDevice::HDMI;
}
size_t pos = settings.device_string.find("alsa");
if(pos != std::string::npos)
{
m_config_audio.devices |= OMXAudioConfig::AudioDevice::ALSA;
pos += 4; // position right behind "alsa"
// check for alsa device name
if(settings.device_string[pos] == ':')
{
pos++; // name without the ':' character
size_t end = settings.device_string.find(',', pos);
if(end == std::string::npos) // get name till end of device_string...
m_config_audio.alsa_device_name = settings.device_string.substr(pos);
else // ...or till (found) separator
m_config_audio.alsa_device_name = settings.device_string.substr(pos, end-pos);
}
}
The AudioDevice class defined in OMXAudio.h:
class OMXAudioConfig
{
public:
enum class AudioDevice : std::uint8_t { NONE=0x00, LOCAL=0x01, HDMI=0x02, ALSA=0x04 };
friend bool operator&(AudioDevice lhs, AudioDevice rhs) { return ((uint8_t)lhs & (uint8_t)rhs) ? true : false; }
friend AudioDevice operator|(const AudioDevice lhs, const AudioDevice rhs) { return static_cast<AudioDevice>((uint8_t)lhs | (uint8_t)rhs); }
friend AudioDevice& operator|=(AudioDevice& lhs, const AudioDevice rhs) { return lhs = static_cast<AudioDevice>((uint8_t)lhs | (uint8_t)rhs); }
COMXStreamInfo hints;
AudioDevice devices;
std::string alsa_device_name;
...
OMXAudioConfig()
{
devices = AudioDevice::NONE;
alsa_device_name = "default";
...
}
};
A snapshot of its usage (in OMXAudio.cpp)
// S P L I T T E R I N I T I A L I S A T I O N
// Only when two or more render components are used
int ndevices = 0;
if(m_config.devices & OMXAudioConfig::AudioDevice::LOCAL)
ndevices++;
if(m_config.devices & OMXAudioConfig::AudioDevice::HDMI)
ndevices++;
if(m_config.devices & OMXAudioConfig::AudioDevice::ALSA)
ndevices++;
if(ndevices > 1)
{
if(!m_omx_splitter.Initialize("OMX.broadcom.audio_splitter", OMX_IndexParamAudioInit))
{
CLog::Log(LOGERROR, "COMXAudio::PortSettingsChanged() FAIL audio_splitter OMX_IndexParamAudioInit\n");
return false;
}
}
// R E N D E R I N I T I A L I S A T I O N
if(m_config.devices & OMXAudioConfig::AudioDevice::LOCAL)
{
if(!m_omx_render_analog.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
{
CLog::Log(LOGERROR, "COMXAudio::PortSettingsChanged() FAIL analog audio_render OMX_IndexParamAudioInit\n");
return false;
}
}
if(m_config.devices & OMXAudioConfig::AudioDevice::HDMI)
{
if(!m_omx_render_hdmi.Initialize("OMX.broadcom.audio_render", OMX_IndexParamAudioInit))
{
CLog::Log(LOGERROR, "COMXAudio::PortSettingsChanged() FAIL hdmi audio_render OMX_IndexParamAudioInit\n");
return false;
}
}
I'm describing the OpenMAX layer of omxplayer in OMXPlayer-OpenMAX-components.pdf
Work in progress...
I also started working on this a little bit. But I want to pass the full audio device string to OMXAudio so it can create the audio graph from it. This allows e.g. output to two alsa devices, and automatically uses the first audio device as clock master so user can decide that too. I pushed WIP code (does not compile) to https://github.com/fabled/omxplayer/commit/feca5cec671b3e859cde0325f70d18d37d422fa2
Ok, updated code now at https://github.com/fabled/omxplayer/commit/cd09c41960fc9911c2fafe92c74542ecc609477a. It should mostly work, though error checking is not done fully yet.
Use -o
local,hdmi
for outputting locally (clock master) and hdmi
hdmi,alsa
for outputting hdmi (clock master) and alsa (default)
alsa:mydev,hdmi,local
for alsa 'mydev' being clock master but copying to hdmi and local
alsa:foo,alsa:bar
for two alsa devices
etc.
Maybe someone could take a look at the code changes if it looks as an idea ok? I still need to add proper error checking for omx calls and that the maximum amount of audio output devices is not exceeded.
@fabled how is it going? It sounds like a lot has been done and only little remains. It would cool to get this implemented
@fabled any news on this one?
I'm waiting feedback from @popcornmix for the above mentioned commit.
I have been researching on Google and I seem to keep coming up that at least in the past it was not possible to get simultaneous audio to HDMI and I2C.
Is there a way to get simultaneous output to Local jack and ALSA (in my case I am using a Hifiberry Amp+)
Thanks for any input!
Best!
Scott