[MPlayer-dev-eng] Cache behaviour for real time streaming (prepatch)
Franck Arnaud
franck at nenie.org
Fri Jan 10 21:33:04 CET 2003
Hello,
I use mplayer with MPEG2 streamed from a broadcast source (using
dvbstream on another box). It used to be a comprehensive disaster,
with AV getting out of synch quite quickly, sound disappearing etc.
I did mistakenly try many sound/synch based tweaks, which did not
help. AV synch is perfect on DVD or files. I eventually got to what
I think is the root of my problem: the cache behaviour.
In non-realtime situations, the cache fills up because the
source can be faster than the video. In a real time broadcast,
there's no way the source could be faster. This means that
unless mplayer plays slower than realtime, we can't ever
fill the cache. That is if there's a little problem like
broken frames, or some A/V synch, mplayer will eat a bit
of the cache and will end up eventually with no cache.
To demonstrate the problem is easy:
- server: dvbstream ...
- client: dumprtp | ts2ps 1 2 | mplayer -cache X -
- client: mplayer OK
- server: kill dvbstream
- client: mplayer waits
- server: restart dvbstream
- client: mplayer tries to catch up, but completely confused.
cache stays at 0%.
Killing the source is drastic, but this also happens in normal
use after a few minutes with a few MB of cache, as the cache
never reaches more than the prefill rate, and once empty
you're in the same confused situation as after killing
the stream, and you never recover (except by restarting
mplayer).
First trick I tried is to use a much bigger cache. So
if I want 4 MB cache, I use -cache 16000 to get 4MB
of prefill, and if everything goes well the cache
fill level stays at 20%. That's much better, but
does not cope much better with stopping the broadcast
source, and eventually we end up with an empty cache.
And we waste 3/4 of the cache memory which is never
used.
So I did a small patch that waits when the cache gets low.
It's not production quality but it may help if you have the
same problem, and may be a useful starting point if the
developers want to introduce something like that (or
point me to what is missing to make a proper patch).
I added that to mplayer.c after the 'auto quality' bit,
after "} // end if(sh_video)":
#ifdef USE_STREAM_CACHE
#define STREAM_REFILL_THRESHOLD 44
#define STREAM_REFILL_SLEEP_TIME 200
current_module="cacherefill";
if(stream->type == STREAMTYPE_STREAM && cache_fill_status < 10) {
// The cache is nearly empty and we are streaming.
// When the stream comes in real time, which is likely for
// STREAMTYPE_STREAM, we have no chance to catch up, so
// just pause until the cache is filled to threshold.
while(cache_stream_fill_status(stream) < STREAM_REFILL_THRESHOLD &&
(mp_input_check_interrupt(STREAM_REFILL_SLEEP_TIME)==0)) {
// the cache is in another process, so we just need to wait
// here until data arrives.
mp_msg(MSGT_CACHE, MSGL_STATUS, "Filling cache %d%%...\r",
cache_stream_fill_status(stream));
usleep(20000);
}
mp_msg(MSGT_CACHE, MSGL_STATUS, "Filling done\n");
}
#endif
And in libmpdemux/cache2.c add:
int cache_stream_fill_status (stream_t *stream) {
cache_vars_t* s=stream->cache_data;
if (!s) return 0;
return 100*(s->max_filepos-s->read_filepos)/s->buffer_size;
}
and the corresponding stream.h bit.
There's some sort of race condition if the cache size is too low
and the threshold to high (I think I had the problem with 2MB and 50%
threashold), I guess because of some minimum block size in the cache
or the like. Try a bigger -cache value if that is a problem.
I tested with rc2.
--
franck at nenie.org
More information about the MPlayer-dev-eng
mailing list