[alsa-devel] [RFC] Channel mapping API
Hi,
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
* KERNEL IMPLEMENTATION
In my latest attempt, I implemented with control elements. A control element is created for each PCM substream with the corresponding device and substream index. Then it gives a TLV for querying maps, a read op for obtaining the current map, and optionally a write op for setting the map. The obvious merit by this way is that no extra kernel ABI is required.
A couple of new helper functions are provided for assigning standard channel maps. Currently, HD-audio and AC97 drivers has some implementation.
* ALSA-LIB IMPLEMENTATION
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
When a driver allows user to change the channel map, user can call snd_pcm_set_chmap(). For example, HDMI allows you to choose whether it's 4.0 or 3.1 output.
* RESOURCES
The latest kernel patchset is found in sound-unstable tree topic/tlv-chmap branch. git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-unstable.git topic/tlv-chmap
The alsa-lib portion is found in a tree on github topic/chmap branch. git://github.com/tiwai/alsa-lib.git topic/chmap
thanks,
Takashi
On 08/21/2012 12:31 PM, Takashi Iwai wrote:
Hi,
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
- KERNEL IMPLEMENTATION
In my latest attempt, I implemented with control elements. A control element is created for each PCM substream with the corresponding device and substream index. Then it gives a TLV for querying maps, a read op for obtaining the current map, and optionally a write op for setting the map. The obvious merit by this way is that no extra kernel ABI is required.
A couple of new helper functions are provided for assigning standard channel maps. Currently, HD-audio and AC97 drivers has some implementation.
- ALSA-LIB IMPLEMENTATION
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
When a driver allows user to change the channel map, user can call snd_pcm_set_chmap(). For example, HDMI allows you to choose whether it's 4.0 or 3.1 output.
Interesting. A few thoughts here:
1) You seem to have invented new constants for different channels (SND_CHMAP_FL for "front left" etc). There is already a channel enumeration in include/mixer.h, _snd_mixer_selem_channel_id. Is there a reason we can't just reuse it for this purpose? If we can't, we should at least make sure that everywhere we have these declarations, they always correspond to the same value and add comments that they need to be kept in sync.
2) a chmap struct would probably be more elegant, something like:
struct snd_chmap { int type; /* or snd_pcm_chmap_type? */ int count; int channels[SND_MIXER_SCHN_LAST+1]; /* Or variable length? */ }
3) Can you use snd_pcm_set_chmap before snd_pcm_prepare, and if so, it seems a bit strange that snd_pcm_get_chmap does not return what you have previously set.
4) The question of memory allocation for _get and _query, who is supposed to allocate and free the snd_chmap array?
5) I'm not sure I'm getting the _VAR and _PAIRED types, even though I read the documentation. Is this for the query only? Or if not, what would it mean to get/set a channelmap with _VAR type?
- RESOURCES
The latest kernel patchset is found in sound-unstable tree topic/tlv-chmap branch. git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-unstable.git topic/tlv-chmap
The alsa-lib portion is found in a tree on github topic/chmap branch. git://github.com/tiwai/alsa-lib.git topic/chmap
thanks,
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
David Henningsson wrote:
- I'm not sure I'm getting the _VAR and _PAIRED types, even though
I read the documentation. Is this for the query only?
AFAIU this types appear only in the TLV, which is read only. The TLV documents what channel configurations are possible, while the current configuration is read/changed through the control value, which is a plain array of integers, one for each channel, without headers.
So _VAR implies that the control's value can be set to any permutation of the channels in the TLV.
Regards, Clemens
At Tue, 21 Aug 2012 13:24:53 +0200, David Henningsson wrote:
On 08/21/2012 12:31 PM, Takashi Iwai wrote:
Hi,
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
- KERNEL IMPLEMENTATION
In my latest attempt, I implemented with control elements. A control element is created for each PCM substream with the corresponding device and substream index. Then it gives a TLV for querying maps, a read op for obtaining the current map, and optionally a write op for setting the map. The obvious merit by this way is that no extra kernel ABI is required.
A couple of new helper functions are provided for assigning standard channel maps. Currently, HD-audio and AC97 drivers has some implementation.
- ALSA-LIB IMPLEMENTATION
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
When a driver allows user to change the channel map, user can call snd_pcm_set_chmap(). For example, HDMI allows you to choose whether it's 4.0 or 3.1 output.
Interesting. A few thoughts here:
- You seem to have invented new constants for different channels
(SND_CHMAP_FL for "front left" etc). There is already a channel enumeration in include/mixer.h, _snd_mixer_selem_channel_id. Is there a reason we can't just reuse it for this purpose?
No big reason, but a minor reason would be that UNKNOWN = -1 is a bit impractical and the mixer id definition lacks some new positions. And, this is for mixer, and another for PCM, so using SND_MIXER_* doesn't sound right.
But adjusting to follow the same values won't be a big issue. Let's see.
If we can't, we should at least make sure that everywhere we have these declarations, they always correspond to the same value and add comments that they need to be kept in sync.
- a chmap struct would probably be more elegant, something like:
struct snd_chmap { int type; /* or snd_pcm_chmap_type? */ int count; int channels[SND_MIXER_SCHN_LAST+1]; /* Or variable length? */ }
It should be a variable length. It could be with zero-size array, though: struct snd_chmap { int type; int count; int channels[0]; };
Though, the type would be used only for queries (see below), so it should be named like struct snd_chmap_query.
- Can you use snd_pcm_set_chmap before snd_pcm_prepare, and if so, it
seems a bit strange that snd_pcm_get_chmap does not return what you have previously set.
Setting or getting the channel map doesn't work before prepare (or more specifically hw_params) because the number of channels isn't determined yet. It's the only reason.
- The question of memory allocation for _get and _query, who is
supposed to allocate and free the snd_chmap array?
The caller. The helper function snd_pcm_free_chmaps() is provided, too.
- I'm not sure I'm getting the _VAR and _PAIRED types, even though I
read the documentation. Is this for the query only? Or if not, what would it mean to get/set a channelmap with _VAR type?
Oh sorry, I must correct the description: get_chmap() returns only the number of channels followed by channel elements. Ditto for set_chmap(). The type is used only for query.
thanks,
Takashi
At Tue, 21 Aug 2012 14:06:09 +0200, Takashi Iwai wrote:
At Tue, 21 Aug 2012 13:24:53 +0200, David Henningsson wrote:
On 08/21/2012 12:31 PM, Takashi Iwai wrote:
Hi,
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
- KERNEL IMPLEMENTATION
In my latest attempt, I implemented with control elements. A control element is created for each PCM substream with the corresponding device and substream index. Then it gives a TLV for querying maps, a read op for obtaining the current map, and optionally a write op for setting the map. The obvious merit by this way is that no extra kernel ABI is required.
A couple of new helper functions are provided for assigning standard channel maps. Currently, HD-audio and AC97 drivers has some implementation.
- ALSA-LIB IMPLEMENTATION
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
When a driver allows user to change the channel map, user can call snd_pcm_set_chmap(). For example, HDMI allows you to choose whether it's 4.0 or 3.1 output.
Interesting. A few thoughts here:
- You seem to have invented new constants for different channels
(SND_CHMAP_FL for "front left" etc). There is already a channel enumeration in include/mixer.h, _snd_mixer_selem_channel_id. Is there a reason we can't just reuse it for this purpose?
No big reason, but a minor reason would be that UNKNOWN = -1 is a bit impractical and the mixer id definition lacks some new positions. And, this is for mixer, and another for PCM, so using SND_MIXER_* doesn't sound right.
But adjusting to follow the same values won't be a big issue. Let's see.
I updated git trees to follow this now.
Takashi
Takashi Iwai wrote:
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
I won't be there, so ...
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
This doesn't handle devices with simply numbered outputs (such as many ICE1712-based devices), or cases where one PCM channel can be routed to multiple outputs. However, those devices typically have their own mixer applets, and generic applications aren't interested in configuring them.
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
So channel maps are reset when a device is reopened?
- WRITE OPERATION
This operation is allowed only at PCM PREPARED state. When called in other states, it shall return an error.
This sounds like an hda-intel HDMI restriction; other chips allow rerouting at any time. (And the route plugin could allow that, too.)
Regards, Clemens
At Tue, 21 Aug 2012 13:37:58 +0200, Clemens Ladisch wrote:
Takashi Iwai wrote:
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
I won't be there, so ...
It's a pity.
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
This doesn't handle devices with simply numbered outputs (such as many ICE1712-based devices), or cases where one PCM channel can be routed to multiple outputs. However, those devices typically have their own mixer applets, and generic applications aren't interested in configuring them.
For such devices, this is a bit hard, indeed. In theory, query should return all possible channel maps the PCM stream covers. This can be calculated somehow statically.
For getting the channel map, the driver could send a notification once when routing is changed.
snd_pcm_get_chmap() returns the currently assigned channel map for the given PCM stream. If the PCM is before prepared, it fills UNKNOWN.
So channel maps are reset when a device is reopened?
The behavior isn't defined, so far, and I don't think it has to be reset.
- WRITE OPERATION
This operation is allowed only at PCM PREPARED state. When called in other states, it shall return an error.
This sounds like an hda-intel HDMI restriction; other chips allow rerouting at any time. (And the route plugin could allow that, too.)
The only reason get/set doesn't work before hw_params is that the number of channels isn't set. In other words, before hw_params, the hardware state is still undetermined. Thus the channel map should be undetermined either.
Strictly speaking, the function can check whether hw_params channels parameter is already set to single. But, from the practical POV, it becomes easier by checking PREPARED state in the end.
thanks,
Takashi
Date 21.8.2012 14:15, Takashi Iwai wrote:
For getting the channel map, the driver could send a notification once when routing is changed.
This leads to this question: Why you define the map controls volatile? I think that the channel map changes can be tracked nicely using the standard control event notifications without any hidden changes. Perhaps, the value change event may be invoked each time after prepare and when the user space set the new values and also in above situation, when the channel map is changed on an external request.
Jaroslav
At Tue, 21 Aug 2012 14:31:55 +0200, Jaroslav Kysela wrote:
Date 21.8.2012 14:15, Takashi Iwai wrote:
For getting the channel map, the driver could send a notification once when routing is changed.
This leads to this question: Why you define the map controls volatile? I think that the channel map changes can be tracked nicely using the standard control event notifications without any hidden changes. Perhaps, the value change event may be invoked each time after prepare and when the user space set the new values and also in above situation, when the channel map is changed on an external request.
What I had in my mind for the volatile flag was how to avoid the effect by "alsactl restore". But since the set op was changed only for the prepared state, the volatile flag can be removed, I think.
Takashi
At Tue, 21 Aug 2012 14:35:57 +0200, Takashi Iwai wrote:
At Tue, 21 Aug 2012 14:31:55 +0200, Jaroslav Kysela wrote:
Date 21.8.2012 14:15, Takashi Iwai wrote:
For getting the channel map, the driver could send a notification once when routing is changed.
This leads to this question: Why you define the map controls volatile? I think that the channel map changes can be tracked nicely using the standard control event notifications without any hidden changes. Perhaps, the value change event may be invoked each time after prepare and when the user space set the new values and also in above situation, when the channel map is changed on an external request.
What I had in my mind for the volatile flag was how to avoid the effect by "alsactl restore". But since the set op was changed only for the prepared state, the volatile flag can be removed, I think.
The VOLATILE flag is removed in the git tree now.
Takashi
On 08/21/2012 01:37 PM, Clemens Ladisch wrote:
Takashi Iwai wrote:
this is a progress report of my longstanding TODO, the channel map API implementation. I'm going to cover this at Plumbers audio uconf, so we can discuss details there, too.
I won't be there, so ...
The channel mapping API provides a method for user-space to query, get and set the channel map of a PCM stream. It's required for assigning channels properly for multi-channel streams.
This doesn't handle devices with simply numbered outputs (such as many ICE1712-based devices), or cases where one PCM channel can be routed to multiple outputs. However, those devices typically have their own mixer applets, and generic applications aren't interested in configuring them.
Good point! It would be nice if we had better support for devices that simply number their outputs, including standard mixer names for those devices, that would be good.
One of the long-standing bugs in PulseAudio is better support for such hardware, so if we had better possibilities to detect and use these outputs and inputs, it could be worth the effort.
As for routing more than one channel in the map from the same PCM, that seems a bit more complex. Maybe one could do a bitmap of channels instead of just one channel (with say, 32 room channel positions and 32 just numbered positions, that would be 64 bits). But how common is that anyway?
Would it make sense to present a bitmap as the query result anyway? Then we could skip the _VAR and _PAIRED types, right?
On Tue, Aug 21, 2012 at 04:00:37PM +0200, David Henningsson wrote:
On 08/21/2012 01:37 PM, Clemens Ladisch wrote:
This doesn't handle devices with simply numbered outputs (such as many ICE1712-based devices), or cases where one PCM channel can be routed to multiple outputs. However, those devices typically have their own mixer applets, and generic applications aren't interested in configuring them.
As for routing more than one channel in the map from the same PCM, that seems a bit more complex. Maybe one could do a bitmap of channels instead of just one channel (with say, 32 room channel positions and 32 just numbered positions, that would be 64 bits). But how common is that anyway?
It's very common on the embedded side to use pure numbered stuff (or at least to assign semantics dynamically at runtime which I suspect boils down to the same thing here).
On 08/21/2012 04:06 PM, Mark Brown wrote:
On Tue, Aug 21, 2012 at 04:00:37PM +0200, David Henningsson wrote:
On 08/21/2012 01:37 PM, Clemens Ladisch wrote:
This doesn't handle devices with simply numbered outputs (such as many ICE1712-based devices), or cases where one PCM channel can be routed to multiple outputs. However, those devices typically have their own mixer applets, and generic applications aren't interested in configuring them.
As for routing more than one channel in the map from the same PCM, that seems a bit more complex. Maybe one could do a bitmap of channels instead of just one channel (with say, 32 room channel positions and 32 just numbered positions, that would be 64 bits). But how common is that anyway?
It's very common on the embedded side to use pure numbered stuff (or at least to assign semantics dynamically at runtime which I suspect boils down to the same thing here).
It reminds me of the discussion we had about jack labelling (for HDA or everyone? I do not remember), where we ended up having
1) physical location (left side, internal, docking station) 2) type (headphone, speaker) 3) channel map (front, rear, c/lfe)
Maybe that's where this discussion is heading as well? I like the idea of having the same TLV description for jacks, mixer controls and PCM channels, maybe that could work for all but the most exotic cases?
(Where exotic means unusual hw on both the pro-audio and the embedded side)
On Tue, Aug 21, 2012 at 04:13:53PM +0200, David Henningsson wrote:
It reminds me of the discussion we had about jack labelling (for HDA or everyone? I do not remember), where we ended up having
- physical location (left side, internal, docking station)
- type (headphone, speaker)
- channel map (front, rear, c/lfe)
Maybe that's where this discussion is heading as well? I like the idea of having the same TLV description for jacks, mixer controls and PCM channels, maybe that could work for all but the most exotic cases?
(Where exotic means unusual hw on both the pro-audio and the embedded side)
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
At Tue, 21 Aug 2012 15:18:00 +0100, Mark Brown wrote:
[1 <text/plain; us-ascii (7bit)>] On Tue, Aug 21, 2012 at 04:13:53PM +0200, David Henningsson wrote:
It reminds me of the discussion we had about jack labelling (for HDA or everyone? I do not remember), where we ended up having
- physical location (left side, internal, docking station)
- type (headphone, speaker)
- channel map (front, rear, c/lfe)
Maybe that's where this discussion is heading as well? I like the idea of having the same TLV description for jacks, mixer controls and PCM channels, maybe that could work for all but the most exotic cases?
(Where exotic means unusual hw on both the pro-audio and the embedded side)
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
It's an interesting idea. But, in the case of HDMI, there are no multiple jacks, so this won't fit.
What I had in my mind originally is to provide the definition of values in TLV, and get/set points the value index.
For example,
val1 = front left val2 = front right ...
then chmap would contain a list like {1,2}.
And the value can be a complex of location + type, such as
val1 = front left at speaker val2 = front left at headphone val3 = front right at speaker val4 = front right at headphone
then chmap can be {1,3} or {1,2}.
So, we can provide one new TLV block of the channel value definitions:
TLV_CHMAP_VALUES chval, position, type(hp/spk), chval, position, type, ...
followed by the list of available maps. But I didn't take it as I thought it might be too complex. If needed, this can be taken as an optional TLV block.
However, this doesn't help much for multiple output cases like ice1712. So far, I ignored that case intentionally. The primary goal of this API is to provide a way for apps to decide the channel map for multi-channel streams. If multiple positions are given, what they should do? It'd be just confusing.
Of course, there might be more use cases. But I'm afraid that supporting the multiple outputs per channel would end up with too deep references and hard to manage.
At least, some fixed multiple outputs could be covered by the free definition of the chmap value like above (e.g. by allowing multiple assignments per channel in the definition block). But whether to cover all flexible multiple outputs per channel, I hesitate to go forward...
Takashi
Takashi Iwai wrote:
Mark Brown wrote:
On Tue, Aug 21, 2012 at 04:13:53PM +0200, David Henningsson wrote:
It reminds me of the discussion we had about jack labelling (for HDA or everyone? I do not remember), where we ended up having
- physical location (left side, internal, docking station)
- type (headphone, speaker)
- channel map (front, rear, c/lfe)
Maybe that's where this discussion is heading as well? I like the idea of having the same TLV description for jacks, mixer controls and PCM channels, maybe that could work for all but the most exotic cases?
(Where exotic means unusual hw on both the pro-audio and the embedded side)
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
It's an interesting idea. But, in the case of HDMI, there are no multiple jacks, so this won't fit. [...] The primary goal of this API is to provide a way for apps to decide the channel map for multi-channel streams.
Indeed; including the jack location/type would go beyond what the channel map is useful for. Playback applications know what kind of multichannel stream they're playing, but they definitely do _not_ want to decice if the output should go to the front or back panel.
The channel mapping is a _stream_ configuration, the other routing choices are device setup.
At the moment, we lack an API to provide topology information. But whatever form it takes, it should probably be independent of the channel mapping. (I'll see if I can find time to do something about my media framework patches until next week.)
Regards, Clemens
On Tue, Aug 21, 2012 at 05:38:34PM +0200, Clemens Ladisch wrote:
Takashi Iwai wrote:
It's an interesting idea. But, in the case of HDMI, there are no multiple jacks, so this won't fit. [...] The primary goal of this API is to provide a way for apps to decide the channel map for multi-channel streams.
Indeed; including the jack location/type would go beyond what the channel map is useful for. Playback applications know what kind of multichannel stream they're playing, but they definitely do _not_ want to decice if the output should go to the front or back panel.
The channel mapping is a _stream_ configuration, the other routing choices are device setup.
Perhaps I'm missing something but why would the availability of additional information be a problem for applications here? The idea was purely to punt the description of the outputs attached to the stream to somewhere we already need to use to describe the outputs rather than having to map the two formats together.
At the moment, we lack an API to provide topology information. But whatever form it takes, it should probably be independent of the channel mapping. (I'll see if I can find time to do something about my media framework patches until next week.)
For media controller? Everyone who's looked at in detail has expressed concern about it being too heavyweight...
At Tue, 21 Aug 2012 17:27:06 +0100, Mark Brown wrote:
On Tue, Aug 21, 2012 at 05:38:34PM +0200, Clemens Ladisch wrote:
Takashi Iwai wrote:
It's an interesting idea. But, in the case of HDMI, there are no multiple jacks, so this won't fit. [...] The primary goal of this API is to provide a way for apps to decide the channel map for multi-channel streams.
Indeed; including the jack location/type would go beyond what the channel map is useful for. Playback applications know what kind of multichannel stream they're playing, but they definitely do _not_ want to decice if the output should go to the front or back panel.
The channel mapping is a _stream_ configuration, the other routing choices are device setup.
Perhaps I'm missing something but why would the availability of additional information be a problem for applications here?
Because apps don't know what to do for such a case. The APIs in other sound subsystems (see PA or gstreamer) don't allow such setups.
The idea was purely to punt the description of the outputs attached to the stream to somewhere we already need to use to describe the outputs rather than having to map the two formats together.
Yeah, passing more info is fine. But if it isn't compatible, it doesn't have to be the same controller elements as channel map. Or, we may put a flag in the query TLV to indicate it's not standard, etc...
At the moment, we lack an API to provide topology information. But whatever form it takes, it should probably be independent of the channel mapping. (I'll see if I can find time to do something about my media framework patches until next week.)
For media controller? Everyone who's looked at in detail has expressed concern about it being too heavyweight...
It's my concern, too, but hey, let's see. Clemens might give some magic :)
Takashi
On Tue, Aug 21, 2012 at 07:05:24PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
The idea was purely to punt the description of the outputs attached to the stream to somewhere we already need to use to describe the outputs rather than having to map the two formats together.
Yeah, passing more info is fine. But if it isn't compatible, it doesn't have to be the same controller elements as channel map. Or, we may put a flag in the query TLV to indicate it's not standard, etc...
So, I guess a lot of my concern here is that this is in line with what we're doing for control names and obviously that information is basic to the point of being unhelpful for any non-trivial hardware. If we're adding something I'd rather it were able to cope with the complicated cases too; multi-channel audio is a big deal with embedded things but usually not for 5.1.
At Tue, 21 Aug 2012 18:11:35 +0100, Mark Brown wrote:
On Tue, Aug 21, 2012 at 07:05:24PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
The idea was purely to punt the description of the outputs attached to the stream to somewhere we already need to use to describe the outputs rather than having to map the two formats together.
Yeah, passing more info is fine. But if it isn't compatible, it doesn't have to be the same controller elements as channel map. Or, we may put a flag in the query TLV to indicate it's not standard, etc...
So, I guess a lot of my concern here is that this is in line with what we're doing for control names and obviously that information is basic to the point of being unhelpful for any non-trivial hardware. If we're adding something I'd rather it were able to cope with the complicated cases too; multi-channel audio is a big deal with embedded things but usually not for 5.1.
I think it won't be able to be implemented in a single piece anyway for such a case, but it'd be a combination of some components. As you pointed, the final mapping can be deduced with some extra routing information. But this won't be needed for normal desktop cases.
So, if anything similar information (e.g. just the mapped number) would be still useful as a piece for the big picture, I'm fine to allow arbitrary values in the definition of API (again, ABI is already there, so it's really just a matter of definition). Something like the bit flag as I suggested would be easily put into.
Just need to know what should be the most appropriate form...
Takashi
On Tue, Aug 21, 2012 at 04:49:56PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
It's an interesting idea. But, in the case of HDMI, there are no multiple jacks, so this won't fit.
Surely the jack should be able to change state, though?
What I had in my mind originally is to provide the definition of values in TLV, and get/set points the value index.
However, this doesn't help much for multiple output cases like ice1712. So far, I ignored that case intentionally. The primary goal of this API is to provide a way for apps to decide the channel map for multi-channel streams. If multiple positions are given, what they should do? It'd be just confusing.
This sort of stuff is why I was suggesting providing a mechanism for saying "fall back to tracing the routing graph" - obviously there's an implementation to do there but it should provide ultimate support for whatever mappings people can dreamm up.
At least, some fixed multiple outputs could be covered by the free definition of the chmap value like above (e.g. by allowing multiple assignments per channel in the definition block). But whether to cover all flexible multiple outputs per channel, I hesitate to go forward...
I agree, I think it'd be too complex to cover every case purely in channel mapping.
On 08/21/2012 04:18 PM, Mark Brown wrote:
On Tue, Aug 21, 2012 at 04:13:53PM +0200, David Henningsson wrote:
It reminds me of the discussion we had about jack labelling (for HDA or everyone? I do not remember), where we ended up having
- physical location (left side, internal, docking station)
- type (headphone, speaker)
- channel map (front, rear, c/lfe)
Maybe that's where this discussion is heading as well? I like the idea of having the same TLV description for jacks, mixer controls and PCM channels, maybe that could work for all but the most exotic cases?
(Where exotic means unusual hw on both the pro-audio and the embedded side)
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
That's an interesting idea. The possible drawback is that it would require all drivers that want to use this to implement jacks also.
In the ctljack interface for HDA, we already describe all inputs and outputs - with the nonchangable ones having the additional "Phantom" suffix, so the result becomes e g "Internal Mic Phantom Jack".
On Tue, Aug 21, 2012 at 04:52:29PM +0200, David Henningsson wrote:
On 08/21/2012 04:18 PM, Mark Brown wrote:
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
That's an interesting idea. The possible drawback is that it would require all drivers that want to use this to implement jacks also.
I'm not sure that's a big deal, we should be able to make the fixed data case easy enough to do.
In the ctljack interface for HDA, we already describe all inputs and outputs - with the nonchangable ones having the additional "Phantom" suffix, so the result becomes e g "Internal Mic Phantom Jack".
Which of course is also replicated with the calls into the original jack API.
On 08/21/2012 05:07 PM, Mark Brown wrote:
On Tue, Aug 21, 2012 at 04:52:29PM +0200, David Henningsson wrote:
On 08/21/2012 04:18 PM, Mark Brown wrote:
Or perhaps what we want to do here is define the channel mapping in terms of saying "I'm connecting to this input/output" and then use the jack interface to describe all inputs and outputs rather than just jacks (making sure it's easy to see which ones can change state)?
That's an interesting idea. The possible drawback is that it would require all drivers that want to use this to implement jacks also.
I'm not sure that's a big deal, we should be able to make the fixed data case easy enough to do.
In the ctljack interface for HDA, we already describe all inputs and outputs - with the nonchangable ones having the additional "Phantom" suffix, so the result becomes e g "Internal Mic Phantom Jack".
Which of course is also replicated with the calls into the original jack API.
Actually, the phantom jacks are only in the ctljack API. I deliberately left them out of the old jack API, because it was deprecated (or at least so I thought).
On Tue, Aug 21, 2012 at 05:38:28PM +0200, David Henningsson wrote:
On 08/21/2012 05:07 PM, Mark Brown wrote:
Which of course is also replicated with the calls into the original jack API.
Actually, the phantom jacks are only in the ctljack API. I deliberately left them out of the old jack API, because it was deprecated (or at least so I thought).
Like I say it seems like the wrong way round to do things - we've got a reasonable set of drivers using the jack API and a single driver using the ctljack API, with the ctljack API being very much a subset of the jack API (in that it only supports disconnected boolean values). I still don't understand why it was ever implemented as a separate API.
At Tue, 21 Aug 2012 17:34:15 +0100, Mark Brown wrote:
On Tue, Aug 21, 2012 at 05:38:28PM +0200, David Henningsson wrote:
On 08/21/2012 05:07 PM, Mark Brown wrote:
Which of course is also replicated with the calls into the original jack API.
Actually, the phantom jacks are only in the ctljack API. I deliberately left them out of the old jack API, because it was deprecated (or at least so I thought).
Like I say it seems like the wrong way round to do things - we've got a reasonable set of drivers using the jack API and a single driver using the ctljack API, with the ctljack API being very much a subset of the jack API (in that it only supports disconnected boolean values). I still don't understand why it was ever implemented as a separate API.
The API itself doesn't restrict the boolean -- it's a control element after all.
The reason for ctljack API was stated many times: it came because of shortcomings of the jack API regarding the multiple items. For example, when multiple pins with the same type exist (e.g. typical for HD-audio), no standard way to resolve that. Or, if multiple cards provide the same name of jacks, we don't know which device is for which card.
But, it's basically irrelevant with the channel map API discussion.
Takashi
On Tue, Aug 21, 2012 at 07:09:32PM +0200, Takashi Iwai wrote:
The API itself doesn't restrict the boolean -- it's a control element after all.
The in kernel API takes a boolean as an argument for reporting values.
The reason for ctljack API was stated many times: it came because of shortcomings of the jack API regarding the multiple items. For example, when multiple pins with the same type exist (e.g. typical for HD-audio), no standard way to resolve that. Or, if multiple cards provide the same name of jacks, we don't know which device is for which card.
Both of these things are totally orthogonal to the problem here - it's the separate in kernel API that's causing issues (and TBH neither issue is a big one for the ABI, if we'd discussed them we'd be fine) since drivers need to support them all. If all the ABIs sat behind a single API in the kernel we'd not have any confusion here, userspace could just pick what amuses it.
But, it's basically irrelevant with the channel map API discussion.
Yeah, some drift here.
On Tue, Aug 21, 2012 at 12:31:57PM +0200, Takashi Iwai wrote:
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
Currently only named channel maps are supported. It'd be nice to also support just plain numbered channels, or at least provide a way to say to userspace that it needs to do something like chase through a routing map to figure out where each channel goes (as opposed to assuming that the driver doesn't know what to report).
It'd also be nice to be able to express the situation we sometimes get in embedded devices where we (for example) play to channels 0 and 1 to get headphones and to 2 and 3 for speaker but that usually falls into the route tracing case anyway so I'm not sure it's worth worrying about.
At Tue, 21 Aug 2012 14:59:47 +0100, Mark Brown wrote:
On Tue, Aug 21, 2012 at 12:31:57PM +0200, Takashi Iwai wrote:
snd_pcm_query_chmaps() returns the list of channel maps. A channel map is represented by an integer array, beginning with the channel map type, followed by the number of channels, and the position of each channel, e.g. { SND_CHMAP_FIXED, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR }
Currently only named channel maps are supported. It'd be nice to also support just plain numbered channels, or at least provide a way to say to userspace that it needs to do something like chase through a routing map to figure out where each channel goes (as opposed to assuming that the driver doesn't know what to report).
The channel map value are basically arbitrary 32bit integer, so we can define something like: #define SND_CHMAP_NUMBERED 0x10000 and pass the channel number with this bit flag. Then it becomes a matter of definition of chmap values.
(But, hm, then setting UNKNOWN = -1 is a bad idea... Maybe I should revert the last change and set UNKNOWN = 0 again.)
It'd also be nice to be able to express the situation we sometimes get in embedded devices where we (for example) play to channels 0 and 1 to get headphones and to 2 and 3 for speaker but that usually falls into the route tracing case anyway so I'm not sure it's worth worrying about.
Ditto, the value can be set with some bit flags.
Maybe the predefined channel enum should be limited to 8 or 16 bits, and give the rest for flags.
Takashi
On Tue, Aug 21, 2012 at 04:08:40PM +0200, Takashi Iwai wrote:
Mark Brown wrote:
Currently only named channel maps are supported. It'd be nice to also support just plain numbered channels, or at least provide a way to say to userspace that it needs to do something like chase through a routing map to figure out where each channel goes (as opposed to assuming that the driver doesn't know what to report).
The channel map value are basically arbitrary 32bit integer, so we can define something like: #define SND_CHMAP_NUMBERED 0x10000 and pass the channel number with this bit flag. Then it becomes a matter of definition of chmap values.
Yes, I think something like this where we've got the map values split into a type and a value would address things simply.
On 8/21/2012 5:31 AM, Takashi Iwai wrote:
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
Hi Takashi, Maybe my question is slightly off-topic but can this be used by applications relying on tinyALSA or tinyCompress? Looks like we will need to replicate the same ideas based on TLV? Thanks, -Pierre
At Tue, 21 Aug 2012 13:03:57 -0500, Pierre-Louis Bossart wrote:
On 8/21/2012 5:31 AM, Takashi Iwai wrote:
The additional alsa-lib API functions look like:
int **snd_pcm_query_chmaps(snd_pcm_t *pcm); int *snd_pcm_get_chmap(snd_pcm_t *pcm); int snd_pcm_set_chmap(snd_pcm_t *pcm, const int *map);
Hi Takashi, Maybe my question is slightly off-topic but can this be used by applications relying on tinyALSA or tinyCompress? Looks like we will need to replicate the same ideas based on TLV?
Yes, the TLV parser code and conversion from the control element values to int array would be required. Other than that, the kernel ABI itself is just a re-use of the exiting infrastructure.
Takashi
participants (6)
-
Clemens Ladisch
-
David Henningsson
-
Jaroslav Kysela
-
Mark Brown
-
Pierre-Louis Bossart
-
Takashi Iwai