Commit cbbd906b authored by Michael Niedermayer's avatar Michael Niedermayer

avformat/flvdec: Check that sizes match and resync if not

Signed-off-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent e01ad950
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#define VALIDATE_INDEX_TS_THRESH 2500 #define VALIDATE_INDEX_TS_THRESH 2500
#define RESYNC_BUFFER_SIZE (1<<20)
typedef struct FLVContext { typedef struct FLVContext {
const AVClass *class; ///< Class for private options. const AVClass *class; ///< Class for private options.
int trust_metadata; ///< configure streams according onMetaData int trust_metadata; ///< configure streams according onMetaData
...@@ -54,6 +56,8 @@ typedef struct FLVContext { ...@@ -54,6 +56,8 @@ typedef struct FLVContext {
int validate_next; int validate_next;
int validate_count; int validate_count;
int searched_for_end; int searched_for_end;
uint8_t resync_buffer[2*RESYNC_BUFFER_SIZE];
} FLVContext; } FLVContext;
static int probe(AVProbeData *p, int live) static int probe(AVProbeData *p, int live)
...@@ -790,6 +794,36 @@ skip: ...@@ -790,6 +794,36 @@ skip:
return ret; return ret;
} }
static int resync(AVFormatContext *s)
{
FLVContext *flv = s->priv_data;
int64_t i;
int64_t pos = avio_tell(s->pb);
for (i=0; !avio_feof(s->pb); i++) {
int j = i & (RESYNC_BUFFER_SIZE-1);
int j1 = j + RESYNC_BUFFER_SIZE;
flv->resync_buffer[j ] =
flv->resync_buffer[j1] = avio_r8(s->pb);
if (i > 22) {
unsigned lsize2 = AV_RB32(flv->resync_buffer + j1 - 4);
if (lsize2 >= 11 && lsize2 + 8LL < FFMIN(i, RESYNC_BUFFER_SIZE)) {
unsigned size2 = AV_RB24(flv->resync_buffer + j1 - lsize2 + 1 - 4);
unsigned lsize1 = AV_RB32(flv->resync_buffer + j1 - lsize2 - 8);
if (lsize1 >= 11 && lsize1 + 8LL + lsize2 < FFMIN(i, RESYNC_BUFFER_SIZE)) {
unsigned size1 = AV_RB24(flv->resync_buffer + j1 - lsize1 + 1 - lsize2 - 8);
if (size1 == lsize1 - 11 && size2 == lsize2 - 11) {
avio_seek(s->pb, pos + i - lsize1 - lsize2 - 8, SEEK_SET);
return 1;
}
}
}
}
}
return AVERROR_EOF;
}
static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{ {
FLVContext *flv = s->priv_data; FLVContext *flv = s->priv_data;
...@@ -802,11 +836,14 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -802,11 +836,14 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
int av_uninit(sample_rate); int av_uninit(sample_rate);
AVStream *st = NULL; AVStream *st = NULL;
int last = -1; int last = -1;
int orig_size;
retry:
/* pkt size is repeated at end. skip it */ /* pkt size is repeated at end. skip it */
for (;; last = avio_rb32(s->pb)) { for (;; last = avio_rb32(s->pb)) {
pos = avio_tell(s->pb); pos = avio_tell(s->pb);
type = (avio_r8(s->pb) & 0x1F); type = (avio_r8(s->pb) & 0x1F);
orig_size =
size = avio_rb24(s->pb); size = avio_rb24(s->pb);
dts = avio_rb24(s->pb); dts = avio_rb24(s->pb);
dts |= avio_r8(s->pb) << 24; dts |= avio_r8(s->pb) << 24;
...@@ -1089,7 +1126,16 @@ retry_duration: ...@@ -1089,7 +1126,16 @@ retry_duration:
pkt->flags |= AV_PKT_FLAG_KEY; pkt->flags |= AV_PKT_FLAG_KEY;
leave: leave:
avio_skip(s->pb, 4); last = avio_rb32(s->pb);
if (last != orig_size + 11) {
av_log(s, AV_LOG_ERROR, "Packet mismatch %d %d\n", last, orig_size + 11);
avio_seek(s->pb, pos + 1, SEEK_SET);
ret = resync(s);
if (ret >= 0) {
av_free_packet(pkt);
goto retry;
}
}
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment