[alsa-devel] How to handle HBR pass-through? (new PCM_FORMAT?)
Hi all!
Passing through compressed audio via a digital link (S/PDIF, HDMI) is done by encapsulating the audio in a constant-bitrate IEC-61937 format, which is then passed to alsa as a normal 16bit PCM stream.
However, there is a new complication: Codecs that require an iec60958 frame rate higher than 192kHz (currently TrueHD/MLP and DTS-HD) need to be transmitted in HDMI (note that these can't be transmitted in normal S/PDIF at all) in a slightly different way.
The transmission via HDMI is essentially the same as transmission of 8-channel PCM stream with sample rate of iec60958_frame_rate/4 (e.g. 192kHz for TrueHD), with the samples inside a HBR packet instead of standard audio sample packet.
What this means is that if just the needed HBR bits are set in the audio driver, one can play back e.g. TrueHD by passing the IEC-61937 stream to ALSA as 192kHz 8-channel 16-bit PCM data; of course normal 8-channel PCM playback wouldn't work anymore then. So the driver would need to know if this is 8- channel PCM or 8-channel compressed audio.
Which brings us to my question: How should the user be able to do this, i.e. inform the driver whether this is 8-channel PCM data or compressed audio data?
One easy option would be to have a separate IEC61937_HBR format in ALSA which could be used for IEC-61937 streams represented as 8x 16-bit channels.
If that would be considered too specific, we could add a more generic IEC61937 format, which is the same as above except that "normal" ( = "2 channel") IEC-61937 streams could be used as well. However, as normal IEC-61937 streams can be used with S/PDIF as well, we'd AFAICS need to add such format bit to all S/PDIF drivers or have a no-op converter to the more widely supported 16- bit PCM format. Technically, I guess, IEC61937 data should be considered 8-bit or 32-bit (which is the amount of data in a single IEC-60958 frame) 1-channel stream, but that would mean the needed sample rate values would be far higher, which would be confusing since 16-bit PCM samples would not be supported at those rates.
Another possible option could be to have some ALSA device flag like AESx now are (I'm not sure how those are handled, maybe it wouldn't work).
Or maybe we should have SND_PCM_SUBFORMAT_IEC61937 or SND_PCM_SUBFORMAT_NONPCM?
What should be done?
What this means is that if just the needed HBR bits are set in the audio driver, one can play back e.g. TrueHD by passing the IEC-61937 stream to ALSA as 192kHz 8-channel 16-bit PCM data; of course normal 8-channel PCM playback wouldn't work anymore then. So the driver would need to know if this is 8- channel PCM or 8-channel compressed audio.
Which brings us to my question: How should the user be able to do this, i.e. inform the driver whether this is 8-channel PCM data or compressed audio data?
One easy option would be to have a separate IEC61937_HBR format in ALSA which could be used for IEC-61937 streams represented as 8x 16-bit channels.
If that would be considered too specific, we could add a more generic IEC61937 format, which is the same as above except that "normal" ( = "2 channel") IEC-61937 streams could be used as well. However, as normal IEC-61937 streams can be used with S/PDIF as well, we'd AFAICS need to add such format bit to all S/PDIF drivers or have a no-op converter to the more widely supported 16- bit PCM format.
Could we require that the user sets the channel status bits (with the AESx controls) in case this is compressed. The driver would then make an informed decision to use HBR packets instead of regular PCM 8-ch layout2? At any rate, supporting such formats entails changes to higher levels of the audio stack, for example gstreamer/alsasink would need additional caps. Changes are not limited to the alsa driver I guess.
pl bossart kirjoitti maanantai, 2. elokuuta 2010 06:18:35:
What this means is that if just the needed HBR bits are set in the audio driver, one can play back e.g. TrueHD by passing the IEC-61937 stream to ALSA as 192kHz 8-channel 16-bit PCM data; of course normal 8-channel PCM playback wouldn't work anymore then. So the driver would need to know if this is 8- channel PCM or 8-channel compressed audio.
Which brings us to my question: How should the user be able to do this, i.e. inform the driver whether this is 8-channel PCM data or compressed audio data?
One easy option would be to have a separate IEC61937_HBR format in ALSA which could be used for IEC-61937 streams represented as 8x 16-bit channels.
If that would be considered too specific, we could add a more generic IEC61937 format, which is the same as above except that "normal" ( = "2 channel") IEC-61937 streams could be used as well. However, as normal IEC-61937 streams can be used with S/PDIF as well, we'd AFAICS need to add such format bit to all S/PDIF drivers or have a no-op converter to the more widely supported 16- bit PCM format.
Could we require that the user sets the channel status bits (with the AESx controls) in case this is compressed. The driver would then make an informed decision to use HBR packets instead of regular PCM 8-ch layout2?
Indeed, the non-audio flag (AES0 & 0x02) could be used for this.
It seems the only always-available way to set those is as parameters in the device string, correct?
Will it always be reset after the user closes the device?
At any rate, supporting such formats entails changes to higher levels of the audio stack, for example gstreamer/alsasink would need additional caps. Changes are not limited to the alsa driver I guess.
Yes. We are in the process of adding support in ffmpeg for the TrueHD-in-IEC61937 muxing and after that I'll add support into XBMC for using that functionality.
Looked at gstreamer, it seems to only have ac3-in-iec61937 support currently. However, I'd guess gstreamer would additionally need some ways to 1) detect if HBR is supported, and 2) detect if the connected receiver supports the specific codec..
At Mon, 2 Aug 2010 10:40:17 +0300, Anssi Hannula wrote:
pl bossart kirjoitti maanantai, 2. elokuuta 2010 06:18:35:
What this means is that if just the needed HBR bits are set in the audio driver, one can play back e.g. TrueHD by passing the IEC-61937 stream to ALSA as 192kHz 8-channel 16-bit PCM data; of course normal 8-channel PCM playback wouldn't work anymore then. So the driver would need to know if this is 8- channel PCM or 8-channel compressed audio.
Which brings us to my question: How should the user be able to do this, i.e. inform the driver whether this is 8-channel PCM data or compressed audio data?
One easy option would be to have a separate IEC61937_HBR format in ALSA which could be used for IEC-61937 streams represented as 8x 16-bit channels.
If that would be considered too specific, we could add a more generic IEC61937 format, which is the same as above except that "normal" ( = "2 channel") IEC-61937 streams could be used as well. However, as normal IEC-61937 streams can be used with S/PDIF as well, we'd AFAICS need to add such format bit to all S/PDIF drivers or have a no-op converter to the more widely supported 16- bit PCM format.
Could we require that the user sets the channel status bits (with the AESx controls) in case this is compressed. The driver would then make an informed decision to use HBR packets instead of regular PCM 8-ch layout2?
Indeed, the non-audio flag (AES0 & 0x02) could be used for this.
It seems the only always-available way to set those is as parameters in the device string, correct?
Right.
Will it always be reset after the user closes the device?
This is usually handled in alsa-lib. But not in 100% guaranteed.
Some drivers have both "default" and "PCM" status bits -- the latter is per PCM stream and re-initialized at each open/close. But, many drivers including HD-audio have only the former for simplicity.
At any rate, supporting such formats entails changes to higher levels of the audio stack, for example gstreamer/alsasink would need additional caps. Changes are not limited to the alsa driver I guess.
Yes. We are in the process of adding support in ffmpeg for the TrueHD-in-IEC61937 muxing and after that I'll add support into XBMC for using that functionality.
Looked at gstreamer, it seems to only have ac3-in-iec61937 support currently. However, I'd guess gstreamer would additionally need some ways to 1) detect if HBR is supported, and 2) detect if the connected receiver supports the specific codec..
Reusing the existing IEC958 status bits is OK for practical POV, indeed. This makes also compatible with the existing user-space stuff.
But I feel a bit uncertain when looking forward for future development. More discussions needed.
thanks,
Takashi
Takashi Iwai kirjoitti maanantai, 2. elokuuta 2010 19:20:35:
At Mon, 2 Aug 2010 10:40:17 +0300,
Anssi Hannula wrote:
pl bossart kirjoitti maanantai, 2. elokuuta 2010 06:18:35:
What this means is that if just the needed HBR bits are set in the audio driver, one can play back e.g. TrueHD by passing the IEC-61937 stream to ALSA as 192kHz 8-channel 16-bit PCM data; of course normal 8-channel PCM playback wouldn't work anymore then. So the driver would need to know if this is 8- channel PCM or 8-channel compressed audio.
Which brings us to my question: How should the user be able to do this, i.e. inform the driver whether this is 8-channel PCM data or compressed audio data?
One easy option would be to have a separate IEC61937_HBR format in ALSA which could be used for IEC-61937 streams represented as 8x 16-bit channels.
If that would be considered too specific, we could add a more generic IEC61937 format, which is the same as above except that "normal" ( = "2 channel") IEC-61937 streams could be used as well. However, as normal IEC-61937 streams can be used with S/PDIF as well, we'd AFAICS need to add such format bit to all S/PDIF drivers or have a no-op converter to the more widely supported 16- bit PCM format.
Could we require that the user sets the channel status bits (with the AESx controls) in case this is compressed. The driver would then make an informed decision to use HBR packets instead of regular PCM 8-ch layout2?
Indeed, the non-audio flag (AES0 & 0x02) could be used for this.
[...]
Reusing the existing IEC958 status bits is OK for practical POV, indeed. This makes also compatible with the existing user-space stuff.
Ok.
Now, on my system I have used device name 'hw:2,9' for the passthrough. How can I pass AES0 to that?
'hw:2,9,AES0=0x06' doesn't work ("Unknown parameter AES0").
Using 'hdmi:AES0=0x06' results in an error as it tries to use a hdmi interface on an usb-audio card ("Unable to find definition 'cards.USB- Audio.pcm.hdmi.0:CARD=0,AES0=6,AES1=130,AES2=0,AES3=2'").
Using 'hdmi:CARD=NVidia,AES0=0x06' results in the wrong device being used (presumably card 2 device 3).
I also tried 'hdmi:CARD=NVidia,DEV=X,AES0=0x06' but no other values for X than 0 seem to work ("Unable to find definition 'cards.HDA- Intel.pcm.hdmi.X:CARD=NVidia,AES0=6,AES1=130,AES2=0,AES3=2'").
(Interestingly, outputting audio (e.g. speaker-test) to any of the hw:2,[378] works, but only after I've outputted something to hw:2,9 first. Similarly, if I try 8-channel audio on hw:2,[378] when last stream on hw:2,9 was a 2-channel one, only 2 channels will get through. I guess the audio lines for the 4 hdmi codecs are somehow shared or something.)
Here's the device list: $ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: External [SB Live! 24-bit External], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: Intel [HDA Intel], device 0: CONEXANT Analog [CONEXANT Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: NVidia [HDA NVidia], device 3: NVIDIA HDMI [NVIDIA HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: NVidia [HDA NVidia], device 7: NVIDIA HDMI [NVIDIA HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: NVidia [HDA NVidia], device 8: NVIDIA HDMI [NVIDIA HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: NVidia [HDA NVidia], device 9: NVIDIA HDMI [NVIDIA HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0
Looked at gstreamer, it seems to only have ac3-in-iec61937 support currently. However, I'd guess gstreamer would additionally need some ways to 1) detect if HBR is supported, and 2) detect if the connected receiver supports the specific codec..
Reusing the existing IEC958 status bits is OK for practical POV, indeed. This makes also compatible with the existing user-space stuff.
But I feel a bit uncertain when looking forward for future development. More discussions needed.
The automatic detection is not possible for now no matter if you rely on gstreamer or ffmpeg or something else. The one thing that is missing for HDMI is to make use of EDID information to report to userspace the capabilities of the receiver so that apps or the audio policy make educated decisions on whether to decode locally or use pass-through modes using iec61937. The HDMI spec only mandates stereo/48kHz, and if you have an older receiver (2 years old...) you may not have TruHD supported there. To the best of my knowledge, there aren't any standard controls to report what the receiver supports. I had some discussions with Takashi on this in the past, looks like it's time to make this happen?
At Mon, 2 Aug 2010 14:33:38 -0500, pl bossart wrote:
Looked at gstreamer, it seems to only have ac3-in-iec61937 support currently. However, I'd guess gstreamer would additionally need some ways to 1) detect if HBR is supported, and 2) detect if the connected receiver supports the specific codec..
Reusing the existing IEC958 status bits is OK for practical POV, indeed. This makes also compatible with the existing user-space stuff.
But I feel a bit uncertain when looking forward for future development. More discussions needed.
The automatic detection is not possible for now no matter if you rely on gstreamer or ffmpeg or something else. The one thing that is missing for HDMI is to make use of EDID information to report to userspace the capabilities of the receiver so that apps or the audio policy make educated decisions on whether to decode locally or use pass-through modes using iec61937. The HDMI spec only mandates stereo/48kHz, and if you have an older receiver (2 years old...) you may not have TruHD supported there. To the best of my knowledge, there aren't any standard controls to report what the receiver supports. I had some discussions with Takashi on this in the past, looks like it's time to make this happen?
Yeah, good chance to really implement something. We certainly need some solid channel for the extra information like EDID.
Takashi
participants (3)
-
Anssi Hannula
-
pl bossart
-
Takashi Iwai