extern int dvr_iov_max;
TAILQ_HEAD(mk_cue_queue, mk_cue);
+TAILQ_HEAD(mk_chapter_queue, mk_chapter);
#define MATROSKA_TIMESCALE 1000000 // in nS
off_t cluster_pos;
};
+/**
+ *
+ */
+struct mk_chapter {
+ TAILQ_ENTRY(mk_chapter) link;
+ int uuid;
+ int64_t ts;
+};
+
/**
*
*/
off_t trackinfo_pos;
off_t metadata_pos;
off_t cue_pos;
+ off_t chapters_pos;
int addcue;
struct mk_cue_queue cues;
+ struct mk_chapter_queue chapters;
char uuid[16];
char *title;
}
+/**
+ *
+ */
+static htsbuf_queue_t *
+mk_build_one_chapter(struct mk_chapter *ch)
+{
+ htsbuf_queue_t *q = htsbuf_queue_alloc(0);
+
+ ebml_append_uint(q, 0x73C4, ch->uuid);
+ ebml_append_uint(q, 0x91, ch->ts * MATROSKA_TIMESCALE);
+ ebml_append_uint(q, 0x98, 0); //ChapterFlagHidden
+ ebml_append_uint(q, 0x4598, 1); //ChapterFlagEnabled
+
+ return q;
+}
+
+
+/**
+ *
+ */
+static htsbuf_queue_t *
+mk_build_edition_entry(mk_mux_t *mkm)
+{
+ struct mk_chapter *ch;
+ htsbuf_queue_t *q = htsbuf_queue_alloc(0);
+
+ ebml_append_uint(q, 0x45bd, 0); //EditionFlagHidden
+ ebml_append_uint(q, 0x45db, 1); //EditionFlagDefault
+
+ TAILQ_FOREACH(ch, &mkm->chapters, link) {
+ ebml_append_master(q, 0xB6, mk_build_one_chapter(ch));
+ }
+
+ return q;
+}
+
+
+/**
+ *
+ */
+static htsbuf_queue_t *
+mk_build_chapters(mk_mux_t *mkm)
+{
+ htsbuf_queue_t *q = htsbuf_queue_alloc(0);
+
+ ebml_append_master(q, 0x45b9, mk_build_edition_entry(mkm));
+
+ return q;
+}
+
+/**
+ *
+ */
+static void
+mk_write_chapters(mk_mux_t *mkm)
+{
+ if(TAILQ_FIRST(&mkm->chapters) == NULL)
+ return;
+
+ mkm->chapters_pos = mkm->fdpos;
+ mk_write_master(mkm, 0x1043a770, mk_build_chapters(mkm));
+}
+
+
/**
*
*/
ebml_append_master(q, 0x4dbb,
mk_build_one_metaseek(mkm, 0x1c53bb6b,
mkm->cue_pos));
+
+ if(mkm->chapters_pos)
+ ebml_append_master(q, 0x4dbb,
+ mk_build_one_metaseek(mkm, 0x1043a770,
+ mkm->chapters_pos));
return q;
}
}
+/**
+ *
+ */
+static void
+mk_add_chapter(mk_mux_t *mkm, int64_t ts)
+{
+ struct mk_chapter *ch;
+ int uuid;
+
+ ch = TAILQ_LAST(&mkm->chapters, mk_chapter_queue);
+ if(ch)
+ uuid = ch->uuid + 1;
+ else
+ uuid = 1;
+
+ ch = malloc(sizeof(struct mk_chapter));
+
+ ch->uuid = uuid;
+ ch->ts = ts;
+
+ TAILQ_INSERT_TAIL(&mkm->chapters, ch, link);
+}
+
/**
*
*/
mkm->title = strdup(mkm->filename);
TAILQ_INIT(&mkm->cues);
+ TAILQ_INIT(&mkm->chapters);
htsbuf_queue_init(&q, 0);
pkt = pkt_merge_header(pkt);
mk_write_frame_i(mkm, t, pkt);
}
-
+
pkt_ref_dec(pkt);
return mkm->error;
}
+/**
+ * Insert a new chapter at the current location
+ */
+int
+mk_mux_insert_chapter(mk_mux_t *mkm)
+{
+ if(mkm->totduration != PTS_UNSET)
+ mk_add_chapter(mkm, mkm->totduration);
+
+ return mkm->error;
+}
+
+
/**
* Close the muxer
*/
int64_t totsize;
mk_close_cluster(mkm);
mk_write_cues(mkm);
+ mk_write_chapters(mkm);
mk_write_metaseek(mkm, 0);
totsize = mkm->fdpos;
void
mk_mux_destroy(mk_mux_t *mkm)
{
+ struct mk_chapter *ch;
+
+ while((ch = TAILQ_FIRST(&mkm->chapters)) != NULL) {
+ free(ch);
+ }
+
free(mkm->filename);
free(mkm->tracks);
free(mkm->title);