Test this patch for MPEG-TS over network/dvb streams
Nico Sabbi <[email protected]> Sat, 16 Feb 2008 02:14:06 +0100
| Newsgroups | gmane.comp.video.mplayer.user.dvb |
|---|---|
| Message-ID | <[email protected]> |
Hi, this patch should finally make mplayer play stably and in the long run non-local mpegts streams such as DVB and network ones; in the past those playing streams lead to a lot of video freezes and messages like "too many packate in the buffer". What this patch does is very simple: avoid to decode demuxed packets until the right PCR time has been inserted in the stream. I should use the DTS instead of the PTS to do the time validation, but since they are always very close and since the relation pcr < dts <= pts always applies, the pts serves the purpose well enough. In practice, this patch prevents mplayer from starving data. If you are interested in the details of this issue read the "nut broadcast" thread in [email protected]. Don't forget to add the pmt pid in the stream, or the pcr can't be identified. Please, let me know if you experience improvements and/or regressions, and especially let mplayer run on the same channel for some hour before reporting success. Nico _______________________________________________ MPlayer-dvb mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dvb
pcr2.diff
(text/x-diff, 3.5 KB)
Index: libmpdemux/demux_ts.c
===================================================================
--- libmpdemux/demux_ts.c (revisione 25986)
+++ libmpdemux/demux_ts.c (copia locale)
@@ -502,7 +502,21 @@
return -1;
}
+static inline int32_t prog_pcr_pid(ts_priv_t *priv, int progid)
+{
+ int i;
+ if(priv->pmt == NULL)
+ return -1;
+ for(i=0; i < priv->pmt_cnt; i++)
+ {
+ if(priv->pmt[i].progid == progid)
+ return priv->pmt[i].PCR_PID;
+ }
+ return -1;
+}
+
+
static inline int pid_match_lang(ts_priv_t *priv, uint16_t pid, char *lang)
{
uint16_t i, j;
@@ -875,6 +889,13 @@
if(video_found || audio_found)
{
+ if(!param->prog)
+ {
+ p = progid_for_pid(priv, video_found ? param->vpid : param->apid, 0);
+ if(p != -1)
+ param->prog = p;
+ }
+
if(demuxer->stream->eof && (ret == 0))
ret = init_pos;
mp_msg(MSGT_DEMUXER, MSGL_INFO, " PROGRAM N. %d\n", param->prog);
@@ -1031,6 +1052,7 @@
start_pos = (start_pos <= priv->ts.packet_size ? 0 : start_pos - priv->ts.packet_size);
demuxer->movi_start = start_pos;
+ demuxer->reference_clock = MP_NOPTS_VALUE;
stream_reset(demuxer->stream);
stream_seek(demuxer->stream, start_pos); //IF IT'S FROM A PIPE IT WILL FAIL, BUT WHO CARES?
@@ -2721,11 +2743,38 @@
//c==0 is allowed!
if(c > 0)
{
- rap_flag = (stream_read_char(stream) & 0x40) >> 6;
+ uint8_t pcrbuf[188];
+ int flags = stream_read_char(stream);
+ rap_flag = (flags & 0x40) >> 6;
+ int has_pcr = flags & 0x10;
+
buf_size--;
+ c--;
+ stream_read(stream, pcrbuf, c);
+
+ if(has_pcr)
+ {
+ int pcr_pid = prog_pcr_pid(priv, priv->prog);
+ if(pcr_pid == pid)
+ {
+ uint64_t pcr, pcr_ext;
- c--;
- stream_skip(stream, c);
+ pcr = (int64_t)(pcrbuf[0]) << 25;
+ pcr |= pcrbuf[1] << 17 ;
+ pcr |= (pcrbuf[2]) << 9;
+ pcr |= pcrbuf[3] << 1 ;
+ pcr |= (pcrbuf[4] & 0x80) >> 7;
+
+ pcr_ext = (pcrbuf[4] & 0x01) << 8;
+ pcr_ext |= pcrbuf[5];
+
+ pcr = pcr * 300 + pcr_ext;
+
+ demuxer->reference_clock = (double)pcr/(double)27000000.0;
+ //fprintf(stderr, "\r\nSET PCR: %.3lf\r\n", demuxer->reference_clock);
+ }
+ }
+
buf_size -= c;
if(buf_size == 0)
continue;
Index: libmpdemux/demuxer.c
===================================================================
--- libmpdemux/demuxer.c (revisione 25986)
+++ libmpdemux/demuxer.c (copia locale)
@@ -206,6 +206,7 @@
memset(d,0,sizeof(demuxer_t));
d->stream=stream;
d->stream_pts = MP_NOPTS_VALUE;
+ d->reference_clock = MP_NOPTS_VALUE;
d->movi_start=stream->start_pos;
d->movi_end=stream->end_pos;
d->seekable=1;
@@ -418,6 +419,12 @@
while(1){
if(ds->packs){
demux_packet_t *p=ds->first;
+ if(demux->reference_clock != MP_NOPTS_VALUE) {
+ if((p->pts != MP_NOPTS_VALUE) && (p->pts > demux->reference_clock) && (ds->packs < MAX_PACKS)) {
+ if(demux_fill_buffer(demux,ds))
+ continue;
+ }
+ }
// copy useful data:
ds->buffer=p->buffer;
ds->buffer_pos=0;
Index: libmpdemux/demuxer.h
===================================================================
--- libmpdemux/demuxer.h (revisione 25986)
+++ libmpdemux/demuxer.h (copia locale)
@@ -194,6 +194,7 @@
off_t movi_end;
stream_t *stream;
double stream_pts; // current stream pts, if applicable (e.g. dvd)
+ double reference_clock;
char *filename; ///< Needed by avs_check_file
int synced; // stream synced (used by mpeg)
int type; // demuxer type: mpeg PS, mpeg ES, avi, avi-ni, avi-nini, asf