@@ -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;
@@ -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;
}
@@ -7253,6 +7310,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 },
@@ -7713,6 +7771,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);