diff options
author | Aurelien Jacobs <aurel@gnuage.org> | 2008-08-25 00:09:08 +0000 |
---|---|---|
committer | Aurelien Jacobs <aurel@gnuage.org> | 2008-08-25 00:09:08 +0000 |
commit | 8bc98ba92b5c3df4180bc09393a6e3517467fe76 (patch) | |
tree | c37560aa3e7e53ff9e94c7326ca6714d8d2e8745 /libavformat/matroskadec.c | |
parent | dfbbbdc0bf94d39cbef290decefbc951a809f742 (diff) | |
download | ffmpeg-8bc98ba92b5c3df4180bc09393a6e3517467fe76.tar.gz |
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
Diffstat (limited to 'libavformat/matroskadec.c')
-rw-r--r-- | libavformat/matroskadec.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d990b58064..9ab8126aea 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -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; |