10.05.2014 06:46, Raymond Yau wrote:
I acknowledge that there was some confusion regarding the precise
meaning of the flag (especially given three possible situations - accurate to just one period, accurate to better than one period but worse than one sample, accurate to one sample), and I am not the authority here.
Can this granularity be measured by
- open a playback stream with 2 or more periods
- fill the full buffer and start playback
- check the value returned by snd_pcm_rewindable () is half of period
at half period time interval 4) repeat the test with 1/4 , 1/8,..., period time interval
Yes and no.
Instead of what you are proposing above, I wrote a loop that repeatedly calls snd_pcm_rewindable() 7000000 times and prints the result if it differs from the previous one. With snd-hda-intel (PCH), hw plugin, stereo, S16_LE, 48 kHz, 6 periods, and a period size of 1024, I get this:
Rewindable: 6119, loop iteration: 0 Rewindable: 5119, loop iteration: 5389434
So snd_pcm_rewindable() can return weird values that are updated every period size or so. As such, I wouldn't believe its return value out of the box even for hw devices. At loop iteration 5389433, the CPU chewed enough time for almost one period, but snd_pcm_rewindable() said that almost 6 periods are rewindable. Probably a missing sync_ptr() somewhere, or a documentation bug.
With snd_pcm_avail() inserted (which does synchronize the position) before each call to snd_pcm_rewindable(), I get:
Rewindable: 6119, loop iteration: 0 Rewindable: 6112, loop iteration: 2 Rewindable: 6104, loop iteration: 42 Rewindable: 6096, loop iteration: 76 Rewindable: 6088, loop iteration: 125 Rewindable: 6080, loop iteration: 173 Rewindable: 6072, loop iteration: 222 Rewindable: 6064, loop iteration: 270
(and an underrun in the end).
With 4 channels:
Rewindable: 6112, loop iteration: 0 Rewindable: 6108, loop iteration: 2 Rewindable: 6104, loop iteration: 14 Rewindable: 6100, loop iteration: 36 Rewindable: 6096, loop iteration: 58 Rewindable: 6092, loop iteration: 63
With 8 channels:
Rewindable: 6104, loop iteration: 0 Rewindable: 6098, loop iteration: 1 Rewindable: 6096, loop iteration: 2 Rewindable: 6094, loop iteration: 9 Rewindable: 6092, loop iteration: 24 Rewindable: 6090, loop iteration: 32 Rewindable: 6088, loop iteration: 41
So on my snd-hda-intel, the granularity of the pointer is 32 bytes.
For Haswell HDMI (on another snd-hda-intel), stereo, S16_LE:
Rewindable: 6128, loop iteration: 0 Rewindable: 6112, loop iteration: 129 Rewindable: 6096, loop iteration: 339 Rewindable: 6080, loop iteration: 551 Rewindable: 6064, loop iteration: 753 Rewindable: 6048, loop iteration: 966 Rewindable: 6032, loop iteration: 1180
so the resulting granularity is 64 bytes.
An unfortunate observation is that, without snd_pcm_avail(), even on hw just after an underrun snd_pcm_rewindable() can return negative numbers such as -16 or -25 that lead to nonsense error codes (EBUSY or ENOTTY).
In addition, there seems to be some confusion here between the
hardware periods (which are always 256 samples) and the period size in hw params. If I understand the other emails correctly, regardless of what the user set in hw_params, the reported position on ymfpci will be accurate to within 256 samples.
http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/ch05s06.html#pcm-i...
This callback is called when the PCM middle layer inquires the current hardware position on the buffer. The position must be returned in frames, ranging from 0 to buffer_size - 1.
This does not implies all drivers must give accurate position at any time, some drivers may use timer interrupt and increase the pointer by one periods
That's why we have snd_pcm_htimestamp().
http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/ch05s07.html#pcm-i...
High frequency timer interrupts
This happens when the hardware doesn't generate interrupts at the period boundary but issues timer interrupts at a fixed timer rate (e.g. es1968 or ymfpci drivers). In this case, you need to check the current hardware position and accumulate the processed sample length at each interrupt. When the accumulated size exceeds the period size, call snd_pcm_period_elapsed() and reset the accumulator.
This clears the confusion.
I am also confuse about ymfpci really use timer interrupts.
Well, that's easy. According to your own words, the card sends an interrupt every 256 samples and has no real notion of the user-defined period size. From ALSA viewpoint, this 256-sample interrupt is just a timer (but not a timer that is managed through functions that have "timer" in the name).
<snip information on the OSS DSP_CAP_REALTIME and DSP_CAP_BATCH capability bits>
Interesting, but does not really clarify anything.
hw_ptr granularity is defined only by period_bytes_min (and
additional constraints if any).
Well, this disagrees with my experiments. For S16_LE stereo, snd_pcm_hw_params_get_period_size_min() says 32 samples for both PCH and HDMI, while the measured granularity is different (8 and 16 samples).
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/so...
hw.period_bytes_min = 256; hw.fifo_size = dma_data->fifo_size;
Does soc drivers transfer audio in 256 bytes ?
seem twice the values of snd-hda-Intel (pcie bus)
No comment on this, I am not an expert in this area.
PulseAudio has the following consideration here: if the card cannot
report the position accurately, we need to disable the timestamp-based scheduling, as this breaks module-combine-sink (or any successor of it), because it relies on very accurate estimations of the actual sample rate ratio between two non-identical cards.
This is something to investigate, I am not ready to provide any useful comment. Although in comment #2 bluetooth is mentioned, and this is indeed an example where even somewhat accurate timing information is not available.
if you want to hear sound from two snd-hda-intel at the same time using combined sink, you may need driver provide the output delay in hda codec
7.3.4.5 Audio Function Group Capabilities
Output Delay is a four bit value representing the number of samples between when the sample is received from the Link and when it appears as an analog signal at the pin. This may be a “typical” value. If this is 0, the widgets along the critical path should be queried, and each individual widget must report its individual delay.
Figure 85. Audio Function Group Capabilities Response Format
7.3.4.6 Audio Widget Capabilities
Delay indicates the number of sample delays through the widget. This may be 0 if the delay value in the Audio Function Parameters is supplied to represent the entire path.
http://git.kernel.org/cgit/linux/kernel/git/tiwai/hda-emu.git/tree/codecs
some hda codecs report delay in audio output/input widgets and the ranges of delay vary from 3 to 13 samples, hda_proc.c did not show output/input delay in the audio function group
Interesting, implementable for someone with the skills in this area, but probably not relevant for the above freedesktop bug. What you are talking about is just a constant offset in the snd_pcm_delay() return values. That's bad, but I guess not bad enough for PulseAudio to stutter. What PulseAudio doesn't tolerate is jitter.
Does it mean that pulseaudio need to add back the difference of output delay of two hda codecs ?
Yes.
If yes, this look like combined sink is also not rewindable too when difference of output delay is not zero
Indeed, it is not fully rewindable. But what's worse is that the combined sink contains a variable-rate resampler that is used in order to compensate adaptively for slightly different sample rates of the two cards.
http://git.alsa-project.org/?p=alsa-plugins.git;a=blob;f=doc/upmix.txt;hb=HE...
for upmix plugin, this mean that snd_pcm_rewindable may need to return zero when user specify delay > 0 if you want "glitch free" rewind
Absolutely correct.
Other pulseaudio modules seen does not support rewind (e.g. jack, tunnel, Bluetooth,...
http://git.alsa-project.org/?p=alsa-plugins.git;a=tree
Other alsa plugins (e.g. Jack, oss,...) seem not support rewind
Jack is interesting here: it is the only ioplug-based plugin which sets mmap_rw = 1. As such, ALSA treats it as something that has mmapped buffer with the same semantics as an ordinary hardware sound card, and performs rewinds using this buffer. There is also a "hardware" position callback. The actual transfer of samples from that buffer to JACK is performed in a separate realtime thread which is implicitly created in jack_activate(). The porition is updated every JACK period.
The whole construction should support rewinds, with the non-rewindable remainder being one JACK period (which may be different from one ALSA period). If the JACK period is 256 samples, this plugin should behave very much like one voice of ymfpci.
However, there is still a bug (possibly fixable). While running my test program over this plugin does produce silence, it produces a wrong amount of silence. As if there is something wrong with snd_pcm_jack_poll_revents() or snd_pcm_jack_pointer(). I have not tested this patch yet, although I should:
http://comments.gmane.org/gmane.linux.alsa.devel/122554
As for ioplug-based plugins with mmap_rw = 0, they are indeed not rewindable at all.
How about route and plug plugins ?
Route should in theory support rewind, but there may be bugs. The best way to test is to run a program that I attached to an earlier message in this thread and listen - any non-silence indicates a non-rewindable plugin.
Plug is not really a plugin, it just inserts other plugins and then disappears. It can insert adpcm and rate plugins which are not really rewindable.
For cards that are not batch, it will attempt to set both the period
size and the buffer size to something large (tsched_size, the default is 2s) and let the driver adjust that to something more sensible for the card. I think that in practice this means periods_min, although it is never mentioned explicitly in PulseAudio source.
it does not mean all drivers uses periods_min when applicaition did not explicitly set period , period time or period bytes
http://git.alsa-project.org/?p=alsa-lib.git;a=commit;h=09879a4bb58199f64abcb...
Some driver 's period_bytes_max can be less than (buffer_bytes_max / periods_min)
Please see this code and make your own conclusions.
http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/modules/alsa/alsa...
PulseAudio does try several strategies, among those is "set nothing at all if everything else failed".
For batch cards, the desired period (or, in PA speak, "fragment")
time and the number of periods come from the config, of course subject to adjustments made by the ALSA library to fit the hardware requirements.
as long as the application use two periods , no safe rewind is possible as the application need to keep at least two periods fill in the buffer if the pointer is not accurate.
Correct if we use the viewpoint that the pointer granularity is one period for such cards. Which is not the case for ymfpci and for USB audio.
do you mean that pulseaudio still perform rewind when using AC3 passthrough on Didital playback device ?
I don't know.
if not , the value of snd_pcm_rewindable() of digital playback device depends on whether no audio bit is set or not
While I understand the idea, I would like to see more details. The only consideration that comes to my mind is that it should not be possible to rewind into the middle of the currently playing IEC 61937 frame. But there are also stupid receivers (e.g. JVC TH-A25) that mute their outputs if a non-IEC-wrapped DTS stream (as found on DTS CDs) is coming with AES0 = 6.
The defaults are:
; default-fragments = 4 ; default-fragment-size-msec = 25
Does this mean that pulseaudio use this values for all sound card including hda when user specify this value ?
This is the default for all cards that are autodetected as incompatible with tsched or where the user configured tsched=0. These defaults can still be overridden with module-alsa-card parameters.
Seem the values are comment out and not used by pulseaudio as default , users have to explicitly set these in the following report
The commented-out values are used by default when PulseAudio decides that it needs a traditional (not tsched based) playback model. They are in the source:
http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/daemon/daemon-con...
https://bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/428619/comments/96
The key in that comment is the explicit tsched=0. Without tsched=0, these settings are not used.