[FFmpeg-trac] #3531(undetermined:closed): ffmpeg hangs converting a possibly broken avi file
FFmpeg
trac at avcodec.org
Fri Apr 25 20:02:02 CEST 2014
#3531: ffmpeg hangs converting a possibly broken avi file
-------------------------------------+-------------------------------------
Reporter: hxuanyu | Owner:
Type: defect | Status: closed
Priority: important | Component:
Version: git-master | undetermined
Keywords: avi | Resolution: fixed
deadlock regression | Blocked By:
Blocking: | Reproduced by developer: 1
Analyzed by developer: 0 |
-------------------------------------+-------------------------------------
Comment (by DonMoir):
I ended up changing the following. I tested several avi files and it seems
to be ok. With the change, lake.avi will open in about 2 seconds with
about 350 index entries. Need someone to verify. Also, it could be
last_pos should only be set if an index is added. Does new ticket need to
be opened?
{{{
static int read_braindead_odml_indx(AVFormatContext *s, int frame_num)
{
AVIContext *avi = s->priv_data;
AVIOContext *pb = s->pb;
int longs_pre_entry = avio_rl16(pb);
int index_sub_type = avio_r8(pb);
int index_type = avio_r8(pb);
int entries_in_use = avio_rl32(pb);
int chunk_id = avio_rl32(pb);
int64_t base = avio_rl64(pb);
int stream_id = ((chunk_id & 0xFF) - '0') * 10 +
((chunk_id >> 8 & 0xFF) - '0');
AVStream *st;
AVIStream *ast;
int i;
int64_t last_pos = -1;
int64_t filesize = avi->fsize;
av_dlog(s,
"longs_pre_entry:%d index_type:%d entries_in_use:%d "
"chunk_id:%X base:%16"PRIX64"\n",
longs_pre_entry,
index_type,
entries_in_use,
chunk_id,
base);
if (stream_id >= s->nb_streams || stream_id < 0)
return AVERROR_INVALIDDATA;
st = s->streams[stream_id];
ast = st->priv_data;
if (index_sub_type)
return AVERROR_INVALIDDATA;
avio_rl32(pb);
if (index_type && longs_pre_entry != 2)
return AVERROR_INVALIDDATA;
if (index_type > 1)
return AVERROR_INVALIDDATA;
if (filesize > 0 && base >= filesize) {
av_log(s, AV_LOG_ERROR, "ODML index invalid\n");
if (base >> 32 == (base & 0xFFFFFFFF) &&
(base & 0xFFFFFFFF) < filesize &&
filesize <= 0xFFFFFFFF)
base &= 0xFFFFFFFF;
else
return AVERROR_INVALIDDATA;
}
for (i = 0; i < entries_in_use; i++) {
if (index_type) {
int64_t pos = avio_rl32(pb) + base - 8;
int len = avio_rl32(pb);
int key = len >= 0;
len &= 0x7FFFFFFF;
#ifdef DEBUG_SEEK
av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len);
#endif
if (url_feof(pb))
return AVERROR_INVALIDDATA;
if (last_pos == pos || pos == base - 8)
avi->non_interleaved = 1;
- if (last_pos != pos && (len || !ast->sample_size))
+ if (len && last_pos != pos)
av_add_index_entry(st, pos, ast->cum_len, len, 0,
key ? AVINDEX_KEYFRAME : 0);
ast->cum_len += get_duration(ast, len);
last_pos = pos;
} else {
int64_t offset, pos;
int duration;
offset = avio_rl64(pb);
avio_rl32(pb); /* size */
duration = avio_rl32(pb);
if (url_feof(pb))
return AVERROR_INVALIDDATA;
pos = avio_tell(pb);
if (avi->odml_depth > MAX_ODML_DEPTH) {
av_log(s, AV_LOG_ERROR, "Too deeply nested ODML
indexes\n");
return AVERROR_INVALIDDATA;
}
if (avio_seek(pb, offset + 8, SEEK_SET) < 0)
return -1;
avi->odml_depth++;
read_braindead_odml_indx(s, frame_num);
avi->odml_depth--;
frame_num += duration;
if (avio_seek(pb, pos, SEEK_SET) < 0) {
av_log(s, AV_LOG_ERROR, "Failed to restore position after
reading index\n");
return -1;
}
}
}
avi->index_loaded = 2;
return 0;
}
}}}
--
Ticket URL: <https://trac.ffmpeg.org/ticket/3531#comment:9>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list