i-rinat / apulse

PulseAudio emulation for ALSA
MIT License
609 stars 35 forks source link

Video playback is choppy in Firefox when apulse is used #45

Closed i-rinat closed 7 years ago

i-rinat commented 7 years ago

Video playback is choppy in Firefox when apulse is used. Looks like fps was significantly decreased, with random frame delays.

Reproduced with Firefox 51. When the same Firefox 51 is using ALSA directly, video playback is smooth.

hishamhm commented 7 years ago

@i-rinat We made more tests here and it seems reducing the ring buffer improves the behavior a lot. @lucasvr wrote the following patch:

Reduce audio delay playing Youtube videos.
Patch by lucasvr@gobolinux.org
--- apulse-0.1.8.orig/src/apulse-stream.c   2017-03-08 13:38:10.000000000 -0300
+++ apulse-0.1.8/src/apulse-stream.c    2017-03-08 20:36:17.074256258 -0300
@@ -77,7 +77,7 @@ data_available_for_stream(pa_mainloop_ap
     pa_stream          *s = userdata;
     snd_pcm_sframes_t   frame_count;
     size_t              frame_size = pa_frame_size(&s->ss);
-    char                buf[16 * 1024];
+    char                buf[8 * 1024];
     const size_t        buf_size = pa_find_multiple_of(sizeof(buf), frame_size);
     int                 paused = g_atomic_int_get(&s->paused);

@@ -593,7 +593,7 @@ pa_stream_new_with_proplist(pa_context *
     s->timing_info.configured_source_usec = 0;
     s->timing_info.since_underrun = 0;

-    s->rb = ringbuffer_new(72 * 1024);    // TODO: figure out size
+    s->rb = ringbuffer_new(8 * 1024);    // TODO: figure out size
     s->peek_buffer = malloc(s->rb->end - s->rb->start);

     return s;
@@ -754,7 +754,7 @@ pa_stream_writable_size(pa_stream *s)
     //
     // Workaround issue by reserving certain amount for that case.

-    const size_t limit = 16 * 1024; // TODO: adaptive values?
+    const size_t limit = 8 * 1024; // TODO: adaptive values?

     if (writable_size < limit)
         writable_size = 0;
hishamhm commented 7 years ago

I also noticed that, in my case, most of the choppiness came when using the dmix ALSA plugin. When I disabled it in my ~/.asoundrc (and applied the above patch), I got smooth and (apparently) synced playback in Youtube. I'm running this right now.

I also noticed that apulse is not the only piece of software to have trouble with dmix: the Nestopia NES emulator also gets very choppy when dmix is in use in ~/.asoundrc — so the problem may be in dmix instead?

ndk- commented 7 years ago

I can confirm that the issue is present on FF 52.0 64-bit on the current(-ish) Gentoo (64-bit too). My sound card is the USB one: [81085.135278] usb 3-4: new full-speed USB device number 6 using xhci_hcd [81085.304240] usb 3-4: New USB device found, idVendor=08bb, idProduct=2704 [81085.304242] usb 3-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [81085.304243] usb 3-4: Product: USB Audio DAC
[81085.304244] usb 3-4: Manufacturer: Burr-Brown from TI
[81085.307107] input: Burr-Brown from TI USB Audio DAC as /devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.2/0003:08BB:2704.0007/input/input23 [81085.358306] hid-generic 0003:08BB:2704.0007: input,hidraw0: USB HID v1.00 Device [Burr-Brown from TI USB Audio DAC ] on usb-0000:00:14.0-4/input2

I did a quick preliminary research and it seems that some of the buffer sizes must me queried from ALSA: https://bugzilla.gnome.org/show_bug.cgi?id=162024 I could be wrong though.

i-rinat commented 7 years ago

Previously, I did nothing with pa_buffer_attr values passed by a client, but rather used some arbitrary values. It was fine. But Firefox seems to be expecting callbacks on every minreq bytes.

PulseAudio API describes that field as "minimum request". And I thought it was fine to call client back for more that minreq bytes at a time, but apparently it's not.

Anyway, I pushed 18f74bc24fdefbf2f3323a6802f1b783bbdacb06, which makes videos look fine in Firefox (for me, at least). There are some other changes, mostly to make sure that minreq will be multiple of a frame size.