int mk_writeHeader(mk_Writer *w, const char *writingApp) { mk_Context *c; mk_Track *tk; int i; int64_t offset = 0; if (w->wrote_header) return -1; md5_starts(&w->segment_md5); /* Initalize MD5 */ CHECK(mk_writeEbmlHeader(w, "matroska", MATROSKA_VERSION, MATROSKA_VERSION)); /* Segment */ if ((c = mk_createContext(w, w->root, MATROSKA_ID_SEGMENT)) == NULL) return -1; CHECK(mk_flushContextID(c)); w->segment_ptr = c->d_cur; CHECK(mk_closeContext(c, &w->segment_ptr)); if (w->vlc_compat) { CHECK(mk_writeVoid(w->root, RESERVED_SEEKHEAD)); /* Reserved space for SeekHead */ CHECK(mk_writeVoid(w->root, RESERVED_CHAPTERS)); /* Reserved space for Chapters */ } else { w->seek_data.seekhead = 0x80000000; CHECK(mk_writeSeekHead(w, &w->seekhead_ptr)); w->seek_data.seekhead = 0; } if ((c = mk_createContext(w, w->root, MATROSKA_ID_INFO)) == NULL) /* SegmentInfo */ return -1; w->seek_data.segmentinfo = w->root->d_cur - w->segment_ptr; /* Reserve space for a SegmentUID (16 bytes + 1 byte longer EBML ID), to be written it later. */ CHECK(mk_writeVoid(c, 16 + 1)); CHECK(mk_writeStr(c, MATROSKA_ID_MUXINGAPP, PACKAGE_STRING)); /* MuxingApp */ CHECK(mk_writeStr(c, MATROSKA_ID_WRITINGAPP, writingApp)); /* WritingApp */ CHECK(mk_writeUInt(c, MATROSKA_ID_TIMECODESCALE, w->timescale)); /* TimecodeScale */ CHECK(mk_writeFloat(c, MATROSKA_ID_DURATION, 0)); /* Duration */ w->duration_ptr = c->d_cur - 4; CHECK(mk_closeContext(c, &offset)); w->duration_ptr += offset; w->segmentuid_ptr = offset; w->seek_data.tracks = w->root->d_cur - w->segment_ptr; if (w->tracks) { offset = 0; CHECK(mk_closeContext(w->tracks, &offset)); for (i = 0; i < w->num_tracks; i++) { tk = w->tracks_arr[i]; if (tk->private_data_size) tk->private_data_ptr += offset; } } CHECK(mk_flushContextData(w->root)); w->wrote_header = 1; w->def_duration = w->tracks_arr[0]->default_duration; return 0; }
int mk_writeHeader(mk_Writer *w, const char *writingApp, const char *codecID, const void *codecPrivate, unsigned codecPrivateSize, int64_t default_frame_duration, int64_t timescale, unsigned width, unsigned height, unsigned d_width, unsigned d_height) { mk_Context *c, *ti, *v; if (w->wrote_header) return -1; w->timescale = timescale; w->def_duration = default_frame_duration; if ((c = mk_createContext(w, w->root, 0x1a45dfa3)) == NULL) // EBML return -1; CHECK(mk_writeUInt(c, 0x4286, 1)); // EBMLVersion CHECK(mk_writeUInt(c, 0x42f7, 1)); // EBMLReadVersion CHECK(mk_writeUInt(c, 0x42f2, 4)); // EBMLMaxIDLength CHECK(mk_writeUInt(c, 0x42f3, 8)); // EBMLMaxSizeLength CHECK(mk_writeStr(c, 0x4282, "matroska")); // DocType CHECK(mk_writeUInt(c, 0x4287, 1)); // DocTypeVersion CHECK(mk_writeUInt(c, 0x4285, 1)); // DocTypeReadversion CHECK(mk_closeContext(c, 0)); if ((c = mk_createContext(w, w->root, 0x18538067)) == NULL) // Segment return -1; CHECK(mk_flushContextID(c)); CHECK(mk_closeContext(c, 0)); if ((c = mk_createContext(w, w->root, 0x1549a966)) == NULL) // SegmentInfo return -1; CHECK(mk_writeStr(c, 0x4d80, "Haali Matroska Writer b0")); CHECK(mk_writeStr(c, 0x5741, writingApp)); CHECK(mk_writeUInt(c, 0x2ad7b1, w->timescale)); CHECK(mk_writeFloat(c, 0x4489, 0)); w->duration_ptr = c->d_cur - 4; CHECK(mk_closeContext(c, &w->duration_ptr)); if ((c = mk_createContext(w, w->root, 0x1654ae6b)) == NULL) // tracks return -1; if ((ti = mk_createContext(w, c, 0xae)) == NULL) // TrackEntry return -1; CHECK(mk_writeUInt(ti, 0xd7, 1)); // TrackNumber CHECK(mk_writeUInt(ti, 0x73c5, 1)); // TrackUID CHECK(mk_writeUInt(ti, 0x83, 1)); // TrackType CHECK(mk_writeUInt(ti, 0x9c, 0)); // FlagLacing CHECK(mk_writeStr(ti, 0x86, codecID)); // CodecID if (codecPrivateSize) CHECK(mk_writeBin(ti, 0x63a2, codecPrivate, codecPrivateSize)); // CodecPrivate if (default_frame_duration) CHECK(mk_writeUInt(ti, 0x23e383, default_frame_duration)); // DefaultDuration if ((v = mk_createContext(w, ti, 0xe0)) == NULL) // Video return -1; CHECK(mk_writeUInt(v, 0xb0, width)); CHECK(mk_writeUInt(v, 0xba, height)); CHECK(mk_writeUInt(v, 0x54b0, d_width)); CHECK(mk_writeUInt(v, 0x54ba, d_height)); CHECK(mk_closeContext(v, 0)); CHECK(mk_closeContext(ti, 0)); CHECK(mk_closeContext(c, 0)); CHECK(mk_flushContextData(w->root)); w->wrote_header = 1; return 0; }