I have a customer with a commercial product that incorporates Xine for
playback of ATSC streams. I've got a case where I hit a PCR
discontinuity and from that point forward get stuttering video,
despite my best efforts to tune various buffering parameters and
instrument the code.
It looks like I've got concurrency issue between the three main
threads (input thread, decoder thread, video_out thread), where the
video_out thread stalls and exhausts the available buffers, thus the
input thread gets blocked in buffer_pool_alloc(). It's not quite a
deadlock because the video_out thread periodically wakes up once a
second in vo_remove_from_img_buf_queue_int(). Because the input
thread is blocked allocating buffers, it isn't calling read() often
enough, which ultimately returns -EOVERFLOW (note, I've got a simple
patch that retries in this case rather than ending the stream). In
short, the problem is exacerbated by the fact that when the input
thread finally does start running again, it immediately hits a
discontinuity. The net effect is the playback stalls for one second,
starts playing for a fraction of a second, and then stalls again for
one second (this process repeats until the stream is stopped).
I'm running Xine 1.2.5 and I have a sample TS that demonstrates the
issue. The problem is that the issue is only reproducible when the
stream is served via the input_dvb plugin (it doesn't occur when
playing the ts file directly). Hence a DVB/ATSC signal generator is
required to repro/debug the problem. In my environment I've got the
ten minute segment playing on a loop with my Dektec DTA-110T
Things I've already tried:
- tuning the engine.buffers.video_num_buffers
- increasing the NPKT_PER_READ in demux_ts.c
- tweaking the timeout for the pthread_cond_timedwait in
vo_remove_from_img_buf_queue_int() to be smaller
- increasing the size of the in-kernel dvr buffer via DMX_SET_BUFFER_SIZE
The latter two changes do appear to "improve" the situation, but I
still hit EOVERFLOWs a bit later in the stream, suggesting after we
hit the problem we're still not servicing the read() call fast enough.
I've spent several days digging into the code for the various threads
to understand the lock interdependencies, but it would be great if
there were somebody out there much more familiar with the Xine
codebase that might be interested in doing a bit of consulting to get
the sample stream playing well.
Any other advise is on how to get to the bottom of this is certainly welcome.
Devin J. Heitmueller - Kernel Labs