[FFmpeg-devel] [PATCH] libavformat/matroskadec: Add support for chapter segment UUID and edition UID

Alexander Westberg-Bladh alexander.bladh at gmail.com
Fri Apr 4 12:24:05 EEST 2025


This adds support for parsing ChapterSegmentUID and ChapterSegmentEditionUID
elements in Matroska chapters. These elements are used in ordered chapters
to reference external files see #3123.

Signed-off-by: Alexander Westberg-Bladh <alexander.bladh at gmail.com>
---
 libavformat/matroska.h    |  3 +++
 libavformat/matroskadec.c | 32 ++++++++++++++++++++------------
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 719f2ef796..5f617aa287 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -275,6 +275,9 @@
 #define MATROSKA_ID_CHAPTERFLAGENABLED  0x4598
 #define MATROSKA_ID_CHAPTERPHYSEQUIV    0x63C3
 
+#define MATROSKA_ID_CHAPTERSEGMENTUID         0x6E67
+#define MATROSKA_ID_CHAPTERSEGMENTEDITIONUID  0x6EBC
+
 typedef enum {
   MATROSKA_TRACK_TYPE_NONE     = 0x0,
   MATROSKA_TRACK_TYPE_VIDEO    = 0x1,
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index d4b7ae112c..e5c6eb74e2 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -312,6 +312,8 @@ typedef struct MatroskaChapter {
     uint64_t end;
     uint64_t uid;
     char    *title;
+    EbmlBin  segment_uid;
+    uint64_t segment_edition_uid;
 
     AVChapter *chapter;
 } MatroskaChapter;
@@ -438,6 +440,10 @@ typedef struct MatroskaDemuxContext {
 
     /* Bandwidth value for WebM DASH Manifest */
     int bandwidth;
+
+    /* Ordered chapters flag */
+    int ordered_chapters;
+    int segment_uid;
 } MatroskaDemuxContext;
 
 #define CHILD_OF(parent) { .def = { .n = parent } }
@@ -475,9 +481,9 @@ static EbmlSyntax matroska_info[] = {
     { MATROSKA_ID_DURATION,      EBML_FLOAT, 0, 0, offsetof(MatroskaDemuxContext, duration) },
     { MATROSKA_ID_TITLE,         EBML_UTF8,  0, 0, offsetof(MatroskaDemuxContext, title) },
     { MATROSKA_ID_WRITINGAPP,    EBML_NONE },
-    { MATROSKA_ID_MUXINGAPP,     EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, muxingapp) },
-    { MATROSKA_ID_DATEUTC,       EBML_BIN,  0, 0, offsetof(MatroskaDemuxContext, date_utc) },
-    { MATROSKA_ID_SEGMENTUID,    EBML_NONE },
+    { MATROSKA_ID_MUXINGAPP,     EBML_UTF8,  0, 0, offsetof(MatroskaDemuxContext, muxingapp) },
+    { MATROSKA_ID_DATEUTC,       EBML_BIN,   0, 0, offsetof(MatroskaDemuxContext, date_utc) },
+    { MATROSKA_ID_SEGMENTUID,    EBML_BIN,   0, 0, offsetof(MatroskaDemuxContext, segment_uid) },
     CHILD_OF(matroska_segment)
 };
 
@@ -669,14 +675,16 @@ static EbmlSyntax matroska_chapter_display[] = {
 };
 
 static EbmlSyntax matroska_chapter_entry[] = {
-    { MATROSKA_ID_CHAPTERTIMESTART,   EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } },
-    { MATROSKA_ID_CHAPTERTIMEEND,     EBML_UINT, 0, 0, offsetof(MatroskaChapter, end),   { .u = AV_NOPTS_VALUE } },
-    { MATROSKA_ID_CHAPTERUID,         EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) },
-    { MATROSKA_ID_CHAPTERDISPLAY,     EBML_NEST, 0, 0,                        0,         { .n = matroska_chapter_display } },
-    { MATROSKA_ID_CHAPTERFLAGHIDDEN,  EBML_NONE },
-    { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE },
-    { MATROSKA_ID_CHAPTERPHYSEQUIV,   EBML_NONE },
-    { MATROSKA_ID_CHAPTERATOM,        EBML_NONE },
+    { MATROSKA_ID_CHAPTERTIMESTART,         EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } },
+    { MATROSKA_ID_CHAPTERTIMEEND,           EBML_UINT, 0, 0, offsetof(MatroskaChapter, end),   { .u = AV_NOPTS_VALUE } },
+    { MATROSKA_ID_CHAPTERUID,               EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) },
+    { MATROSKA_ID_CHAPTERSEGMENTUID,        EBML_BIN,  0, 0, offsetof(MatroskaChapter, segment_uid) },
+    { MATROSKA_ID_CHAPTERSEGMENTEDITIONUID, EBML_UINT, 0, 0, offsetof(MatroskaChapter, segment_edition_uid) },
+    { MATROSKA_ID_CHAPTERDISPLAY,           EBML_NEST, 0, 0,                        0,         { .n = matroska_chapter_display } },
+    { MATROSKA_ID_CHAPTERFLAGHIDDEN,        EBML_NONE },
+    { MATROSKA_ID_CHAPTERFLAGENABLED,       EBML_NONE },
+    { MATROSKA_ID_CHAPTERPHYSEQUIV,         EBML_NONE },
+    { MATROSKA_ID_CHAPTERATOM,              EBML_NONE },
     CHILD_OF(matroska_chapter)
 };
 
@@ -685,7 +693,7 @@ static EbmlSyntax matroska_chapter[] = {
     { MATROSKA_ID_EDITIONUID,         EBML_NONE },
     { MATROSKA_ID_EDITIONFLAGHIDDEN,  EBML_NONE },
     { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE },
-    { MATROSKA_ID_EDITIONFLAGORDERED, EBML_NONE },
+    { MATROSKA_ID_EDITIONFLAGORDERED, EBML_UINT, 0, 0, offsetof(MatroskaDemuxContext, ordered_chapters) },
     CHILD_OF(matroska_chapters)
 };
 
-- 
2.48.1



More information about the ffmpeg-devel mailing list