# HG changeset patch # User aurel # Date 1219622948 0 # Node ID 2533332ca75236dd99a2eb9ddc4ee121fe2a5a1f # Parent 7814581e98ff4c5c13052d4a41743d6f72aa918a 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 diff -r 7814581e98ff -r 2533332ca752 matroskadec.c --- a/matroskadec.c Sun Aug 24 23:57:29 2008 +0000 +++ b/matroskadec.c Mon Aug 25 00:09:08 2008 +0000 @@ -204,6 +204,7 @@ AVPacket **packets; int num_packets; + AVStream *vstream; int done; int has_cluster_id; @@ -1270,6 +1271,7 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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; inb_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;