[FFmpeg-devel] [RFC][PATCH] avformat/flvdec: avoid reseting eof_reached to 0 silently
Zhang Rui
bbcallen at gmail.com
Wed Apr 8 17:28:30 CEST 2015
avio_feof() and avio_seek() could reset eof_reached to 0,
after some silent IO error in avio_r*(). And the reconnection
caused by seek makes demuxer to continue read at wrong position.
---
libavformat/flvdec.c | 66 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 41 insertions(+), 25 deletions(-)
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index b625c78..ae8e2fe 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -85,6 +85,22 @@ static int live_flv_probe(AVProbeData *p)
return probe(p, 1);
}
+static int64_t safe_io_seek(AVIOContext *s, int64_t offset, int whence)
+{
+ if (s->eof_reached)
+ return AVERROR_EOF;
+
+ return avio_seek(s, offset, whence);
+}
+
+static int64_t safe_io_skip(AVIOContext *s, int64_t offset)
+{
+ if (s->eof_reached)
+ return AVERROR_EOF;
+
+ return avio_skip(s, offset);
+}
+
static AVStream *create_stream(AVFormatContext *s, int codec_type)
{
AVStream *st = avformat_new_stream(s, NULL);
@@ -265,7 +281,7 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
if (vcodec->extradata)
vcodec->extradata[0] = avio_r8(s->pb);
else
- avio_skip(s->pb, 1);
+ safe_io_skip(s->pb, 1);
}
return 1; // 1 byte body size adjustment for flv_read_packet()
case FLV_CODECID_H264:
@@ -287,7 +303,7 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
{
int length = avio_rb16(ioc);
if (length >= buffsize) {
- avio_skip(ioc, length);
+ safe_io_skip(ioc, length);
return -1;
}
@@ -378,7 +394,7 @@ invalid:
finish:
av_freep(×);
av_freep(&filepositions);
- avio_seek(ioc, initial_pos, SEEK_SET);
+ safe_io_seek(ioc, initial_pos, SEEK_SET);
return ret;
}
@@ -433,7 +449,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
case AMF_DATA_TYPE_UNSUPPORTED:
break; // these take up no additional space
case AMF_DATA_TYPE_MIXEDARRAY:
- avio_skip(ioc, 4); // skip 32-bit max array index
+ safe_io_skip(ioc, 4); // skip 32-bit max array index
while (avio_tell(ioc) < max_pos - 2 &&
amf_get_string(ioc, str_val, sizeof(str_val)) > 0)
// this is the only case in which we would want a nested
@@ -458,7 +474,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
}
break;
case AMF_DATA_TYPE_DATE:
- avio_skip(ioc, 8 + 2); // timestamp (double) and UTC offset (int16)
+ safe_io_skip(ioc, 8 + 2); // timestamp (double) and UTC offset (int16)
break;
default: // unsupported type, we couldn't skip
av_log(s, AV_LOG_ERROR, "unsupported amf type %d\n", amf_type);
@@ -603,7 +619,7 @@ static int flv_read_header(AVFormatContext *s)
{
int offset, flags;
- avio_skip(s->pb, 4);
+ safe_io_skip(s->pb, 4);
flags = avio_r8(s->pb);
s->ctx_flags |= AVFMTCTX_NOHEADER;
@@ -618,8 +634,8 @@ static int flv_read_header(AVFormatContext *s)
// create that stream if it's encountered.
offset = avio_rb32(s->pb);
- avio_seek(s->pb, offset, SEEK_SET);
- avio_skip(s->pb, 4);
+ safe_io_seek(s->pb, offset, SEEK_SET);
+ safe_io_skip(s->pb, 4);
s->start_time = 0;
@@ -678,13 +694,13 @@ static int amf_skip_tag(AVIOContext *pb, AMFDataType type)
switch (type) {
case AMF_DATA_TYPE_NUMBER:
- avio_skip(pb, 8);
+ safe_io_skip(pb, 8);
break;
case AMF_DATA_TYPE_BOOL:
- avio_skip(pb, 1);
+ safe_io_skip(pb, 1);
break;
case AMF_DATA_TYPE_STRING:
- avio_skip(pb, avio_rb16(pb));
+ safe_io_skip(pb, avio_rb16(pb));
break;
case AMF_DATA_TYPE_ARRAY:
parse_name = 0;
@@ -695,10 +711,10 @@ static int amf_skip_tag(AVIOContext *pb, AMFDataType type)
if (parse_name) {
int size = avio_rb16(pb);
if (!size) {
- avio_skip(pb, 1);
+ safe_io_skip(pb, 1);
break;
}
- avio_skip(pb, size);
+ safe_io_skip(pb, size);
}
if ((ret = amf_skip_tag(pb, avio_r8(pb))) < 0)
return ret;
@@ -727,7 +743,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
case AMF_DATA_TYPE_ARRAY:
array = 1;
case AMF_DATA_TYPE_MIXEDARRAY:
- avio_seek(pb, 4, SEEK_CUR);
+ safe_io_seek(pb, 4, SEEK_CUR);
case AMF_DATA_TYPE_OBJECT:
break;
default:
@@ -775,7 +791,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
pkt->flags |= AV_PKT_FLAG_KEY;
skip:
- avio_seek(s->pb, next + 4, SEEK_SET);
+ safe_io_seek(s->pb, next + 4, SEEK_SET);
return ret;
}
@@ -792,16 +808,16 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *st = NULL;
/* pkt size is repeated at end. skip it */
- for (;; avio_skip(s->pb, 4)) {
+ for (;; safe_io_skip(s->pb, 4)) {
pos = avio_tell(s->pb);
type = (avio_r8(s->pb) & 0x1F);
size = avio_rb24(s->pb);
dts = avio_rb24(s->pb);
dts |= avio_r8(s->pb) << 24;
av_dlog(s, "type:%d, size:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, dts, avio_tell(s->pb));
- if (avio_feof(s->pb))
+ if (s->pb->eof_reached || avio_feof(s->pb))
return AVERROR_EOF;
- avio_skip(s->pb, 3); /* stream id, always 0 */
+ safe_io_skip(s->pb, 3); /* stream id, always 0 */
flags = 0;
if (flv->validate_next < flv->validate_count) {
@@ -849,14 +865,14 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
} else if (type == TYPE_ONCAPTION) {
return flv_data_packet(s, pkt, dts, next);
}
- avio_seek(s->pb, meta_pos, SEEK_SET);
+ safe_io_seek(s->pb, meta_pos, SEEK_SET);
}
} else {
av_log(s, AV_LOG_DEBUG,
"Skipping flv packet: type %d, size %d, flags %d.\n",
type, size, flags);
skip:
- avio_seek(s->pb, next, SEEK_SET);
+ safe_io_seek(s->pb, next, SEEK_SET);
continue;
}
@@ -898,7 +914,7 @@ skip:
||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO)))
|| st->discard >= AVDISCARD_ALL
) {
- avio_seek(s->pb, next, SEEK_SET);
+ safe_io_seek(s->pb, next, SEEK_SET);
continue;
}
break;
@@ -913,11 +929,11 @@ skip:
// previous FLV tag. Use the timestamp of its payload as duration.
int64_t fsize = avio_size(s->pb);
retry_duration:
- avio_seek(s->pb, fsize - 4, SEEK_SET);
+ safe_io_seek(s->pb, fsize - 4, SEEK_SET);
size = avio_rb32(s->pb);
// Seek to the start of the last FLV tag at position (fsize - 4 - size)
// but skip the byte indicating the type.
- avio_seek(s->pb, fsize - 3 - size, SEEK_SET);
+ safe_io_seek(s->pb, fsize - 3 - size, SEEK_SET);
if (size == avio_rb24(s->pb) + 11) {
uint32_t ts = avio_rb24(s->pb);
ts |= avio_r8(s->pb) << 24;
@@ -929,7 +945,7 @@ retry_duration:
}
}
- avio_seek(s->pb, pos, SEEK_SET);
+ safe_io_seek(s->pb, pos, SEEK_SET);
flv->searched_for_end = 1;
}
@@ -1063,7 +1079,7 @@ retry_duration:
pkt->flags |= AV_PKT_FLAG_KEY;
leave:
- avio_skip(s->pb, 4);
+ safe_io_skip(s->pb, 4);
return ret;
}
--
2.0.0
More information about the ffmpeg-devel
mailing list