summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Bœsch <u@pkh.me>2022-02-18 22:55:13 +0100
committerClément Bœsch <u@pkh.me>2022-03-04 15:50:51 +0100
commite05e4398c39b2dafbec748fcd82dcb8709956ed4 (patch)
treebeeeb2c7a675c8677ffde517cd4bb36f23be9ee7
parenteb947471b245d0c2563c057fca5d1a18e57b3643 (diff)
avformat/mov: add parsing for the sgpd sync box
sgpd means Sample Group Description Box. For now, only the sync grouping type is parsed, but the function can easily be adjusted to support other flavours. The sbgp (Sample to Group Box) sync_group table built in previous commit contains references to this table through the group_description_index field.
-rw-r--r--libavformat/isom.h2
-rw-r--r--libavformat/mov.c59
2 files changed, 61 insertions, 0 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h
index e326f4f27f..bbe395ee4b 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -220,6 +220,8 @@ typedef struct MOVStreamContext {
MOVSbgp *rap_group;
unsigned int sync_group_count;
MOVSbgp *sync_group;
+ uint8_t *sgpd_sync;
+ uint32_t sgpd_sync_count;
int nb_frames_for_fps;
int64_t duration_for_fps;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6221bb0490..3127bdf23d 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -3130,6 +3130,62 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
+static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ MOVStreamContext *sc;
+ uint8_t version;
+ uint32_t grouping_type;
+ uint32_t default_length;
+ av_unused uint32_t default_group_description_index;
+ uint32_t entry_count;
+
+ 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);
+
+ /*
+ * This function only supports "sync" boxes, but the code is able to parse
+ * other boxes (such as "tscl", "tsas" and "stsa")
+ */
+ if (grouping_type != MKTAG('s','y','n','c'))
+ return 0;
+
+ default_length = version >= 1 ? avio_rb32(pb) : 0;
+ default_group_description_index = version >= 2 ? avio_rb32(pb) : 0;
+ entry_count = avio_rb32(pb);
+
+ av_freep(&sc->sgpd_sync);
+ sc->sgpd_sync_count = entry_count;
+ sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync));
+ if (!sc->sgpd_sync)
+ return AVERROR(ENOMEM);
+
+ for (uint32_t i = 0; i < entry_count && !pb->eof_reached; i++) {
+ uint32_t description_length = default_length;
+ if (version >= 1 && default_length == 0)
+ description_length = avio_rb32(pb);
+ if (grouping_type == MKTAG('s','y','n','c')) {
+ const uint8_t nal_unit_type = avio_r8(pb) & 0x3f;
+ sc->sgpd_sync[i] = nal_unit_type;
+ description_length -= 1;
+ }
+ avio_skip(pb, description_length);
+ }
+
+ if (pb->eof_reached) {
+ av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n");
+ return AVERROR_EOF;
+ }
+
+ return 0;
+}
+
static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
AVStream *st;
@@ -4375,6 +4431,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
av_freep(&sc->elst_data);
av_freep(&sc->rap_group);
av_freep(&sc->sync_group);
+ av_freep(&sc->sgpd_sync);
return 0;
}
@@ -7255,6 +7312,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','g','p','d'), mov_read_sgpd },
{ MKTAG('s','b','g','p'), mov_read_sbgp },
{ MKTAG('h','v','c','C'), mov_read_glbl },
{ MKTAG('u','u','i','d'), mov_read_uuid },
@@ -7715,6 +7773,7 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&sc->elst_data);
av_freep(&sc->rap_group);
av_freep(&sc->sync_group);
+ av_freep(&sc->sgpd_sync);
av_freep(&sc->display_matrix);
av_freep(&sc->index_ranges);