diff options
author | Yusuke Nakamura <muken.the.vfrmaniac@gmail.com> | 2012-04-24 08:51:29 +0900 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2012-09-19 20:34:15 +0200 |
commit | d17d0ec8c2b432f0b680737de0b2aa03f2d4dd8d (patch) | |
tree | 9903e8ff82e6719cdfa08335e0bc90d517c0eb8b | |
parent | 7d8431004a236c7f3ea600753989fad11fd2d6df (diff) | |
download | ffmpeg-d17d0ec8c2b432f0b680737de0b2aa03f2d4dd8d.tar.gz |
mov: support random access point grouping
Frames described by this grouping are the starter of a closed or
an open GOP.
This is useful for open GOP of H.264 stream which is not described
by sync sample atom.
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
-rw-r--r-- | libavformat/isom.h | 7 | ||||
-rw-r--r-- | libavformat/mov.c | 53 |
2 files changed, 60 insertions, 0 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h index a766326082..b191699711 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -87,6 +87,11 @@ typedef struct { unsigned flags; } MOVTrackExt; +typedef struct { + unsigned int count; + unsigned int index; +} MOVSbgp; + typedef struct MOVStreamContext { AVIOContext *pb; int ffindex; ///< AVStream index @@ -128,6 +133,8 @@ typedef struct MOVStreamContext { int has_palette; int64_t data_size; int64_t track_end; ///< used for dts generation in fragmented movie files + unsigned int rap_group_count; + MOVSbgp *rap_group; } MOVStreamContext; typedef struct MOVContext { diff --git a/libavformat/mov.c b/libavformat/mov.c index 56a075e0b0..63049f559f 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1736,6 +1736,46 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + MOVStreamContext *sc; + unsigned int i, entries; + uint8_t version; + uint32_t grouping_type; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + sc = st->priv_data; + + version = avio_r8(pb); /* version */ + avio_rb24(pb); /* flags */ + grouping_type = avio_rl32(pb); + if (grouping_type != MKTAG( 'r','a','p',' ')) + return 0; /* only support 'rap ' grouping */ + if (version == 1) + avio_rb32(pb); /* grouping_type_parameter */ + + entries = avio_rb32(pb); + if (!entries) + return 0; + if (entries >= UINT_MAX / sizeof(*sc->rap_group)) + return AVERROR_INVALIDDATA; + sc->rap_group = av_malloc(entries * sizeof(*sc->rap_group)); + if (!sc->rap_group) + return AVERROR(ENOMEM); + + for (i = 0; i < entries && !pb->eof_reached; i++) { + sc->rap_group[i].count = avio_rb32(pb); /* sample_count */ + sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */ + } + + sc->rap_group_count = i; + + return pb->eof_reached ? AVERROR_EOF : 0; +} + static void mov_build_index(MOVContext *mov, AVStream *st) { MOVStreamContext *sc = st->priv_data; @@ -1770,6 +1810,9 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int stts_sample = 0; unsigned int sample_size; unsigned int distance = 0; + unsigned int rap_group_index = 0; + unsigned int rap_group_sample = 0; + int rap_group_present = sc->rap_group_count && sc->rap_group; int key_off = (sc->keyframes && sc->keyframes[0] > 0) || (sc->stps_data && sc->stps_data[0] > 0); current_dts -= sc->dts_shift; @@ -1805,6 +1848,14 @@ static void mov_build_index(MOVContext *mov, AVStream *st) if (stps_index + 1 < sc->stps_count) stps_index++; } + if (rap_group_present && rap_group_index < sc->rap_group_count) { + if (sc->rap_group[rap_group_index].index > 0) + keyframe = 1; + if (++rap_group_sample == sc->rap_group[rap_group_index].count) { + rap_group_sample = 0; + rap_group_index++; + } + } if (keyframe) distance = 0; sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample]; @@ -2054,6 +2105,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_freep(&sc->keyframes); av_freep(&sc->stts_data); av_freep(&sc->stps_data); + av_freep(&sc->rap_group); return 0; } @@ -2497,6 +2549,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','m','o','v'), mov_read_cmov }, { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */ { MKTAG('d','v','c','1'), mov_read_dvc1 }, +{ MKTAG('s','b','g','p'), mov_read_sbgp }, { 0, NULL } }; |