matroskadec: on the fly index construction for index-less files

each cluster that is read and that contains a video key frame is added
to the index

Originally committed as revision 14957 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Aurelien Jacobs 2008-08-25 00:09:08 +00:00
parent dfbbbdc0bf
commit 8bc98ba92b

View File

@ -204,6 +204,7 @@ typedef struct {
AVPacket **packets;
int num_packets;
AVStream *vstream;
int done;
int has_cluster_id;
@ -1270,6 +1271,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
if (!matroska->vstream) matroska->vstream = st;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_tag = track->video.fourcc;
st->codec->width = track->video.pixel_width;
@ -1390,7 +1392,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
uint64_t duration, int is_keyframe)
{
MatroskaTrack *track;
int res = 0;
int is_video_key_frame = is_keyframe, res = 0;
AVStream *st;
AVPacket *pkt;
int16_t block_time;
@ -1430,6 +1432,8 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
matroska->skip_to_keyframe = 0;
}
is_video_key_frame &= st == matroska->vstream;
switch ((flags & 0x06) >> 1) {
case 0x0: /* no lacing */
laces = 1;
@ -1592,7 +1596,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
}
av_free(lace_size);
return res;
return res < 0 ? res : is_video_key_frame;
}
static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
@ -1600,23 +1604,31 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
MatroskaCluster cluster = { 0 };
EbmlList *blocks_list;
MatroskaBlock *blocks;
int i, res;
int i, res, key_frame = 0;
offset_t pos = url_ftell(matroska->ctx->pb);
if (matroska->has_cluster_id){
/* For the first cluster we parse, its ID was already read as
part of matroska_read_header(), so don't read it again */
res = ebml_parse_id(matroska, matroska_clusters,
MATROSKA_ID_CLUSTER, &cluster);
pos -= 4; /* sizeof the ID which was already read */
matroska->has_cluster_id = 0;
} else
res = ebml_parse(matroska, matroska_clusters, &cluster);
blocks_list = &cluster.blocks;
blocks = blocks_list->elem;
for (i=0; i<blocks_list->nb_elem; i++)
if (blocks[i].bin.size > 0)
if (blocks[i].bin.size > 0) {
res=matroska_parse_block(matroska,
blocks[i].bin.data, blocks[i].bin.size,
blocks[i].bin.pos, cluster.timecode,
blocks[i].duration, !blocks[i].reference);
key_frame |= res > 0;
}
if (key_frame)
av_add_index_entry(matroska->vstream, pos,
cluster.timecode*matroska->time_scale/AV_TIME_BASE,
0, 0, AVINDEX_KEYFRAME);
ebml_free(matroska_cluster, &cluster);
if (res < 0) matroska->done = 1;
return res;