From f925ac0f65cfd312aff5c98e9c941d41f2a349af Mon Sep 17 00:00:00 2001 From: Nathan Caldwell Date: Thu, 26 Jul 2007 23:03:30 -0600 Subject: [PATCH] Chapter stuff. This is will NOT even compile, do NOT use! --- include/libmkv.h | 16 +++++++++ src/chapters.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/matroska.h | 16 ++++++++- 3 files changed, 128 insertions(+), 3 deletions(-) diff --git a/include/libmkv.h b/include/libmkv.h index fada55f..2c78b40 100644 --- a/include/libmkv.h +++ b/include/libmkv.h @@ -84,6 +84,7 @@ extern "C" { typedef struct mk_Writer_s mk_Writer; typedef struct mk_Track_s mk_Track; typedef struct mk_TrackConfig_s mk_TrackConfig; +typedef struct mk_Edition_s mk_Edition; struct mk_TrackConfig_s { uint64_t trackUID; // Optional: Unique identifier for the track. @@ -117,6 +118,21 @@ struct mk_TrackConfig_s { } audio; }; +mk_Chapter_s { + mk_Edition *edition // Edition this chapter belongs to. Do not set this yourself. + mk_Chapter *parent; // Parent of this chapter. Do not set this yourself. + mk_Context *context; // Don't change this either. + + mk_Chapter *next; + mk_Chapter *prev; + mk_Chapter **tail; + mk_Chapter *children; + +// mk_Context *chapterTrack; // Not so sure about this, yet. + mk_Context *chapterDisplay; // or this... + mk_Context *chapterProcess; // or this... +} + mk_Writer *mk_createWriter(const char *filename, int64_t timescale, uint8_t vlc_compat); /* vlc_compat writes the Seek entries at the top of the file because VLC stops parsing * * once it finds the first cluster. However, this creates extra overhead in the file. */ diff --git a/src/chapters.c b/src/chapters.c index c1f566b..4a050fe 100644 --- a/src/chapters.c +++ b/src/chapters.c @@ -28,8 +28,7 @@ int mk_createChapterSimple(mk_Writer *w, uint64_t start, uint64_t end, char *n { mk_Context *ca, *cd; - if (w->chapters == NULL) - { + if (w->chapters == NULL) { if ((w->chapters = mk_createContext(w, w->root, 0x1043a770)) == NULL) // Chapters return -1; if ((w->edition_entry = mk_createContext(w, w->chapters, 0x45b9)) == NULL) // EditionEntry @@ -54,6 +53,102 @@ int mk_createChapterSimple(mk_Writer *w, uint64_t start, uint64_t end, char *n return 0; } +/* FIXME: Don't use CHECK when we need to return a pointer! */ +mk_Edition *mk_createEdition(mk_Writer *w, uint8_t flagHidden, uint8_t flagDefault, uint8_t flagOrdered) { + mk_Edition *ed = calloc(1, sizeof(*ed)); + if (ed == NULL) + return NULL; + + if (w->chapters.context == NULL) { + if ((w->chapters.context = mk_createContext(w, w->root, 0x1043a770)) == NULL) // Chapters + return NULL; + ed->tail = calloc(1, sizeof(*mk_Edition)); + w->chapters.children = ed; + } else { + ed->tail = w->chapters.children->tail; + **(ed->tail)->next = ed; + ed->prev = *(ed->tail); + } + + *(ed->tail) = ed; + + if ((ed->context = mk_createContext(w, w->chapters, 0x45b9)) == NULL) // EditionEntry + return NULL; + + if (flagHidden != 0) + CHECK(mk_writeUInt(ed, 0x45bd, flagHidden)); // EditionFlagHidden + if (flagDefault != 0) + CHECK(mk_writeUInt(ed, 0x45db, flagDefault)); // EditionFlagDefault + if (flagOrdered != 0) + CHECK(mk_writeUInt(ed, 0x45dd, flagOrdered)); // EditionFlagOrdered + + return ed; +} + +/* edition, and parent are mutially exclusive. If you specify both, edition will be ignored. */ +mk_Chapter *mk_createChapter(mk_Writer *w, mk_Chapter *config, mk_Edition *edition, mk_Chapter *parent) { + mk_Chapter *chapter = calloc(1, sizeof(*chapter)); + if (config == NULL || chapter == NULL) + return NULL; + memcpy(chapter, config, sizeof(*chapter)); + + if (parent) { + if (parent->children) { + chapter->tail = parent->children->tail; + **(chapter->tail)->next = chapter; + chapter->prev = *(chapter->tail); + } else { + chapter->tail = calloc(1, sizeof(*mk_Chapter)); + parent->children = chapter; + } + *(chapter->tail) = chapter; + + if ((chapter->context = mk_createContext(w, parent->context, 0xb6)) == NULL) // ChapterAtom + return NULL; + } else { + + } + + CHECK(mk_writeUInt(c, 0x73c4, chapter->chapterUID)); // ChapterUID - FIXME + CHECK(mk_writeUInt(c, 0x91, chapter->chapterTimeStart)); // ChapterTimeStart + if (chapter->chapterTimeStart <= chapter->chapterTimeEnd) // We don't write ChapterTimeEnd if we have a start time that would result in a negative or 0-length chapter. + CHECK(mk_writeUInt(c, 0x92, chapter->chapterTimeEnd)); // ChapterTimeEnd + if (chapter->chapterFlagHidden != 0) + CHECK(mk_writeUInt(c, 0x98, chapter->chapterFlagHidden)); // ChapterFlagHidden + if (chapter->chapterFlagEnabled != 1) + CHECK(mk_writeUInt(c, 0x4598, chapter->chapterFlagEnabled)); // ChapterFlagEnabled + if (chapter->chapterSegmentUID != 0) + CHECK(mk_writeUInt(c, 0x6e67, chapter->chapterSegmentUID)); // ChapterSegmentUID - FIXME + if (chapter->chapterSegmentEditionUID != 0) + CHECK(mk_writeUInt(c, 0x6ebc, chapter->chapterSegmentEditionUID)); // ChapterSegmentEditionUID - FIXME + + return c; +} + +/* country is optional. If lang is blank or NULL the language will be set to 'und' (Unknown/Undefined) */ +int mk_appendChapterDisplay(mk_Writer *w, mk_Context *chapter, char *string, char *lang, char *country) { + mk_Context *c; + + if ((c = mk_createContext(w, chapter, 0x80)) == NULL) // ChapterDisplay + return -1; + + CHECK(mk_writeStr(c, 0x85, string)); // ChapString + if (lang != NULL) + CHECK(mk_writeStr(c, 0x437c, lang)); // ChapLanguage + if (country != NULL) + CHECK(mk_writeStr(c, 0x437e, country)); // ChapCountry + + CHECK(mk_closeContext(c)); + + return 0; +} + +int mk_appendChapterTrack(mk_Writer *w, mk_Context *chapter, mk_Track *track) { + mk_Context *c; + + if ((c = mk_createContext(w, chapter, 0x8f)) == NULL) +} + int mk_writeChapters(mk_Writer *w) { if ((w->chapters == NULL) || (w->edition_entry == NULL)) return -1; diff --git a/src/matroska.h b/src/matroska.h index 151d742..a7d2231 100644 --- a/src/matroska.h +++ b/src/matroska.h @@ -56,7 +56,6 @@ struct mk_Writer_s { mk_Context *root; mk_Context *freelist; mk_Context *actlist; - mk_Context *chapters; mk_Context *edition_entry; mk_Context *tracks; mk_Context *cues; @@ -92,6 +91,11 @@ struct mk_Writer_s { int64_t tc_scaled; } cluster; + struct { + mk_Context *context; + mk_Edition *children; + } + int chapter_uid; uint8_t vlc_compat; }; @@ -119,6 +123,16 @@ struct mk_Track_s { } frame; }; +struct mk_Edition_s { + mk_Context *context; + + mk_Edition *next; + mk_Edition *prev; + mk_Edition **tail; + + mk_Chapter *children; +} + /* EBML */ mk_Context *mk_createContext(mk_Writer *w, mk_Context *parent, unsigned id); int mk_appendContextData(mk_Context *c, const void *data, uint64_t size); -- 2.11.4.GIT