On Wed, 2010-06-09 at 14:56 -0500, pl bossart wrote: > It's been more than a year that this topic shows as 'being on the > roadmap', but for now the reality is that people bypass PulseAudio to > hear multichannel sound. I thought solving this would be a nice summer > skunkworks project while everyone is busy increasing their chances of > skin cancer. Sounds good. I too would prefer hassle-free AC3 playback over skin cancer! > Here's the deal: formatting an AC3 file into the required IEC format > takes about 30 lines of code, this can be done in the application that > connects to PulseAudio. Do you plan to do it (the formatting) inside or outside libpulse? > Then the problem is to pass raw data > internally without applying any volume controls and with mixing > disabled. There's no issue with timing or variable bitrate since the > formatting adds headers and zero-padding to reach the non-compressed > PCM bitrate, i.e. all the bytes-to-ms conversions still apply. > I started looking into this but the volume control code is spread out > between sink-input, sink, alsa, and it's hard to figure out how to go > about this. Likewise, preventing mixing isn't self-explanatory. If > anyone has pointers on these points or is willing to contribute, let > me know. Here's some thoughts of how I'd approach the task: Sink inputs would get a new flag: PA_SINK_INPUT_NONPCM. The flag would mean that no automatic conversion may be done before passing the stream data to the sink, and also that the sink must know what it's doing (= understand the non-PCM semantics) if it wants to modify the stream data in any way. For example, module-combine doesn't understand any other data types than PCM, so module-combine couldn't accept AC3 streams. If there was "module-combine-ac3" that would decode the stream, or use magic to resample the raw AC3 data, then that would be fine. Sinks would get a new function: pa_sink_accept_input(pa_sink *s, pa_sink_input *si). The function would check whether the sink input is suitable for that sink. It would be called inside pa_sink_input_may_move_to() and inside pa_sink_input_put(), or if making _put() a failable function is not acceptable, then whenever anyone wants to call _put(), he must first call _accept_input(). Sink implementers could provide a callback that would be called inside pa_sink_accept_input(). By default inputs with the _NONPCM flag would be rejected, but the ALSA sink and module-combine-ac3 would accept also _NONPCM inputs if the sample format happened to be PA_SAMPLE_AC3 (for ALSA sinks, of course only if the sink's sample format would also be PA_SAMPLE_AC3). So, I'd introduce a new sample format: PA_SAMPLE_AC3. Preventing mixing would be achieved by the fact that either sinks only accept one AC3 stream at a time, or they don't use pa_sink_render(), but do the mixing themselves if they somehow can handle that. I think pa_sink_render() should be safe for the ALSA sink to use as long as there's only one input and the sample rates match[1]. (I assume AC3 streams always have six channels. If that's not the case, then there are more complications.) Avoiding applying sw volume could be done by introducing another sink input flag: PA_SINK_INPUT_NO_VOLUME and making sure that such sink inputs are initialized with PA_VOLUME_NORM. pa_sink_input_set_volume() would contain an assertion making sure that it's not called for inputs with that flag. That would mean that all the places that call pa_sink_input_set_volume() would need to be adapted. The detail that even while conceptually the sink input wouldn't have volume, initializing the volume to PA_VOLUME_NORM would probably save us from touching pa_sink_render() code. Similar flag would be needed for sinks too, and similar modifications to the places that call pa_sink_set_volume(). I think that covers the most important pieces. The lack of volume would need to be communicated to clients somehow (with sink and stream flags probably). But old clients wouldn't understand that anyway - when a client tries to set the volume of a sink or stream without volume, then just make the operation fail, or make the operation a no-op. [1] Is it a problem that a sink can't reconfigure its sample rate at runtime? According to Wikipedia, an AC3 stream's sample rate can be either 32 kHz, 44.1 kHz or 48 kHz. It would seem to me that the sink should reinitialize its sample rate whenever a new AC3 stream is connected to it, otherwise the user can play only those files that have the right sample rate. -- Tanu Kaskinen