mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-08 16:54:03 +02:00
flvdec: Validate index entries added from metadata while reading
By validating the index entries while reading, we don't need to seek at startup to validate the entries. If the error in the index entries is not pointing to (our definition of) the start of packets, and there is an index entry pointing at some of the first packets after the metadata, the invalid index can be discarded almost immediately. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
1a6b9a98ce
commit
7e297a46db
@ -39,12 +39,20 @@
|
|||||||
#define KEYFRAMES_TIMESTAMP_TAG "times"
|
#define KEYFRAMES_TIMESTAMP_TAG "times"
|
||||||
#define KEYFRAMES_BYTEOFFSET_TAG "filepositions"
|
#define KEYFRAMES_BYTEOFFSET_TAG "filepositions"
|
||||||
|
|
||||||
|
#define VALIDATE_INDEX_TS_THRESH 2500
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int wrong_dts; ///< wrong dts due to negative cts
|
int wrong_dts; ///< wrong dts due to negative cts
|
||||||
uint8_t *new_extradata[2];
|
uint8_t *new_extradata[2];
|
||||||
int new_extradata_size[2];
|
int new_extradata_size[2];
|
||||||
int last_sample_rate;
|
int last_sample_rate;
|
||||||
int last_channels;
|
int last_channels;
|
||||||
|
struct {
|
||||||
|
int64_t dts;
|
||||||
|
int64_t pos;
|
||||||
|
} validate_index[2];
|
||||||
|
int validate_next;
|
||||||
|
int validate_count;
|
||||||
} FLVContext;
|
} FLVContext;
|
||||||
|
|
||||||
static int flv_probe(AVProbeData *p)
|
static int flv_probe(AVProbeData *p)
|
||||||
@ -137,6 +145,7 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream *vstream, int64_t max_pos) {
|
static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream *vstream, int64_t max_pos) {
|
||||||
|
FLVContext *flv = s->priv_data;
|
||||||
unsigned int arraylen = 0, timeslen = 0, fileposlen = 0, i;
|
unsigned int arraylen = 0, timeslen = 0, fileposlen = 0, i;
|
||||||
double num_val;
|
double num_val;
|
||||||
char str_val[256];
|
char str_val[256];
|
||||||
@ -206,11 +215,17 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret && timeslen == fileposlen)
|
if (!ret && timeslen == fileposlen) {
|
||||||
for (i = 0; i < fileposlen; i++)
|
for (i = 0; i < fileposlen; i++) {
|
||||||
av_add_index_entry(vstream, filepositions[i], times[i]*1000,
|
av_add_index_entry(vstream, filepositions[i], times[i]*1000,
|
||||||
0, 0, AVINDEX_KEYFRAME);
|
0, 0, AVINDEX_KEYFRAME);
|
||||||
else
|
if (i < 2) {
|
||||||
|
flv->validate_index[i].pos = filepositions[i];
|
||||||
|
flv->validate_index[i].dts = times[i] * 1000;
|
||||||
|
flv->validate_count = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
|
av_log(s, AV_LOG_WARNING, "Invalid keyframes object, skipping.\n");
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
@ -434,6 +449,22 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clear_index_entries(AVFormatContext *s, int64_t pos)
|
||||||
|
{
|
||||||
|
int i, j, out;
|
||||||
|
av_log(s, AV_LOG_WARNING, "Found invalid index entries, clearing the index.\n");
|
||||||
|
for (i = 0; i < s->nb_streams; i++) {
|
||||||
|
AVStream *st = s->streams[i];
|
||||||
|
/* Remove all index entries that point to >= pos */
|
||||||
|
out = 0;
|
||||||
|
for (j = 0; j < st->nb_index_entries; j++) {
|
||||||
|
if (st->index_entries[j].pos < pos)
|
||||||
|
st->index_entries[out++] = st->index_entries[j];
|
||||||
|
}
|
||||||
|
st->nb_index_entries = out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -455,6 +486,22 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
avio_skip(s->pb, 3); /* stream id, always 0 */
|
avio_skip(s->pb, 3); /* stream id, always 0 */
|
||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
||||||
|
if (flv->validate_next < flv->validate_count) {
|
||||||
|
int64_t validate_pos = flv->validate_index[flv->validate_next].pos;
|
||||||
|
if (pos == validate_pos) {
|
||||||
|
if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <=
|
||||||
|
VALIDATE_INDEX_TS_THRESH) {
|
||||||
|
flv->validate_next++;
|
||||||
|
} else {
|
||||||
|
clear_index_entries(s, validate_pos);
|
||||||
|
flv->validate_count = 0;
|
||||||
|
}
|
||||||
|
} else if (pos > validate_pos) {
|
||||||
|
clear_index_entries(s, validate_pos);
|
||||||
|
flv->validate_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -633,6 +680,8 @@ leave:
|
|||||||
static int flv_read_seek(AVFormatContext *s, int stream_index,
|
static int flv_read_seek(AVFormatContext *s, int stream_index,
|
||||||
int64_t ts, int flags)
|
int64_t ts, int flags)
|
||||||
{
|
{
|
||||||
|
FLVContext *flv = s->priv_data;
|
||||||
|
flv->validate_count = 0;
|
||||||
return avio_seek_time(s->pb, stream_index, ts, flags);
|
return avio_seek_time(s->pb, stream_index, ts, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user