Merge branch 'subtitles' of git+ssh://saintdev@repo.or.cz/srv/git/libmkv
[libmkv.git] / src / matroska.c
blob94170a5c5f119bdc9e1a59bd41e808f117a0e855
1 /*****************************************************************************
2 * matroska.c:
3 *****************************************************************************
4 * Copyright (C) 2005 x264 project
6 * Authors: Mike Matsnev
7 * Nathan Caldwell
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
23 #include "config.h"
24 #include "libmkv.h"
25 #include "matroska.h"
26 #include "md5.h"
28 #include <sys/time.h>
30 #define RESERVED_SEEKHEAD 0x100
31 /* 256 bytes should be enough room for our Seek entries. */
32 #define RESERVED_CHAPTERS 0x1000
33 /* 4096 bytes, hopefully enough for Chapters. */
35 int mk_seekFile(mk_Writer *w, uint64_t pos)
37 if (fseek(w->fp, pos, SEEK_SET))
38 return -1;
40 w->f_pos = pos;
42 if (pos > w->f_eof)
43 w->f_eof = pos;
45 return 0;
48 char *mk_laceXiph(uint64_t *sizes, uint8_t num_frames,
49 uint64_t *output_size)
51 unsigned i, j;
52 uint64_t offset = 0;
53 uint64_t alloc_size = num_frames * 6; /* Complete guess. It gets realloc'd
54 * below if we need more space, though.
56 char *laced = calloc(alloc_size, sizeof(*laced));
57 if (laced == NULL)
58 return NULL;
60 laced[offset++] = num_frames;
61 for (i = 0; i < num_frames; i++) {
62 for (j = sizes[i]; j >= 255; j -= 255) {
63 laced[offset++] = 255;
64 if (offset + 1 >= alloc_size) {
65 int avg_sz = offset / (i - 1); /* Compute approximate average bytes/frame */
66 alloc_size += avg_sz * (num_frames - i);
67 /* Sum average so far and number of frames left
68 * with alloc'd size
70 if ((laced = realloc(laced, alloc_size)) == NULL)
71 return NULL;
74 laced[offset++] = j;
77 if (output_size != NULL)
78 *output_size = offset;
80 return laced;
83 mk_Writer *mk_createWriter(const char *filename, int64_t timescale,
84 uint8_t vlc_compat)
86 mk_Writer *w = calloc(1, sizeof(*w));
87 struct timeval tv;
89 if (w == NULL)
90 return NULL;
92 w->root = mk_createContext(w, NULL, 0);
93 if (w->root == NULL) {
94 free(w);
95 return NULL;
98 /* Cues */
99 if ((w->cues = mk_createContext(w, w->root, MATROSKA_ID_CUES)) == NULL)
101 mk_destroyContexts(w);
102 free(w);
103 return NULL;
106 /* Clusters SeekHead */
107 if ((w->cluster.seekhead = mk_createContext(w, w->root, MATROSKA_ID_SEEKHEAD)) == NULL)
109 mk_destroyContexts(w);
110 free(w);
111 return NULL;
114 w->fp = fopen(filename, "wb");
115 if (w->fp == NULL) {
116 mk_destroyContexts(w);
117 free(w);
118 return NULL;
121 gettimeofday( &tv, NULL );
122 srandom(tv.tv_sec ^ tv.tv_usec);
124 w->timescale = timescale;
125 w->vlc_compat = vlc_compat;
127 return w;
130 int mk_writeHeader(mk_Writer *w, const char *writingApp)
132 mk_Context *c;
133 int64_t offset = 0;
135 if (w->wrote_header)
136 return -1;
138 md5_starts(&w->segment_md5); /* Initalize MD5 */
140 CHECK(mk_writeEbmlHeader(w, "matroska", MATROSKA_VERSION, MATROSKA_VERSION));
142 /* Segment */
143 if ((c = mk_createContext(w, w->root, MATROSKA_ID_SEGMENT)) == NULL)
144 return -1;
145 CHECK(mk_flushContextID(c));
146 w->segment_ptr = c->d_cur;
147 CHECK(mk_closeContext(c, &w->segment_ptr));
149 if (w->vlc_compat) {
150 CHECK(mk_writeVoid(w->root, RESERVED_SEEKHEAD)); /* Reserved space for SeekHead */
151 CHECK(mk_writeVoid(w->root, RESERVED_CHAPTERS)); /* Reserved space for Chapters */
152 } else {
153 w->seek_data.seekhead = 0x80000000;
154 CHECK(mk_writeSeekHead(w, &w->seekhead_ptr));
155 w->seek_data.seekhead = 0;
158 if ((c = mk_createContext(w, w->root, MATROSKA_ID_INFO)) == NULL) /* SegmentInfo */
159 return -1;
160 w->seek_data.segmentinfo = w->root->d_cur - w->segment_ptr;
161 CHECK(mk_writeVoid(c, 16)); /* Reserve space for a SegmentUID, to be written it later. */
162 CHECK(mk_writeStr(c, MATROSKA_ID_MUXINGAPP, PACKAGE_STRING)); /* MuxingApp */
163 CHECK(mk_writeStr(c, MATROSKA_ID_WRITINGAPP, writingApp)); /* WritingApp */
164 CHECK(mk_writeUInt(c, MATROSKA_ID_TIMECODESCALE, w->timescale)); /* TimecodeScale */
165 CHECK(mk_writeFloat(c, MATROSKA_ID_DURATION, 0)); /* Duration */
166 w->duration_ptr = c->d_cur - 4;
167 CHECK(mk_closeContext(c, &offset));
168 w->duration_ptr += offset;
169 w->segmentuid_ptr = offset;
171 w->seek_data.tracks = w->root->d_cur - w->segment_ptr;
173 if (w->tracks)
174 CHECK(mk_closeContext(w->tracks, 0));
176 CHECK(mk_flushContextData(w->root));
178 w->wrote_header = 1;
179 w->def_duration = w->tracks_arr[0]->default_duration;
180 return 0;
183 static int mk_closeCluster(mk_Writer *w)
185 if (w->cluster.context == NULL)
186 return 0;
187 w->cluster.count++;
188 CHECK(mk_closeContext(w->cluster.context, 0));
189 w->cluster.context = NULL;
190 CHECK(mk_flushContextData(w->root));
192 return 0;
195 int mk_flushFrame(mk_Writer *w, mk_Track *track)
197 mk_Context *c, *tp;
198 int64_t delta, ref = 0;
199 unsigned fsize, bgsize;
200 uint8_t flags, c_delta[2];
201 int i;
202 char *laced = NULL;
203 uint64_t length = 0;
204 uint64_t block_duration = 0;
206 if (!track->in_frame)
207 return 0;
209 delta = track->frame.timecode / w->timescale - w->cluster.tc_scaled;
210 block_duration = track->frame.duration / w->timescale;
211 /* If switch rapidly back-and-forth between tracks with drastically different timecodes
212 * this causes a new cluster to be written each time a switch is made. This causes
213 * unnecessary overhead.
216 if (delta > 20000ll || delta < -20000ll)
217 CHECK(mk_closeCluster(w));
219 if (w->cluster.context == NULL) {
220 w->cluster.tc_scaled = track->frame.timecode / w->timescale;
221 /* Cluster */
222 w->cluster.context = mk_createContext(w, w->root, MATROSKA_ID_CLUSTER);
223 if (w->cluster.context == NULL)
224 return -1;
226 w->cluster.pointer = w->f_pos - w->segment_ptr;
228 /* Cluster SeekEntry */
229 CHECK(mk_writeSeek(w, w->cluster.seekhead, MATROSKA_ID_CLUSTER,
230 w->cluster.pointer));
232 /* Cluster Timecode */
233 CHECK(mk_writeUInt(w->cluster.context, MATROSKA_ID_CLUSTERTIMECODE, w->cluster.tc_scaled));
235 delta = 0;
236 w->cluster.block_count = 0;
239 /* Calculate the encoded lacing sizes. */
240 switch (track->frame.lacing) {
241 case MK_LACING_XIPH:
242 laced = mk_laceXiph(track->frame.lacing_sizes,
243 track->frame.lacing_num_frames, &length);
244 break;
245 case MK_LACING_EBML:
247 uint64_t u_size = 0;
248 /* Add one below for the frame count. */
249 length += mk_ebmlSizeSize(track->frame.lacing_sizes[0]) + 1;
250 for (i = 1; i < track->frame.lacing_num_frames; i++) {
251 u_size = llabs(track->frame.lacing_sizes[i] -
252 track->frame.lacing_sizes[i - 1]);
253 /* Shift by one so we get the right size for a signed number. */
254 length += mk_ebmlSizeSize((u_size) << 1);
256 break;
258 case MK_LACING_FIXED:
260 laced = calloc(1, sizeof(*laced));
261 laced[0] = track->frame.lacing_num_frames;
262 ++length;
263 break;
265 default:
266 break;
269 fsize = track->frame.data ? track->frame.data->d_cur : 0;
270 bgsize = fsize + 4 + mk_ebmlSizeSize(fsize + 4 + length) + 1 + length;
271 if (!track->frame.keyframe) {
272 ref = track->prev_frame_tc_scaled - w->cluster.tc_scaled - delta;
273 bgsize += 1 + 1 + mk_ebmlSIntSize(ref);
275 if (block_duration > 0) /* BlockDuration */
277 bgsize += 1 + 1 + mk_ebmlUIntSize(block_duration);
280 CHECK(mk_writeID(w->cluster.context, MATROSKA_ID_BLOCKGROUP)); /* BlockGroup */
281 CHECK(mk_writeSize(w->cluster.context, bgsize));
282 CHECK(mk_writeID(w->cluster.context, MATROSKA_ID_BLOCK)); /* Block */
283 CHECK(mk_writeSize(w->cluster.context, fsize + 4 + length)); /* BlockSize */
284 CHECK(mk_writeSize(w->cluster.context, track->track_id)); /* track number */
286 w->cluster.block_count++;
288 c_delta[0] = delta >> 8;
289 c_delta[1] = delta;
290 /* Timecode relative to Cluster. */
291 CHECK(mk_appendContextData(w->cluster.context, c_delta, 2));
293 /* flags = ( track->frame.keyframe << 8 ) | track->frame.lacing; */
294 flags = track->frame.lacing << 1; /* Flags: Bit 5-6 describe what type of lacing to use. */
295 CHECK(mk_appendContextData(w->cluster.context, &flags, 1));
296 if (track->frame.lacing) {
297 if (track->frame.lacing == MK_LACING_EBML) {
298 /* Number of frames in lace - 1 */
299 CHECK(mk_appendContextData(w->cluster.context, &track->frame.lacing_num_frames, 1));
300 /* Size of 1st frame. */
301 CHECK(mk_writeSize(w->cluster.context, track->frame.lacing_sizes[0]));
302 for (i = 1; i < track->frame.lacing_num_frames; i++) {
303 /* Size difference between previous size and this size. */
304 CHECK(mk_writeSSize(w->cluster.context, track->frame.lacing_sizes[i] - track->frame.lacing_sizes[i - 1]));
306 } else if (length > 0 && laced != NULL) {
307 CHECK(mk_appendContextData(w->cluster.context, laced, length));
308 free(laced);
309 laced = NULL;
313 if (track->frame.data) {
314 CHECK(mk_appendContextData(w->cluster.context, track->frame.data->data,
315 track->frame.data->d_cur));
316 track->frame.data->d_cur = 0;
318 if (!track->frame.keyframe) /* ReferenceBlock */
319 CHECK(mk_writeSInt(w->cluster.context, MATROSKA_ID_REFERENCEBLOCK, ref));
321 if (block_duration > 0) /* BlockDuration */
322 CHECK(mk_writeUInt(w->cluster.context, 0x9b, block_duration));
324 /* This may get a little out of hand, but it seems sane enough for now. */
325 if (track->frame.keyframe && (track->track_type == MK_TRACK_VIDEO)) {
326 /* if (track->frame.keyframe && (track->track_type & MK_TRACK_VIDEO) && ((track->prev_cue_pos + 3*CLSIZE) <= w->f_pos || track->frame.timecode == 0)) { */
327 /* CuePoint */
328 if ((c = mk_createContext(w, w->cues, MATROSKA_ID_CUEPOINT)) == NULL)
329 return -1;
330 /* CueTime */
331 CHECK(mk_writeUInt(c, MATROSKA_ID_CUETIME, (track->frame.timecode / w->timescale)));
333 /* CueTrackPositions */
334 if ((tp = mk_createContext(w, c, MATROSKA_ID_CUETRACKPOSITIONS)) == NULL)
335 return -1;
336 /* CueTrack */
337 CHECK(mk_writeUInt(tp, MATROSKA_ID_CUETRACK, track->track_id));
338 /* CueClusterPosition */
339 CHECK(mk_writeUInt(tp, MATROSKA_ID_CUECLUSTERPOSITION, w->cluster.pointer));
340 /* CueBlockNumber */
341 /* CHECK(mk_writeUInt(c, MATROSKA_ID_CUEBLOCKNUMBER, w->cluster.block_count)); */
342 CHECK(mk_closeContext(tp, 0));
343 CHECK(mk_closeContext(c, 0));
344 track->prev_cue_pos = w->f_pos;
347 track->in_frame = 0;
348 track->prev_frame_tc_scaled = w->cluster.tc_scaled + delta;
350 /* Write a new Cluster ~ every 5MB */
351 if (w->cluster.context->d_cur > 5 * CLSIZE)
352 CHECK(mk_closeCluster(w));
354 return 0;
357 int mk_startFrame(mk_Writer *w, mk_Track *track)
359 if (mk_flushFrame(w, track) < 0)
360 return -1;
362 track->in_frame = 1;
363 track->frame.keyframe = 0;
364 track->frame.lacing = MK_LACING_NONE;
365 track->frame.lacing_num_frames = 0;
366 track->frame.lacing_sizes = NULL;
368 return 0;
371 int mk_setFrameFlags(mk_Writer *w, mk_Track *track, int64_t timestamp,
372 unsigned keyframe, uint64_t duration)
374 if (!track->in_frame)
375 return -1;
377 track->frame.timecode = timestamp;
378 track->frame.keyframe = keyframe != 0;
380 if (track->max_frame_tc < timestamp)
381 track->max_frame_tc = timestamp;
383 if (duration > 0)
384 track->frame.duration = duration;
386 return 0;
389 int mk_setFrameLacing(mk_Writer *w, mk_Track *track,
390 mk_LacingType lacing, uint8_t num_frames,
391 uint64_t sizes[])
393 if (!track->in_frame)
394 return -1;
395 track->frame.lacing_sizes = calloc(num_frames, sizeof(*sizes));
397 track->frame.lacing = lacing;
398 track->frame.lacing_num_frames = num_frames;
399 memcpy(track->frame.lacing_sizes, sizes,
400 num_frames * sizeof(*sizes));
402 return 0;
405 int mk_addFrameData(mk_Writer *w, mk_Track *track, const void *data,
406 unsigned size)
408 if (!track->in_frame)
409 return -1;
411 if (track->frame.data == NULL) {
412 if ((track->frame.data = mk_createContext(w, NULL, 0)) == NULL)
413 return -1;
416 md5_update(&w->segment_md5, (unsigned char *) data, size);
418 return mk_appendContextData(track->frame.data, data, size);
421 int mk_writeSeek(mk_Writer *w, mk_Context *c, unsigned seek_id,
422 uint64_t seek_pos)
424 mk_Context *s;
426 if ((s = mk_createContext(w, c, MATROSKA_ID_SEEKENTRY)) == NULL) /* Seek */
427 return -1;
428 CHECK(mk_writeUInt(s, MATROSKA_ID_SEEKID, seek_id)); /* SeekID */
429 CHECK(mk_writeUInt(s, MATROSKA_ID_SEEKPOSITION, seek_pos)); /* SeekPosition */
430 CHECK(mk_closeContext(s, 0));
432 return 0;
435 /* The offset of the SeekHead is returned in pointer. */
436 int mk_writeSeekHead(mk_Writer *w, int64_t *pointer)
438 mk_Context *c;
439 int64_t seekhead_ptr;
441 /* SeekHead */
442 if ((c = mk_createContext(w, w->root, MATROSKA_ID_SEEKHEAD)) == NULL)
443 return -1;
444 if (pointer != NULL)
445 seekhead_ptr = w->f_pos;
446 if (w->seek_data.seekhead)
447 CHECK(mk_writeSeek(w, c, MATROSKA_ID_SEEKHEAD, w->seek_data.seekhead));
448 if (w->seek_data.segmentinfo)
449 CHECK(mk_writeSeek(w, c, MATROSKA_ID_INFO, w->seek_data.segmentinfo));
450 if (w->seek_data.tracks)
451 CHECK(mk_writeSeek(w, c, MATROSKA_ID_TRACKS, w->seek_data.tracks));
452 if (w->seek_data.cues)
453 CHECK(mk_writeSeek(w, c, MATROSKA_ID_CUES, w->seek_data.cues));
454 if (w->seek_data.attachments)
455 CHECK(mk_writeSeek(w, c, MATROSKA_ID_ATTACHMENTS, w->seek_data.attachments));
456 if (w->seek_data.chapters)
457 CHECK(mk_writeSeek(w, c, MATROSKA_ID_CHAPTERS, w->seek_data.chapters));
458 if (w->seek_data.tags)
459 CHECK(mk_writeSeek(w, c, MATROSKA_ID_TAGS, w->seek_data.tags));
460 CHECK(mk_closeContext(c, 0));
462 if (pointer != NULL)
463 *pointer = seekhead_ptr;
465 return 0;
468 int mk_close(mk_Writer *w)
470 int i, ret = 0;
471 mk_Track *tk;
472 int64_t max_frame_tc = w->tracks_arr[0]->max_frame_tc;
473 uint64_t segment_size = 0;
474 unsigned char c_size[8];
475 unsigned char segment_uid[16];
477 md5_finish(&w->segment_md5, segment_uid);
479 for (i = w->num_tracks - 1; i >= 0; i--) {
480 tk = w->tracks_arr[i];
481 w->tracks_arr[i] = NULL;
482 --w->num_tracks;
483 if (mk_flushFrame(w, tk) < 0)
484 ret = -1;
485 free(tk);
486 tk = NULL;
489 if (mk_closeCluster(w) < 0)
490 ret = -1;
492 w->seek_data.cues = w->f_pos - w->segment_ptr;
493 if (mk_closeContext(w->cues, 0) < 0)
494 ret = -1;
495 if (mk_flushContextData(w->root) < 0)
496 ret = -1;
498 if (w->cluster.seekhead) {
499 w->seek_data.seekhead = w->f_pos - w->segment_ptr;
500 if (mk_closeContext(w->cluster.seekhead, 0) < 0)
501 ret = -1;
502 if (mk_flushContextData(w->root) < 0)
503 ret = -1;
506 if (w->attachments != NULL) {
507 w->seek_data.attachments = w->f_pos - w->segment_ptr;
508 mk_writeAttachments(w);
509 if (mk_flushContextData(w->root) < 0)
510 ret = -1;
513 if (w->tags != NULL) {
514 w->seek_data.tags = w->f_pos - w->segment_ptr;
515 mk_writeTags(w);
516 if (mk_flushContextData(w->root) < 0)
517 ret = -1;
520 if (w->chapters != NULL) {
521 if (w->vlc_compat) {
522 if (mk_flushContextData(w->root) < 0)
523 ret = -1;
524 if (mk_seekFile(w, w->segment_ptr + RESERVED_SEEKHEAD + 3) < 0)
525 ret = -1;
527 w->seek_data.chapters = w->f_pos - w->segment_ptr;
528 mk_writeChapters(w);
529 if (mk_flushContextData(w->root) < 0)
530 ret = -1;
531 if (w->vlc_compat) {
532 if (mk_writeVoid(w->root, (RESERVED_CHAPTERS - (w->f_pos - w->segment_ptr - RESERVED_SEEKHEAD - 3))) < 0)
533 ret = -1;
534 if (mk_flushContextData(w->root) < 0)
535 ret = -1;
539 if (w->wrote_header) {
540 if (w->vlc_compat) {
541 if (mk_seekFile(w, w->segment_ptr) < 0)
542 ret = -1;
545 if (mk_writeSeekHead(w, &w->seek_data.seekhead) < 0)
546 ret = -1;
547 w->seek_data.seekhead -= w->segment_ptr;
549 if (w->vlc_compat) {
550 if (mk_flushContextData(w->root) < 0)
551 ret = -1;
552 if (mk_writeVoid(w->root, (RESERVED_SEEKHEAD - (w->f_pos - w->segment_ptr))) < 0)
553 ret = -1;
556 if (mk_flushContextData(w->root) < 0)
557 ret = -1;
559 if (!w->vlc_compat) {
560 int i = w->seek_data.segmentinfo;
561 w->seek_data.segmentinfo = 0;
562 w->seek_data.tracks = 0;
563 w->seek_data.cues = 0;
564 w->seek_data.chapters = 0;
565 w->seek_data.attachments = 0;
566 w->seek_data.tags = 0;
567 if (mk_seekFile(w, w->segment_ptr) < 0)
568 ret = -1;
569 if (mk_writeSeekHead(w, NULL) < 0 || mk_flushContextData(w->root) < 0)
570 ret = -1;
571 // The conditional below is easier to understand, but incorrect
572 // because f_pos is unsigned and causes the lhs to be evaluated
573 // as an unsigned quantity.
574 // if (((i + w->segment_ptr) - w->f_pos - 2) > 1)
575 if ((i + w->segment_ptr) > (w->f_pos + 3))
576 if (mk_writeVoid(w->root, (i + w->segment_ptr) - w->f_pos - 2) < 0
577 || mk_flushContextData(w->root) < 0)
578 ret = -1;
581 if (mk_seekFile(w, w->duration_ptr) < 0)
582 ret = -1;
583 if (mk_writeFloatRaw(w->root,
584 (float) ((double) (max_frame_tc + w->def_duration) /
585 w->timescale)) < 0
586 || mk_flushContextData(w->root) < 0)
587 ret = -1;
588 if (mk_seekFile(w, w->segment_ptr - 8) < 0)
589 ret = -1;
590 segment_size = w->f_eof - w->segment_ptr;
591 for (i = 7; i > 0; --i)
592 c_size[i] = segment_size >> (8 * (7 - i));
593 c_size[i] = 0x01;
594 if (mk_appendContextData(w->root, &c_size, 8) < 0 ||
595 mk_flushContextData(w->root) < 0)
596 ret = -1;
597 if (mk_seekFile(w, w->segmentuid_ptr) < 0)
598 ret = -1;
599 if (mk_writeBin(w->root, MATROSKA_ID_SEGMENTUID, segment_uid,
600 sizeof(segment_uid)) < 0 ||
601 mk_flushContextData(w->root) < 0)
602 ret = -1;
605 if (mk_closeContext(w->root, 0) < 0)
606 ret = -1;
607 mk_destroyContexts(w);
608 fclose(w->fp);
609 free(w->tracks_arr);
610 free(w);
612 return ret;