Mercurial > libavformat.hg
comparison matroskaenc.c @ 2489:3ef5728030da libavformat
Calculate the size of key EBML master elements beforehand so only just enough size is reserved for the size
author | conrad |
---|---|
date | Wed, 05 Sep 2007 00:24:56 +0000 |
parents | 7420572a8d72 |
children | 06d0bb96139a |
comparison
equal
deleted
inserted
replaced
2488:7420572a8d72 | 2489:3ef5728030da |
---|---|
23 #include "md5.h" | 23 #include "md5.h" |
24 #include "riff.h" | 24 #include "riff.h" |
25 #include "xiph.h" | 25 #include "xiph.h" |
26 #include "matroska.h" | 26 #include "matroska.h" |
27 | 27 |
28 typedef struct ebml_master { | |
29 offset_t pos; ///< absolute offset in the file where the master's elements start | |
30 int sizebytes; ///< how many bytes were reserved for the size | |
31 } ebml_master; | |
32 | |
28 typedef struct mkv_seekhead_entry { | 33 typedef struct mkv_seekhead_entry { |
29 unsigned int elementid; | 34 unsigned int elementid; |
30 uint64_t segmentpos; | 35 uint64_t segmentpos; |
31 } mkv_seekhead_entry; | 36 } mkv_seekhead_entry; |
32 | 37 |
50 mkv_cuepoint *entries; | 55 mkv_cuepoint *entries; |
51 int num_entries; | 56 int num_entries; |
52 } mkv_cues; | 57 } mkv_cues; |
53 | 58 |
54 typedef struct MatroskaMuxContext { | 59 typedef struct MatroskaMuxContext { |
55 offset_t segment; | 60 ebml_master segment; |
56 offset_t segment_offset; | 61 offset_t segment_offset; |
57 offset_t segment_uid; | 62 offset_t segment_uid; |
58 offset_t cluster; | 63 ebml_master cluster; |
59 offset_t cluster_pos; ///< file offset of the current cluster | 64 offset_t cluster_pos; ///< file offset of the current cluster |
60 uint64_t cluster_pts; | 65 uint64_t cluster_pts; |
61 offset_t duration_offset; | 66 offset_t duration_offset; |
62 uint64_t duration; | 67 uint64_t duration; |
63 mkv_seekhead *main_seekhead; | 68 mkv_seekhead *main_seekhead; |
64 mkv_seekhead *cluster_seekhead; | 69 mkv_seekhead *cluster_seekhead; |
65 mkv_cues *cues; | 70 mkv_cues *cues; |
66 | 71 |
67 struct AVMD5 *md5_ctx; | 72 struct AVMD5 *md5_ctx; |
68 } MatroskaMuxContext; | 73 } MatroskaMuxContext; |
74 | |
75 | |
76 // 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit offset, 4 bytes for target EBML ID | |
77 #define MAX_SEEKENTRY_SIZE 21 | |
78 | |
79 // per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2 8-byte uint max | |
80 #define MAX_CUETRACKPOS_SIZE 22 | |
81 | |
82 // per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max | |
83 #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks | |
84 | |
69 | 85 |
70 static int ebml_id_size(unsigned int id) | 86 static int ebml_id_size(unsigned int id) |
71 { | 87 { |
72 return (av_log2(id+1)-1)/7+1; | 88 return (av_log2(id+1)-1)/7+1; |
73 } | 89 } |
192 else | 208 else |
193 put_ebml_size(pb, size-9, 8); | 209 put_ebml_size(pb, size-9, 8); |
194 url_fseek(pb, currentpos + size, SEEK_SET); | 210 url_fseek(pb, currentpos + size, SEEK_SET); |
195 } | 211 } |
196 | 212 |
197 static offset_t start_ebml_master(ByteIOContext *pb, unsigned int elementid) | 213 static ebml_master start_ebml_master(ByteIOContext *pb, unsigned int elementid, uint64_t expectedsize) |
198 { | 214 { |
215 int bytes = expectedsize ? ebml_size_bytes(expectedsize) : 8; | |
199 put_ebml_id(pb, elementid); | 216 put_ebml_id(pb, elementid); |
200 // XXX: this always reserves the maximum needed space to store any size value | 217 put_ebml_size_unknown(pb, bytes); |
201 // we should be smarter (additional parameter for expected size?) | 218 return (ebml_master){ url_ftell(pb), bytes }; |
202 put_ebml_size_unknown(pb, 8); | 219 } |
203 return url_ftell(pb); | 220 |
204 } | 221 static void end_ebml_master(ByteIOContext *pb, ebml_master master) |
205 | |
206 static void end_ebml_master(ByteIOContext *pb, offset_t start) | |
207 { | 222 { |
208 offset_t pos = url_ftell(pb); | 223 offset_t pos = url_ftell(pb); |
209 | 224 |
210 url_fseek(pb, start - 8, SEEK_SET); | 225 url_fseek(pb, master.pos - master.sizebytes, SEEK_SET); |
211 put_ebml_size(pb, pos - start, 8); | 226 put_ebml_size(pb, pos - master.pos, master.sizebytes); |
212 url_fseek(pb, pos, SEEK_SET); | 227 url_fseek(pb, pos, SEEK_SET); |
213 } | 228 } |
214 | 229 |
215 static void put_xiph_size(ByteIOContext *pb, int size) | 230 static void put_xiph_size(ByteIOContext *pb, int size) |
216 { | 231 { |
239 | 254 |
240 if (numelements > 0) { | 255 if (numelements > 0) { |
241 new_seekhead->filepos = url_ftell(pb); | 256 new_seekhead->filepos = url_ftell(pb); |
242 // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID and size, | 257 // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID and size, |
243 // and 3 bytes to guarantee that an EBML void element will fit afterwards | 258 // and 3 bytes to guarantee that an EBML void element will fit afterwards |
244 // XXX: 28 bytes right now because begin_ebml_master() reserves more than necessary | 259 new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 13; |
245 new_seekhead->reserved_size = numelements * 28 + 13; | |
246 new_seekhead->max_entries = numelements; | 260 new_seekhead->max_entries = numelements; |
247 put_ebml_void(pb, new_seekhead->reserved_size); | 261 put_ebml_void(pb, new_seekhead->reserved_size); |
248 } | 262 } |
249 return new_seekhead; | 263 return new_seekhead; |
250 } | 264 } |
278 * | 292 * |
279 * @return the file offset where the seekhead was written | 293 * @return the file offset where the seekhead was written |
280 */ | 294 */ |
281 static offset_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead) | 295 static offset_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead) |
282 { | 296 { |
283 offset_t metaseek, seekentry, currentpos; | 297 ebml_master metaseek, seekentry; |
298 offset_t currentpos; | |
284 int i; | 299 int i; |
285 | 300 |
286 currentpos = url_ftell(pb); | 301 currentpos = url_ftell(pb); |
287 | 302 |
288 if (seekhead->reserved_size > 0) | 303 if (seekhead->reserved_size > 0) |
289 url_fseek(pb, seekhead->filepos, SEEK_SET); | 304 url_fseek(pb, seekhead->filepos, SEEK_SET); |
290 | 305 |
291 metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD); | 306 metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_size); |
292 for (i = 0; i < seekhead->num_entries; i++) { | 307 for (i = 0; i < seekhead->num_entries; i++) { |
293 mkv_seekhead_entry *entry = &seekhead->entries[i]; | 308 mkv_seekhead_entry *entry = &seekhead->entries[i]; |
294 | 309 |
295 seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY); | 310 seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE); |
296 | 311 |
297 put_ebml_id(pb, MATROSKA_ID_SEEKID); | 312 put_ebml_id(pb, MATROSKA_ID_SEEKID); |
298 put_ebml_size(pb, ebml_id_size(entry->elementid), 0); | 313 put_ebml_size(pb, ebml_id_size(entry->elementid), 0); |
299 put_ebml_id(pb, entry->elementid); | 314 put_ebml_id(pb, entry->elementid); |
300 | 315 |
342 cues->entries = entries; | 357 cues->entries = entries; |
343 cues->num_entries++; | 358 cues->num_entries++; |
344 return 0; | 359 return 0; |
345 } | 360 } |
346 | 361 |
347 static offset_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues) | 362 static offset_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks) |
348 { | 363 { |
349 offset_t currentpos, cues_element; | 364 ebml_master cues_element; |
365 offset_t currentpos; | |
350 int i, j; | 366 int i, j; |
351 | 367 |
352 currentpos = url_ftell(pb); | 368 currentpos = url_ftell(pb); |
353 cues_element = start_ebml_master(pb, MATROSKA_ID_CUES); | 369 cues_element = start_ebml_master(pb, MATROSKA_ID_CUES, 0); |
354 | 370 |
355 for (i = 0; i < cues->num_entries; i++) { | 371 for (i = 0; i < cues->num_entries; i++) { |
356 offset_t cuepoint, track_positions; | 372 ebml_master cuepoint, track_positions; |
357 mkv_cuepoint *entry = &cues->entries[i]; | 373 mkv_cuepoint *entry = &cues->entries[i]; |
358 uint64_t pts = entry->pts; | 374 uint64_t pts = entry->pts; |
359 | 375 |
360 cuepoint = start_ebml_master(pb, MATROSKA_ID_POINTENTRY); | 376 cuepoint = start_ebml_master(pb, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_SIZE(num_tracks)); |
361 put_ebml_uint(pb, MATROSKA_ID_CUETIME, pts); | 377 put_ebml_uint(pb, MATROSKA_ID_CUETIME, pts); |
362 | 378 |
363 // put all the entries from different tracks that have the exact same | 379 // put all the entries from different tracks that have the exact same |
364 // timestamp into the same CuePoint | 380 // timestamp into the same CuePoint |
365 for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { | 381 for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { |
366 track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION); | 382 track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); |
367 put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum ); | 383 put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum ); |
368 put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos); | 384 put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos); |
369 end_ebml_master(pb, track_positions); | 385 end_ebml_master(pb, track_positions); |
370 } | 386 } |
371 i += j - 1; | 387 i += j - 1; |
378 return currentpos; | 394 return currentpos; |
379 } | 395 } |
380 | 396 |
381 static int put_xiph_codecpriv(ByteIOContext *pb, AVCodecContext *codec) | 397 static int put_xiph_codecpriv(ByteIOContext *pb, AVCodecContext *codec) |
382 { | 398 { |
383 offset_t codecprivate; | 399 ebml_master codecprivate; |
384 uint8_t *header_start[3]; | 400 uint8_t *header_start[3]; |
385 int header_len[3]; | 401 int header_len[3]; |
386 int first_header_size; | 402 int first_header_size; |
387 int j; | 403 int j; |
388 | 404 |
395 first_header_size, header_start, header_len) < 0) { | 411 first_header_size, header_start, header_len) < 0) { |
396 av_log(codec, AV_LOG_ERROR, "Extradata corrupt.\n"); | 412 av_log(codec, AV_LOG_ERROR, "Extradata corrupt.\n"); |
397 return -1; | 413 return -1; |
398 } | 414 } |
399 | 415 |
400 codecprivate = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE); | 416 codecprivate = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE, 0); |
401 put_byte(pb, 2); // number packets - 1 | 417 put_byte(pb, 2); // number packets - 1 |
402 for (j = 0; j < 2; j++) { | 418 for (j = 0; j < 2; j++) { |
403 put_xiph_size(pb, header_len[j]); | 419 put_xiph_size(pb, header_len[j]); |
404 } | 420 } |
405 for (j = 0; j < 3; j++) | 421 for (j = 0; j < 3; j++) |
411 | 427 |
412 #define FLAC_STREAMINFO_SIZE 34 | 428 #define FLAC_STREAMINFO_SIZE 34 |
413 | 429 |
414 static int put_flac_codecpriv(ByteIOContext *pb, AVCodecContext *codec) | 430 static int put_flac_codecpriv(ByteIOContext *pb, AVCodecContext *codec) |
415 { | 431 { |
416 offset_t codecpriv = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE); | 432 ebml_master codecpriv = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE, 0); |
417 | 433 |
418 // if the extradata_size is greater than FLAC_STREAMINFO_SIZE, | 434 // if the extradata_size is greater than FLAC_STREAMINFO_SIZE, |
419 // assume that it's in Matroska's format already | 435 // assume that it's in Matroska's format already |
420 if (codec->extradata_size < FLAC_STREAMINFO_SIZE) { | 436 if (codec->extradata_size < FLAC_STREAMINFO_SIZE) { |
421 av_log(codec, AV_LOG_ERROR, "Invalid FLAC extradata\n"); | 437 av_log(codec, AV_LOG_ERROR, "Invalid FLAC extradata\n"); |
464 | 480 |
465 static int mkv_write_tracks(AVFormatContext *s) | 481 static int mkv_write_tracks(AVFormatContext *s) |
466 { | 482 { |
467 MatroskaMuxContext *mkv = s->priv_data; | 483 MatroskaMuxContext *mkv = s->priv_data; |
468 ByteIOContext *pb = &s->pb; | 484 ByteIOContext *pb = &s->pb; |
469 offset_t tracks; | 485 ebml_master tracks; |
470 int i, j; | 486 int i, j; |
471 | 487 |
472 if (mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, url_ftell(pb)) < 0) | 488 if (mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, url_ftell(pb)) < 0) |
473 return -1; | 489 return -1; |
474 | 490 |
475 tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS); | 491 tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0); |
476 for (i = 0; i < s->nb_streams; i++) { | 492 for (i = 0; i < s->nb_streams; i++) { |
477 AVStream *st = s->streams[i]; | 493 AVStream *st = s->streams[i]; |
478 AVCodecContext *codec = st->codec; | 494 AVCodecContext *codec = st->codec; |
479 offset_t subinfo, track; | 495 ebml_master subinfo, track; |
480 int native_id = 0; | 496 int native_id = 0; |
481 int bit_depth = av_get_bits_per_sample(codec->codec_id); | 497 int bit_depth = av_get_bits_per_sample(codec->codec_id); |
482 int sample_rate = codec->sample_rate; | 498 int sample_rate = codec->sample_rate; |
483 int output_sample_rate = 0; | 499 int output_sample_rate = 0; |
484 | 500 |
485 if (codec->codec_id == CODEC_ID_AAC) | 501 if (codec->codec_id == CODEC_ID_AAC) |
486 get_aac_sample_rates(codec, &sample_rate, &output_sample_rate); | 502 get_aac_sample_rates(codec, &sample_rate, &output_sample_rate); |
487 | 503 |
488 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY); | 504 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); |
489 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); | 505 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); |
490 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); | 506 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); |
491 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) | 507 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) |
492 | 508 |
493 if (st->language[0]) | 509 if (st->language[0]) |
519 switch (codec->codec_type) { | 535 switch (codec->codec_type) { |
520 case CODEC_TYPE_VIDEO: | 536 case CODEC_TYPE_VIDEO: |
521 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); | 537 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO); |
522 | 538 |
523 if (!native_id) { | 539 if (!native_id) { |
524 offset_t bmp_header; | 540 ebml_master bmp_header; |
525 // if there is no mkv-specific codec id, use VFW mode | 541 // if there is no mkv-specific codec id, use VFW mode |
526 if (!codec->codec_tag) | 542 if (!codec->codec_tag) |
527 codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id); | 543 codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id); |
528 | 544 |
529 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC); | 545 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC); |
530 bmp_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE); | 546 bmp_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE, 0); |
531 put_bmp_header(pb, codec, codec_bmp_tags, 0); | 547 put_bmp_header(pb, codec, codec_bmp_tags, 0); |
532 end_ebml_master(pb, bmp_header); | 548 end_ebml_master(pb, bmp_header); |
533 } | 549 } |
534 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO); | 550 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); |
535 // XXX: interlace flag? | 551 // XXX: interlace flag? |
536 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); | 552 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); |
537 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); | 553 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); |
538 if (codec->sample_aspect_ratio.num) { | 554 if (codec->sample_aspect_ratio.num) { |
539 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->sample_aspect_ratio.num); | 555 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->sample_aspect_ratio.num); |
544 | 560 |
545 case CODEC_TYPE_AUDIO: | 561 case CODEC_TYPE_AUDIO: |
546 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); | 562 put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); |
547 | 563 |
548 if (!native_id) { | 564 if (!native_id) { |
549 offset_t wav_header; | 565 ebml_master wav_header; |
550 // no mkv-specific ID, use ACM mode | 566 // no mkv-specific ID, use ACM mode |
551 codec->codec_tag = codec_get_tag(codec_wav_tags, codec->codec_id); | 567 codec->codec_tag = codec_get_tag(codec_wav_tags, codec->codec_id); |
552 if (!codec->codec_tag) { | 568 if (!codec->codec_tag) { |
553 av_log(s, AV_LOG_ERROR, "no codec id found for stream %d", i); | 569 av_log(s, AV_LOG_ERROR, "no codec id found for stream %d", i); |
554 return -1; | 570 return -1; |
555 } | 571 } |
556 | 572 |
557 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_AUDIO_ACM); | 573 put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_AUDIO_ACM); |
558 wav_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE); | 574 wav_header = start_ebml_master(pb, MATROSKA_ID_CODECPRIVATE, 0); |
559 put_wav_header(pb, codec); | 575 put_wav_header(pb, codec); |
560 end_ebml_master(pb, wav_header); | 576 end_ebml_master(pb, wav_header); |
561 } | 577 } |
562 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO); | 578 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0); |
563 put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels); | 579 put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , codec->channels); |
564 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); | 580 put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); |
565 if (output_sample_rate) | 581 if (output_sample_rate) |
566 put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); | 582 put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); |
567 if (bit_depth) | 583 if (bit_depth) |
587 | 603 |
588 static int mkv_write_header(AVFormatContext *s) | 604 static int mkv_write_header(AVFormatContext *s) |
589 { | 605 { |
590 MatroskaMuxContext *mkv = s->priv_data; | 606 MatroskaMuxContext *mkv = s->priv_data; |
591 ByteIOContext *pb = &s->pb; | 607 ByteIOContext *pb = &s->pb; |
592 offset_t ebml_header, segment_info; | 608 ebml_master ebml_header, segment_info; |
593 | 609 |
594 mkv->md5_ctx = av_mallocz(av_md5_size); | 610 mkv->md5_ctx = av_mallocz(av_md5_size); |
595 av_md5_init(mkv->md5_ctx); | 611 av_md5_init(mkv->md5_ctx); |
596 | 612 |
597 ebml_header = start_ebml_master(pb, EBML_ID_HEADER); | 613 ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); |
598 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); | 614 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); |
599 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); | 615 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); |
600 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); | 616 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); |
601 put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); | 617 put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); |
602 put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska"); | 618 put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska"); |
603 put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); | 619 put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); |
604 put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); | 620 put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); |
605 end_ebml_master(pb, ebml_header); | 621 end_ebml_master(pb, ebml_header); |
606 | 622 |
607 mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT); | 623 mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0); |
608 mkv->segment_offset = url_ftell(pb); | 624 mkv->segment_offset = url_ftell(pb); |
609 | 625 |
610 // we write 2 seek heads - one at the end of the file to point to each cluster, and | 626 // we write 2 seek heads - one at the end of the file to point to each cluster, and |
611 // one at the beginning to point to all other level one elements (including the seek | 627 // one at the beginning to point to all other level one elements (including the seek |
612 // head at the end of the file), which isn't more than 10 elements if we only write one | 628 // head at the end of the file), which isn't more than 10 elements if we only write one |
615 mkv->cluster_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 0); | 631 mkv->cluster_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 0); |
616 | 632 |
617 if (mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, url_ftell(pb)) < 0) | 633 if (mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, url_ftell(pb)) < 0) |
618 return -1; | 634 return -1; |
619 | 635 |
620 segment_info = start_ebml_master(pb, MATROSKA_ID_INFO); | 636 segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0); |
621 put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); | 637 put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); |
622 if (strlen(s->title)) | 638 if (strlen(s->title)) |
623 put_ebml_string(pb, MATROSKA_ID_TITLE, s->title); | 639 put_ebml_string(pb, MATROSKA_ID_TITLE, s->title); |
624 if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { | 640 if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { |
625 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT); | 641 put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT); |
641 | 657 |
642 if (mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)) < 0) | 658 if (mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)) < 0) |
643 return -1; | 659 return -1; |
644 | 660 |
645 mkv->cluster_pos = url_ftell(pb); | 661 mkv->cluster_pos = url_ftell(pb); |
646 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER); | 662 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); |
647 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0); | 663 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0); |
648 mkv->cluster_pts = 0; | 664 mkv->cluster_pts = 0; |
649 | 665 |
650 mkv->cues = mkv_start_cues(mkv->segment_offset); | 666 mkv->cues = mkv_start_cues(mkv->segment_offset); |
651 if (mkv->cues == NULL) | 667 if (mkv->cues == NULL) |
652 return -1; | 668 return -1; |
653 | 669 |
654 return 0; | 670 return 0; |
671 } | |
672 | |
673 static int mkv_block_size(AVPacket *pkt) | |
674 { | |
675 int size = 4; // track num + timecode + flags | |
676 return size + pkt->size; | |
677 } | |
678 | |
679 static int mkv_blockgroup_size(AVPacket *pkt) | |
680 { | |
681 int size = mkv_block_size(pkt); | |
682 size += ebml_size_bytes(size); | |
683 size += 2; // EBML ID for block and block duration | |
684 size += 8; // max size of block duration | |
685 size += ebml_size_bytes(size); | |
686 size += 1; // blockgroup EBML ID | |
687 return size; | |
655 } | 688 } |
656 | 689 |
657 static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *pkt, int flags) | 690 static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *pkt, int flags) |
658 { | 691 { |
659 MatroskaMuxContext *mkv = s->priv_data; | 692 MatroskaMuxContext *mkv = s->priv_data; |
660 ByteIOContext *pb = &s->pb; | 693 ByteIOContext *pb = &s->pb; |
661 | 694 |
662 av_log(s, AV_LOG_DEBUG, "Writing block at offset %llu, size %d, pts %lld, dts %lld, duration %d, flags %d\n", | 695 av_log(s, AV_LOG_DEBUG, "Writing block at offset %llu, size %d, pts %lld, dts %lld, duration %d, flags %d\n", |
663 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); | 696 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); |
664 put_ebml_id(pb, blockid); | 697 put_ebml_id(pb, blockid); |
665 put_ebml_size(pb, pkt->size + 4, 0); | 698 put_ebml_size(pb, mkv_block_size(pkt), 0); |
666 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 | 699 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 |
667 put_be16(pb, pkt->pts - mkv->cluster_pts); | 700 put_be16(pb, pkt->pts - mkv->cluster_pts); |
668 put_byte(pb, flags); | 701 put_byte(pb, flags); |
669 put_buffer(pb, pkt->data, pkt->size); | 702 put_buffer(pb, pkt->data, pkt->size); |
670 } | 703 } |
683 | 716 |
684 if (mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)) < 0) | 717 if (mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)) < 0) |
685 return -1; | 718 return -1; |
686 | 719 |
687 mkv->cluster_pos = url_ftell(pb); | 720 mkv->cluster_pos = url_ftell(pb); |
688 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER); | 721 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); |
689 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts); | 722 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts); |
690 mkv->cluster_pts = pkt->pts; | 723 mkv->cluster_pts = pkt->pts; |
691 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size)); | 724 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size)); |
692 } | 725 } |
693 | 726 |
694 if (codec->codec_type != CODEC_TYPE_SUBTITLE) { | 727 if (codec->codec_type != CODEC_TYPE_SUBTITLE) { |
695 mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); | 728 mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); |
696 } else { | 729 } else { |
697 offset_t blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP); | 730 ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt)); |
698 mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0); | 731 mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0); |
699 put_ebml_uint(pb, MATROSKA_ID_DURATION, pkt->duration); | 732 put_ebml_uint(pb, MATROSKA_ID_DURATION, pkt->duration); |
700 end_ebml_master(pb, blockgroup); | 733 end_ebml_master(pb, blockgroup); |
701 } | 734 } |
702 | 735 |
715 ByteIOContext *pb = &s->pb; | 748 ByteIOContext *pb = &s->pb; |
716 offset_t currentpos, second_seekhead, cuespos; | 749 offset_t currentpos, second_seekhead, cuespos; |
717 | 750 |
718 end_ebml_master(pb, mkv->cluster); | 751 end_ebml_master(pb, mkv->cluster); |
719 | 752 |
720 cuespos = mkv_write_cues(pb, mkv->cues); | 753 cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
721 second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead); | 754 second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead); |
722 | 755 |
723 mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos); | 756 mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos); |
724 mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEAD, second_seekhead); | 757 mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEAD, second_seekhead); |
725 mkv_write_seekhead(pb, mkv->main_seekhead); | 758 mkv_write_seekhead(pb, mkv->main_seekhead); |