--- libavformat/isom.h | 10 ++++++ libavformat/mov.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++--- libavformat/utils.c | 3 +- 3 files changed, 99 insertions(+), 6 deletions(-)
diff --git a/libavformat/isom.h b/libavformat/isom.h index 65676fb0f5..646b31ccc7 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -137,11 +137,19 @@ typedef struct MOVIndexRange { int64_t end; } MOVIndexRange; +typedef struct MOVIndexEntry { +#define MOVINDEX_DISPOSABLE 0x01 + int8_t flags; +} MOVIndexEntry; + typedef struct MOVStreamContext { AVIOContext *pb; int pb_is_copied; int ffindex; ///< AVStream index int next_chunk; + MOVIndexEntry * mov_index_entries; + int nb_mov_index_entries; + unsigned int mov_index_allocated_size; unsigned int chunk_count; int64_t *chunk_offsets; unsigned int stts_count; @@ -166,6 +174,8 @@ typedef struct MOVStreamContext { int keyframe_absent; unsigned int keyframe_count; int *keyframes; + unsigned int frame_deps_count; + int *frame_deps; int time_scale; int64_t time_offset; ///< time offset of the edit list entries int current_sample; diff --git a/libavformat/mov.c b/libavformat/mov.c index f7fab98dd8..2bb81d8f01 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2682,6 +2682,43 @@ static int mov_read_stps(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + MOVStreamContext *sc; + unsigned int i, entries; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + sc = st->priv_data; + + if (atom.size < 8) + return 0; + + avio_r8(pb); /* version */ + avio_rb24(pb); /* flags */ + + entries = atom.size - 4; + sc->frame_deps_count = 0; + sc->frame_deps = av_malloc_array(entries, sizeof(*sc->frame_deps)); + + if (!sc->frame_deps) + return AVERROR(ENOMEM); + + for (i = 0; i < entries && !pb->eof_reached; i++) { + sc->frame_deps[i] = avio_r8(pb); + } + + sc->frame_deps_count = i; + + if (pb->eof_reached) + return AVERROR_EOF; + + + return 0; +} + static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -3638,15 +3675,40 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (!sc->sample_count || st->nb_index_entries) return; - if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries) + if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries)) return; - if (av_reallocp_array(&st->index_entries, - st->nb_index_entries + sc->sample_count, + if (av_reallocp_array(&st->index_entries, sc->sample_count, sizeof(*st->index_entries)) < 0) { st->nb_index_entries = 0; return; } - st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries); + st->index_entries_allocated_size = sc->sample_count * + sizeof(*st->index_entries); + + // realloc mov_index_entries if needed for frame dependencies + // or if it already exists for ctts + if (sc->frame_deps || sc->mov_index_entries) { + // make mov_index_entries the same number of entries as + // index_entries + if (av_reallocp_array(&sc->mov_index_entries, + sc->sample_count, + sizeof(*sc->mov_index_entries)) < 0) { + sc->nb_mov_index_entries = 0; + return; + } + sc->mov_index_allocated_size = sc->sample_count * + sizeof(*sc->mov_index_entries); + + if (sc->sample_count > sc->nb_mov_index_entries) + // In case there were samples without ctts entries, ensure they + // get zero valued entries. This ensures clips which mix boxes + // with and without ctts entries don't pickup uninitialized + // data. + memset(sc->mov_index_entries + sc->nb_mov_index_entries, 0, + (sc->sample_count - sc->nb_mov_index_entries) * + sizeof(*sc->mov_index_entries)); + sc->nb_mov_index_entries = sc->sample_count; + } if (ctts_data_old) { // Expand ctts entries such that we have a 1-1 mapping with samples @@ -3689,10 +3751,14 @@ static void mov_build_index(MOVContext *mov, AVStream *st) for (j = 0; j < sc->stsc_data[stsc_index].count; j++) { int keyframe = 0; + int disposable = 0; if (current_sample >= sc->sample_count) { av_log(mov->fc, AV_LOG_ERROR, "wrong sample count\n"); return; } + if (sc->frame_deps && current_sample < sc->frame_deps_count) + disposable = ((sc->frame_deps[current_sample] >> 2) & 3) == + MOV_SAMPLE_DEPENDENCY_NO; if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) { keyframe = 1; @@ -3722,16 +3788,22 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (sc->pseudo_stream_id == -1 || sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) { AVIndexEntry *e; + MOVIndexEntry *me; if (sample_size > 0x3FFFFFFF) { av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size); return; } - e = &st->index_entries[st->nb_index_entries++]; + e = &st->index_entries[st->nb_index_entries]; e->pos = current_offset; e->timestamp = current_dts; e->size = sample_size; e->min_distance = distance; e->flags = keyframe ? AVINDEX_KEYFRAME : 0; + if (sc->mov_index_entries) { + me = &sc->mov_index_entries[st->nb_index_entries]; + me->flags = disposable ? MOVINDEX_DISPOSABLE : 0; + } + st->nb_index_entries++; av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", " "size %u, distance %u, keyframe %d\n", st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe); @@ -4098,6 +4170,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_freep(&sc->chunk_offsets); av_freep(&sc->sample_sizes); av_freep(&sc->keyframes); + av_freep(&sc->frame_deps); av_freep(&sc->stts_data); av_freep(&sc->stps_data); av_freep(&sc->elst_data); @@ -5975,6 +6048,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('s','t','s','c'), mov_read_stsc }, { MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */ { MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */ +{ MKTAG('s','d','t','p'), mov_read_sdtp }, /* sample dependencies */ { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */ { MKTAG('s','t','t','s'), mov_read_stts }, { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */ @@ -6407,6 +6481,7 @@ static int mov_read_close(AVFormatContext *s) continue; av_freep(&sc->ctts_data); + av_freep(&sc->mov_index_entries); for (j = 0; j < sc->drefs_count; j++) { av_freep(&sc->drefs[j].path); av_freep(&sc->drefs[j].dir); @@ -6423,6 +6498,7 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->stsc_data); av_freep(&sc->sample_sizes); av_freep(&sc->keyframes); + av_freep(&sc->frame_deps); av_freep(&sc->stts_data); av_freep(&sc->stps_data); av_freep(&sc->elst_data); @@ -6912,6 +6988,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) MOVContext *mov = s->priv_data; MOVStreamContext *sc; AVIndexEntry *sample; + MOVIndexEntry *movsample = NULL; AVStream *st = NULL; int64_t current_index; int ret; @@ -6926,6 +7003,8 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) goto retry; } sc = st->priv_data; + if (sc->current_sample < sc->nb_mov_index_entries) + movsample = &sc->mov_index_entries[sc->current_sample]; /* must be done just before reading, to avoid infinite loop on sample */ current_index = sc->current_index; mov_current_sample_inc(sc); @@ -7008,6 +7087,9 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) if (st->discard == AVDISCARD_ALL) goto retry; pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0; + if (movsample) + pkt->flags |= movsample->flags & MOVINDEX_DISPOSABLE ? + AV_PKT_FLAG_DISPOSABLE : 0; pkt->pos = sample->pos; /* Multiple stsd handling. */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 84e49208b8..816f963b5f 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1458,7 +1458,8 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) out_pkt.pts = st->parser->pts; out_pkt.dts = st->parser->dts; out_pkt.pos = st->parser->pos; - out_pkt.flags |= pkt->flags & AV_PKT_FLAG_DISCARD; + out_pkt.flags |= pkt->flags & (AV_PKT_FLAG_DISCARD | + AV_PKT_FLAG_DISPOSABLE); if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) out_pkt.pos = st->parser->frame_offset; -- 2.14.3 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel