[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