From 3e2ed6d0263c021644041ad3928ba4e7074360d7 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Sun, 3 Jun 2007 17:47:19 +0100 Subject: [patch] Fix video pid misdetection Hi, the next bug that has been annoying me is as follows. I have some streams recorded from BBC4 on UK DVB-T. BBC4 only actually starts transmitting at about 7pm; prior to that there is a static picture saying it is not playing just now. With these streams and xine, I would get audio, but no picture. Looking at the PMT table during the static picture, all the streams have type 0x0b. However there IS a video stream in there, but there are also several streams of binary data. Xine's current video PID auto-detection code was locking on to one of these streams of binary data because it contained the magic sequence 00 00 01 e0 at one of the PUS. *HOWEVER* it is NOT a PES stream; this sequence is just an accident. The other problem is that xine can only handle one video stream; so once it was misdetected once, it was stuck at that PID. The attached patch changes the corrupted_pes flag into a counter. If a video stream has more than CORRUPT_PES_THRESHOLD corrupt PES packets in a row, then it is deselected as the video stream, and auto-detection is kicked off again. Auto-detection will now also ignore any streams seen previously which have a nonzero corrupted_pes count. This works very well; I can now see the video fine. One possible issue might be that if you get a lot of corrupt PES in a stream which really IS the video stream, it will be deselected. However, this is not actually a problem: once the corruption goes away, the corrupted_pes counter will be reset to 0, and the stream will once again be autodetected as the video stream (and playback will continue from there). --- src/demuxers/demux_ts.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index f2da5f268..57925deff 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -180,6 +180,8 @@ #define MAX_PES_BUF_SIZE 2048 +#define CORRUPT_PES_THRESHOLD 10 + #define NULL_PID 0x1fff #define INVALID_PID ((unsigned int)(-1)) #define INVALID_PROGRAM ((unsigned int)(-1)) @@ -913,12 +915,17 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, m->buf = m->fifo->buffer_pool_alloc(m->fifo); if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len, this->stream)) { - m->corrupted_pes = 1; m->buf->free_buffer(m->buf); m->buf = NULL; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + + if (m->corrupted_pes > CORRUPT_PES_THRESHOLD) { + if (this->videoPid == m->pid) + this->videoPid = INVALID_PID; + } else { + m->corrupted_pes++; + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid); - + } } else { m->corrupted_pes = 0; @@ -1784,13 +1791,27 @@ static void demux_ts_parse_packet (demux_ts_t*this) { if ( (pes_stream_id >= VIDEO_STREAM_S) && (pes_stream_id <= VIDEO_STREAM_E) ) { if ( this->videoPid == INVALID_PID) { - - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_ts: auto-detected video pid 0x%.4x\n", pid); - - this->videoPid = pid; - this->videoMedia = this->media_num; - demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, pes_stream_id); + int i, found = 0; + for(i = 0; i < this->media_num; i++) { + if (this->media[i].pid == pid) { + found = 1; + break; + } + } + + if (found && (this->media[i].corrupted_pes == 0)) { + this->videoPid = pid; + this->videoMedia = i; + } else if (!found) { + this->videoPid = pid; + this->videoMedia = this->media_num; + demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, pes_stream_id); + } + + if (this->videoPid != INVALID_PID) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_ts: auto-detected video pid 0x%.4x\n", pid); + } } } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) { if (this->audio_tracks_count < MAX_AUDIO_TRACKS) { -- cgit v1.2.3