[FFmpeg-devel] [PATCH] RTSP-MS 15/15: move packet_time_start zero value assignment in asf.c

Ronald S. Bultje rsbultje
Thu Apr 16 03:36:47 CEST 2009


Hi,

On Wed, Apr 15, 2009 at 6:24 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> so what you say is that the asf demuxer has a bug in relation to EOF handling
> ?
>
> and you want to fix that?

Oh! This is a big can of worms and you knew it!

ASF files never reach EOF, they really do loop forever! This is a ASF
packet header/data printf showing current pos / file size:

Reading ASF packet header at 13618013/13639000
Parsing ASF packet data at 13618027/13639000
Parsing ASF packet data at 13619531/13639000
Parsing ASF packet data at 13621131/13639000
Parsing ASF packet data at 13622622/13639000
Parsing ASF packet data at 13624019/13639000
Reading ASF packet header at 13624566/13639000
Parsing ASF packet data at 13624580/13639000
Parsing ASF packet data at 13626151/13639000
Parsing ASF packet data at 13627647/13639000
Reading ASF packet header at 13631119/13639000
Parsing ASF packet data at 13631132/13639000
Parsing ASF packet data at 13632630/13639000
Parsing ASF packet data at 13637672/13639000
[.. this is EOF! See below ..]
Parsing ASF packet data at 13642714/13639000
Parsing ASF packet data at 13647756/13639000
Parsing ASF packet data at 13652798/13639000

At the "[.. see below ..]" point, every round of data reading consists
just of trying to read the header, failing (because there's no data,
all get_byte() and get_l/beXX() operations and such return 0) and thus
calling url_fskip() to skip the data and try again. However,
url_fskip() is broken in that it never sets eof_reached. It calls
url_fseek(SEEK_CUR, skip_size);, which calls file_seek(), which calls
lseek(2):

     "The lseek() function allows the file offset to be set beyond the end of
     the existing end-of-file of the file."

Shit... I hate you. :-). The only calls that ever set eof_reached()
for regular files are get_buffer() or fill_buffer(), neither of which
are used in asfdec.c, at least not as long as all calls to
get_byte()/get_l/beXX() return 0. Any suggested way of fixing this?...
I'd almost introduce a call to get_buffer() just to use some call that
sets eof_reached(), but I suppose it'd be cleaner to have url_fskip()
set eof_reached when we're at EOF (in read-only streams). Agree? If
so, best thing I could think of so far is to add a check in
url_fseek() (could be placed in file_seek() also if you so prefer) to
make sure we don't go beyond EOF, see attached...

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavformat/aviobuf.c
===================================================================
--- ffmpeg-svn.orig/libavformat/aviobuf.c	2009-04-13 16:10:01.000000000 -0400
+++ ffmpeg-svn/libavformat/aviobuf.c	2009-04-15 21:32:21.000000000 -0400
@@ -159,7 +159,7 @@
             return AVERROR(EPIPE);
         s->buf_ptr = s->buf_end + offset - s->pos;
     } else {
-        int64_t res = AVERROR(EPIPE);
+        int64_t res = AVERROR(EPIPE), size;
 
 #if CONFIG_MUXERS || CONFIG_NETWORK
         if (s->write_flag) {
@@ -167,12 +167,20 @@
             s->must_flush = 1;
         }
 #endif /* CONFIG_MUXERS || CONFIG_NETWORK */
-        if (!s->seek || (res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
+        offset1 = offset;
+        if (!s->write_flag && offset > (size = url_fsize(s)))
+            offset1 = size;
+        if (!s->seek || (res = s->seek(s->opaque, offset1, SEEK_SET)) < 0)
             return res;
         if (!s->write_flag)
             s->buf_end = s->buffer;
         s->buf_ptr = s->buffer;
-        s->pos = offset;
+        s->pos = res;
+        if (res != offset) {
+            if (res < offset)
+                s->eof_reached = 1;
+            return AVERROR(EPIPE);
+        }
     }
     s->eof_reached = 0;
     return offset;



More information about the ffmpeg-devel mailing list