From 55f9a4782bea7a85936b9b2ef3a5a3ddb6fbcde2 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Thu, 16 Jan 2003 22:25:53 +0000 Subject: - fix PVA buffer leaking problems - add generic mpeg-like wrap detection code to TS and PVA demuxers - now scr/pcr based wrap detection is used nowhere in xine, it's simply not reliable and caused too many problems (including recent freezing in demux_ts) CVS patchset: 3938 CVS date: 2003/01/16 22:25:53 --- src/demuxers/demux_mpeg.c | 29 +------------------- src/demuxers/demux_pva.c | 61 ++++++++++++++++++++++++++++++++++------- src/demuxers/demux_ts.c | 70 ++++++++++++++++++----------------------------- 3 files changed, 79 insertions(+), 81 deletions(-) diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index a226a9bae..dea0f3eca 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_mpeg.c,v 1.104 2003/01/10 21:11:00 miguelfreitas Exp $ + * $Id: demux_mpeg.c,v 1.105 2003/01/16 22:25:53 miguelfreitas Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -638,33 +638,6 @@ static uint32_t parse_pack(demux_mpeg_t *this) { buf = read_bytes (this, 3) ; } - /* discontinuity ? */ -#if 0 - /* scr-wrap detection disabled due bad streams */ - if( scr && !this->preview_mode ) - { - int64_t scr_diff = scr - this->last_scr; - - if (abs(scr_diff) > 60000 && !this->send_newpts) { - - buf_element_t *buf; - - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; - buf->disc_off = scr_diff; - this->video_fifo->put (this->video_fifo, buf); - - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; - buf->disc_off = scr_diff; - this->audio_fifo->put (this->audio_fifo, buf); - } - } - this->last_scr = scr; - } -#endif - /* system header */ buf = read_bytes (this, 4) ; diff --git a/src/demuxers/demux_pva.c b/src/demuxers/demux_pva.c index ae324eeee..5d558b060 100644 --- a/src/demuxers/demux_pva.c +++ b/src/demuxers/demux_pva.c @@ -21,7 +21,7 @@ * For more information regarding the PVA file format, refer to this PDF: * http://www.technotrend.de/download/av_format_v1.pdf * - * $Id: demux_pva.c,v 1.3 2003/01/10 11:57:17 miguelfreitas Exp $ + * $Id: demux_pva.c,v 1.4 2003/01/16 22:25:54 miguelfreitas Exp $ */ #ifdef HAVE_CONFIG_H @@ -43,6 +43,11 @@ #define PVA_PREAMBLE_SIZE 8 +#define WRAP_THRESHOLD 120000 + +#define PTS_AUDIO 0 +#define PTS_VIDEO 1 + typedef struct { demux_plugin_t demux_plugin; @@ -60,6 +65,10 @@ typedef struct { int thread_running; pthread_mutex_t mutex; int send_end_buffers; + + int send_newpts; + int buf_flag_seek; + int64_t last_pts[2]; off_t data_start; off_t data_size; @@ -80,6 +89,35 @@ typedef struct { } demux_pva_class_t; +/* redefine abs as macro to handle 64-bit diffs. + i guess llabs may not be available everywhere */ +#define abs(x) ( ((x)<0) ? -(x) : (x) ) + +static void check_newpts( demux_pva_t *this, int64_t pts, int video ) +{ + int64_t diff; + + diff = pts - this->last_pts[video]; + + if( pts && + (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) { + + if (this->buf_flag_seek) { + xine_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); + this->buf_flag_seek = 0; + } else { + xine_demux_control_newpts(this->stream, pts, 0); + } + this->send_newpts = 0; + this->last_pts[1-video] = 0; + } + + if( pts ) + this->last_pts[video] = pts; +} + + + /* returns 1 if the PVA file was opened successfully, 0 otherwise */ static int open_pva_file(demux_pva_t *this) { @@ -115,10 +153,13 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) { unsigned char preamble[PVA_PREAMBLE_SIZE]; unsigned char pts_buf[4]; off_t current_file_pos; + int64_t pts; if (this->input->read(this->input, preamble, PVA_PREAMBLE_SIZE) != - PVA_PREAMBLE_SIZE) - return 0; + PVA_PREAMBLE_SIZE) { + this->status = DEMUX_FINISHED; + return this->status; + } /* make sure the signature is there */ if ((preamble[0] != 'A') || (preamble[1] != 'V')) { @@ -132,25 +173,26 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) { this->data_start; if (preamble[2] == 1) { - + /* video */ - buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); /* load the pts if it is the first thing in the chunk */ if (preamble[5] & 0x10) { if (this->input->read(this->input, pts_buf, 4) != 4) { - buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; } chunk_size -= 4; - buf->pts = BE_32(&pts_buf[0]); + pts = BE_32(&pts_buf[0]); + check_newpts( this, pts, PTS_VIDEO ); } else - buf->pts = 0; + pts = 0; while (chunk_size) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_MPEG; + buf->pts = pts; + pts = 0; buf->extra_info->input_pos = current_file_pos; buf->extra_info->input_length = this->data_size; buf->extra_info->input_time = buf->pts / 90; @@ -251,8 +293,7 @@ static int demux_pva_seek (demux_plugin_t *this_gen, /* if thread is not running, initialize demuxer */ if( !this->stream->demux_thread_running ) { - /* send new pts */ - xine_demux_control_newpts(this->stream, 0, 0); + this->send_newpts = 1; this->status = DEMUX_OK; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index aae2d337d..a3ad4da07 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_ts.c,v 1.75 2003/01/10 21:11:10 miguelfreitas Exp $ + * $Id: demux_ts.c,v 1.76 2003/01/16 22:25:54 miguelfreitas Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -188,6 +188,11 @@ #define ISO13522_STREAM 0xF3 #define PROG_STREAM_DIR 0xFF +#define WRAP_THRESHOLD 120000 + +#define PTS_AUDIO 0 +#define PTS_VIDEO 1 + /* ** ** DATA STRUCTURES @@ -255,8 +260,6 @@ typedef struct { */ unsigned int programNumber; unsigned int pcrPid; - int64_t PCR; - int64_t last_PCR; unsigned int pid; unsigned int pid_count; unsigned int videoPid; @@ -266,7 +269,7 @@ typedef struct { char audioLang[4]; int send_end_buffers; - int ignore_scr_discont; + int64_t last_pts[2]; int send_newpts; int buf_flag_seek; @@ -321,14 +324,23 @@ static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data, return crc32; } -static void check_newpts( demux_ts_t*this, int64_t pts ) { +/* redefine abs as macro to handle 64-bit diffs. + i guess llabs may not be available everywhere */ +#define abs(x) ( ((x)<0) ? -(x) : (x) ) + +static void check_newpts( demux_ts_t *this, int64_t pts, int video ) +{ + int64_t diff; #ifdef TS_LOG printf ("demux_ts: check_newpts %lld, send_newpts %d, buf_flag_seek %d\n", pts, this->send_newpts, this->buf_flag_seek); #endif - - if (this->send_newpts && pts) { + + diff = pts - this->last_pts[video]; + + if( pts && + (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) { if (this->buf_flag_seek) { xine_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); @@ -337,8 +349,11 @@ static void check_newpts( demux_ts_t*this, int64_t pts ) { xine_demux_control_newpts(this->stream, pts, 0); } this->send_newpts = 0; - this->ignore_scr_discont = 1; + this->last_pts[1-video] = 0; } + + if( pts ) + this->last_pts[video] = pts; } @@ -765,7 +780,6 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, } else { - check_newpts(this, m->pts); m->corrupted_pes = 0; m->buf = m->fifo->buffer_pool_alloc(m->fifo); memcpy(m->buf->mem, ts+len-m->size, m->size); @@ -1455,35 +1469,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { if( adaptation_field_control & 0x2 ){ uint32_t adaptation_field_length = originalPkt[4]; if (adaptation_field_length > 0) { - this->PCR = demux_ts_adaptation_field_parse (originalPkt+5, - adaptation_field_length); - - if (pid == this->pcrPid && this->PCR) { - int64_t scr_diff = this->PCR - this->last_PCR; - - /* note: comparing (abs(scr_diff) > 90000) isn't reliable - * below because abs() give inconsistent results on int64_t - * types */ - if ( (scr_diff > 90000 || scr_diff < -90000) && !this->send_newpts && - !this->ignore_scr_discont ) { - - buf_element_t *buf; - - buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; - buf->disc_off = scr_diff; - this->video_fifo->put (this->video_fifo, buf); - - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); - buf->type = BUF_CONTROL_DISCONTINUITY; - buf->disc_off = scr_diff; - this->audio_fifo->put (this->audio_fifo, buf); - } - } - this->last_PCR = this->PCR; - this->ignore_scr_discont = 0; - } + demux_ts_adaptation_field_parse (originalPkt+5, adaptation_field_length); } /* * Skip adaptation header. @@ -1516,7 +1502,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, t); } } else if (t == PRIVATE_STREAM1 || - t >= AUDIO_STREAM_S && t <= AUDIO_STREAM_E) { + (t >= AUDIO_STREAM_S && t <= AUDIO_STREAM_E)) { if ( this->audioPid == INVALID_PID) { printf ("demux_ts: auto-detected audio pid %d\n", @@ -1543,6 +1529,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { #ifdef TS_LOG printf ("demux_ts: Video pid: %.4x\n", pid); #endif + check_newpts(this, this->media[this->videoMedia].pts, PTS_VIDEO); demux_ts_buffer_pes (this, originalPkt+data_offset, this->videoMedia, payload_unit_start_indicator, continuity_counter, data_len); @@ -1552,6 +1539,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { #ifdef TS_LOG printf ("demux_ts: Audio pid: %.4x\n", pid); #endif + check_newpts(this, this->media[this->audioMedia].pts, PTS_AUDIO); demux_ts_buffer_pes (this, originalPkt+data_offset, this->audioMedia, payload_unit_start_indicator, continuity_counter, data_len); @@ -1693,14 +1681,12 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) { this->input->seek (this->input, 0, SEEK_SET); this->send_newpts = 1; - this->ignore_scr_discont = 0; demux_ts_build_crc32_table (this); this->status = DEMUX_OK ; this->send_end_buffers = 1; - this->last_PCR = 0; this->scrambled_npids = 0; /* DVBSUB */ @@ -1729,7 +1715,6 @@ static int demux_ts_seek (demux_plugin_t *this_gen, } this->send_newpts = 1; - this->ignore_scr_discont = 0; for (i=0; imedia[i]; @@ -1967,7 +1952,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->programNumber = INVALID_PROGRAM; this->pcrPid = INVALID_PID; - this->PCR = 0; this->scrambled_npids = 0; this->videoPid = INVALID_PID; this->audioPid = INVALID_PID; -- cgit v1.2.3