From 34a383664ad570b3a85a698f61c494d4ff449d9a Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 25 May 2013 15:00:03 +0200 Subject: demux_lavf: change probing, use stream_unread_buffer() This fixes a longstanding issue with demux_lavf probing. See previous commit. --- demux/demux_lavf.c | 64 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) (limited to 'demux') diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index a482f736c6..efe8edd43c 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -47,7 +47,7 @@ #include "core/m_option.h" #define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE -#define PROBE_BUF_SIZE (2 * 1024 * 1024) +#define PROBE_BUF_SIZE FFMIN(STREAM_MAX_BUFFER_SIZE, 2 * 1024 * 1024) #define OPT_BASE_STRUCT struct MPOpts @@ -190,18 +190,15 @@ static int lavf_check_file(demuxer_t *demuxer) { struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; - AVProbeData avpd; + struct stream *s = demuxer->stream; lavf_priv_t *priv; - int probe_data_size = 0; - int read_size = INITIAL_PROBE_SIZE; - int score; assert(!demuxer->priv); demuxer->priv = talloc_zero(NULL, lavf_priv_t); priv = demuxer->priv; priv->autoselect_sub = -1; - priv->filename = demuxer->stream->url; + priv->filename = s->url; if (!priv->filename) { priv->filename = "mp:unknown"; mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream url is not set!\n"); @@ -210,7 +207,7 @@ static int lavf_check_file(demuxer_t *demuxer) priv->filename = remove_prefix(priv->filename, prefixes); char *avdevice_format = NULL; - if (demuxer->stream->type == STREAMTYPE_AVDEVICE) { + if (s->type == STREAMTYPE_AVDEVICE) { // always require filename in the form "format:filename" char *sep = strchr(priv->filename, ':'); if (!sep) { @@ -237,7 +234,7 @@ static int lavf_check_file(demuxer_t *demuxer) const char *format = lavfdopts->format; if (!format) - format = demuxer->stream->lavf_type; + format = s->lavf_type; if (!format) format = avdevice_format; if (format) { @@ -262,38 +259,43 @@ static int lavf_check_file(demuxer_t *demuxer) if (lavfdopts->probescore) min_probe = lavfdopts->probescore; - avpd.buf = av_mallocz(FFMAX(BIO_BUFFER_SIZE, PROBE_BUF_SIZE) + - FF_INPUT_BUFFER_PADDING_SIZE); - do { - read_size = stream_read(demuxer->stream, avpd.buf + probe_data_size, - read_size); - if (read_size < 0) { - av_free(avpd.buf); - return 0; - } - probe_data_size += read_size; - avpd.filename = priv->filename; - avpd.buf_size = probe_data_size; + AVProbeData avpd = { + .filename = priv->filename, + .buf_size = 0, + .buf = av_mallocz(PROBE_BUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE), + }; + + while (avpd.buf_size < PROBE_BUF_SIZE) { + int nsize = av_clip(avpd.buf_size * 2, INITIAL_PROBE_SIZE, + PROBE_BUF_SIZE); + int read_size = stream_read(s, avpd.buf + avpd.buf_size, + nsize - avpd.buf_size); + if (read_size <= 0) + break; - score = 0; - priv->avif = av_probe_input_format2(&avpd, probe_data_size > 0, &score); + avpd.buf_size += read_size; + + int score = 0; + priv->avif = av_probe_input_format2(&avpd, avpd.buf_size > 0, &score); if (priv->avif) { mp_msg(MSGT_HEADER, MSGL_V, "Found '%s' at score=%d size=%d.\n", - priv->avif->name, score, probe_data_size); - } + priv->avif->name, score, avpd.buf_size); - if (priv->avif && score >= min_probe) - break; - if (priv->avif && expected_format) { - if (strcmp(priv->avif->name, expected_format) == 0 && - score >= expected_format_probescore) + if (score >= min_probe) break; + + if (expected_format) { + if (strcmp(priv->avif->name, expected_format) == 0 && + score >= expected_format_probescore) + break; + } } priv->avif = NULL; - read_size = FFMIN(2 * read_size, PROBE_BUF_SIZE - probe_data_size); - } while (read_size > 0 && probe_data_size < PROBE_BUF_SIZE); + } + + stream_unread_buffer(s, avpd.buf, avpd.buf_size); av_free(avpd.buf); if (!priv->avif) { -- cgit v1.2.3 From 1c35794efd7d025457e527b61f7c23fe375c2f5a Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Jun 2013 20:39:58 +0200 Subject: stream: remove stream_reset() This function was called in various places. Most time, it was used before a seek. In other cases, the purpose was apparently resetting the EOF flag. As far as I can see, this makes no sense anymore. At least the stream_reset() calls paired with stream_seek() are completely pointless. A seek will either seek inside the buffer (and reset the EOF flag), or do an actual seek and reset all state. --- demux/aviheader.c | 3 --- demux/demux_asf.c | 1 - demux/demux_avi.c | 1 - demux/demux_lavf.c | 1 - demux/demux_ts.c | 5 ----- 5 files changed, 11 deletions(-) (limited to 'demux') diff --git a/demux/aviheader.c b/demux/aviheader.c index 2226be25d4..c1b9c59692 100644 --- a/demux/aviheader.c +++ b/demux/aviheader.c @@ -479,7 +479,6 @@ if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) { // read the standard indices for (cx = &priv->suidx[0], i=0; isuidx_size; cx++, i++) { - stream_reset(demuxer->stream); for (j=0; jnEntriesInUse; j++) { int ret1, ret2; memset(&cx->stdidx[j], 0, 32); @@ -543,7 +542,6 @@ if (priv->isodml && (index_mode==-1 || index_mode==0 || index_mode==1)) { { uint32_t id; uint32_t db = 0; - stream_reset (demuxer->stream); // find out the video stream id. I have seen files with 01db. for (idx = &((AVIINDEXENTRY *)priv->idx)[0], i=0; iidx_size; i++, idx++){ @@ -590,7 +588,6 @@ freeout: if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){ int idx_pos = 0; // build index for file: - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); priv->idx_size=0; diff --git a/demux/demux_asf.c b/demux/demux_asf.c index 0b8da6930f..f800e09dc3 100644 --- a/demux/demux_asf.c +++ b/demux/demux_asf.c @@ -628,7 +628,6 @@ static demuxer_t* demux_open_asf(demuxer_t* demuxer) init_priv(asf); if (!read_asf_header(demuxer,asf)) return NULL; - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); // demuxer->idx_pos=0; // demuxer->endpos=avi_header.movi_end; diff --git a/demux/demux_avi.c b/demux/demux_avi.c index daf542bfac..a07f022cde 100644 --- a/demux/demux_avi.c +++ b/demux/demux_avi.c @@ -456,7 +456,6 @@ static demuxer_t* demux_open_avi(demuxer_t* demuxer){ demuxer->video->id=-1; // autodetect } - stream_reset(demuxer->stream); stream_seek(demuxer->stream,demuxer->movi_start); if(priv->idx_size>1){ // decide index format: diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index efe8edd43c..53f583570f 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -143,7 +143,6 @@ static int64_t mp_seek(void *opaque, int64_t pos, int whence) return -1; current_pos = stream_tell(stream); if (stream_seek(stream, pos) == 0) { - stream_reset(stream); stream_seek(stream, current_pos); return -1; } diff --git a/demux/demux_ts.c b/demux/demux_ts.c index 8b2a2d84ba..a16891907d 100644 --- a/demux/demux_ts.c +++ b/demux/demux_ts.c @@ -470,7 +470,6 @@ static int ts_check_file(demuxer_t * demuxer) if(_read < buf_size-1) { mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n"); - stream_reset(demuxer->stream); return 0; } @@ -992,9 +991,6 @@ static demuxer_t *demux_open_ts(demuxer_t * demuxer) demuxer->type= DEMUXER_TYPE_MPEG_TS; demuxer->ts_resets_possible = true; - - stream_reset(demuxer->stream); - packet_size = ts_check_file(demuxer); if(!packet_size) return NULL; @@ -1079,7 +1075,6 @@ static demuxer_t *demux_open_ts(demuxer_t * demuxer) 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? -- cgit v1.2.3 From 5999efb96478cefa33cf61e3ce2c9d872365cec6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Jun 2013 20:40:05 +0200 Subject: stream: fix some aspects of EOF handling The stream EOF flag should only be set when trying to read past the end of the file (relatively similar to unix files). Always clear the EOF flag on seeking. Trying to set it "properly" (depending whether data is available at seek destination or not) might be an ok idea, but would require attention to too many special cases. I suspect before this commit (and in MPlayer etc. too), the EOF flag wasn't handled consistently when the stream position was at the end of the file. Fix one special case in ebml.c and stream_skip(): this function couldn't distinguish between at-EOF and past-EOF either. --- demux/ebml.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'demux') diff --git a/demux/ebml.c b/demux/ebml.c index 52332cd0c5..98ab1ef306 100644 --- a/demux/ebml.c +++ b/demux/ebml.c @@ -308,11 +308,10 @@ int ebml_read_skip_or_resync_cluster(stream_t *s, uint64_t *length) *length = len + l; int64_t pos = stream_tell(s); - stream_skip(s, len); // When reading corrupted elements, len will often be a random high number, - // and stream_skip() will set EOF. - if (s->eof) { + // and stream_skip() will fail when skipping past EOF. + if (!stream_skip(s, len)) { stream_seek(s, pos); goto resync; } -- cgit v1.2.3