From 4b7717078ce7127c1d886c964a28144e944942a3 Mon Sep 17 00:00:00 2001 From: Rocky Bernstein Date: Sun, 15 Dec 2002 01:05:36 +0000 Subject: demux_mpeg_block_estimate_rate(): Don't read outside of region that we are supposed to get bitrate estimate of. Bound the number of reads and samples (which also bounds the time spent in this routine. CVS patchset: 3530 CVS date: 2002/12/15 01:05:36 --- src/demuxers/demux_mpeg_block.c | 58 +++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 8d6c0279d..8a08524d8 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.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_block.c,v 1.147 2002/12/08 21:43:51 miguelfreitas Exp $ + * $Id: demux_mpeg_block.c,v 1.148 2002/12/15 01:05:36 rockyb Exp $ * * demultiplexer for mpeg 1/2 program streams * @@ -640,35 +640,55 @@ static int demux_mpeg_block_send_chunk (demux_plugin_t *this_gen) { return this->status; } -/* estimate bitrate */ +/*! + Estimate bitrate by looking inside the MPEG file for presentation + time stamps (PTS) and computing how far apart these are + in bytes and in time. + + On failure return 0. +*/ + +/* How many *sucessful* PTS samples do we take? */ +#define MAX_SAMPLES 5 + +/* How many times we read blocks before giving up. */ +#define MAX_READS 30 + +/* TRUNCATE x to the nearest multiple of y. */ +#define TRUNC(x,y) (((x) / (y)) * (y)) static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { buf_element_t *buf = NULL; unsigned char *p; int is_mpeg1=0; - off_t pos, last_pos; - off_t step; - int64_t pts, last_pts; - int rate; - int count; + off_t pos, last_pos=0; + off_t step, mpeg_length; + off_t blocksize = this->blocksize; + int64_t pts, last_pts=0; + int reads=0 /* Number of blocks read so far */; + int count=0; /* Number of sucessful PTS found so far */ + int rate=0; /* The return rate value */ int stream_id; + /* We can't estimate by sampling if we don't thave the ability to + randomly access the and more importantly reset after accessessing. */ if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE)) return 0; - last_pos = 0; - last_pts = 0; - rate = 0; - step = this->input->get_length (this->input) / 10; - step = (step / this->blocksize) * this->blocksize; - if (step <= 0) step = this->blocksize; /* avoid endless loop for tiny files */ - pos = step; - count = 0; + mpeg_length= this->input->get_length (this->input); + step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize); + if (step <= 0) step = blocksize; /* avoid endless loop for tiny files */ + pos = step; + + /* At this point "pos", and "step" are a multiple of blocksize and + they should continue to be so throughout. + */ this->input->seek (this->input, pos, SEEK_SET); - while ((buf = this->input->read_block (this->input, this->video_fifo, this->blocksize)) ) { + while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize)) + && count < MAX_SAMPLES && reads++ < MAX_READS ) { p = buf->content; /* len = this->mnBlocksize; */ @@ -698,7 +718,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { pts = 0; if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) { - pos += (off_t) this->blocksize; + pos += (off_t) blocksize; buf->free_buffer (buf); continue; /* only use video packets */ } @@ -762,11 +782,11 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { last_pts = pts; pos += step; } else - pos += (off_t) this->blocksize; + pos += blocksize; buf->free_buffer (buf); - if (this->input->seek (this->input, pos, SEEK_SET) == (off_t)-1) + if (pos > mpeg_length || this->input->seek (this->input, pos, SEEK_SET) == (off_t)-1) break; } -- cgit v1.2.3