OLD | NEW |
1 /* | 1 /* |
2 * Matroska muxer | 2 * Matroska muxer |
3 * Copyright (c) 2007 David Conrad | 3 * Copyright (c) 2007 David Conrad |
4 * | 4 * |
5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
6 * | 6 * |
7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 int tracknum; | 54 int tracknum; |
55 int64_t cluster_pos; ///< file offset of the cluster containi
ng the block | 55 int64_t cluster_pos; ///< file offset of the cluster containi
ng the block |
56 } mkv_cuepoint; | 56 } mkv_cuepoint; |
57 | 57 |
58 typedef struct { | 58 typedef struct { |
59 int64_t segment_offset; | 59 int64_t segment_offset; |
60 mkv_cuepoint *entries; | 60 mkv_cuepoint *entries; |
61 int num_entries; | 61 int num_entries; |
62 } mkv_cues; | 62 } mkv_cues; |
63 | 63 |
| 64 typedef struct { |
| 65 int write_dts; |
| 66 } mkv_track; |
| 67 |
64 typedef struct MatroskaMuxContext { | 68 typedef struct MatroskaMuxContext { |
| 69 ByteIOContext *dyn_bc; |
65 ebml_master segment; | 70 ebml_master segment; |
66 int64_t segment_offset; | 71 int64_t segment_offset; |
67 int64_t segment_uid; | 72 int64_t segment_uid; |
68 ebml_master cluster; | 73 ebml_master cluster; |
69 int64_t cluster_pos; ///< file offset of the current cluster | 74 int64_t cluster_pos; ///< file offset of the current cluster |
70 uint64_t cluster_pts; | 75 int64_t cluster_pts; |
71 int64_t duration_offset; | 76 int64_t duration_offset; |
72 uint64_t duration; | 77 int64_t duration; |
73 mkv_seekhead *main_seekhead; | 78 mkv_seekhead *main_seekhead; |
74 mkv_seekhead *cluster_seekhead; | 79 mkv_seekhead *cluster_seekhead; |
75 mkv_cues *cues; | 80 mkv_cues *cues; |
| 81 mkv_track *tracks; |
76 | 82 |
77 struct AVMD5 *md5_ctx; | 83 struct AVMD5 *md5_ctx; |
78 } MatroskaMuxContext; | 84 } MatroskaMuxContext; |
79 | 85 |
80 | 86 |
81 /** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit | 87 /** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit |
82 * offset, 4 bytes for target EBML ID */ | 88 * offset, 4 bytes for target EBML ID */ |
83 #define MAX_SEEKENTRY_SIZE 21 | 89 #define MAX_SEEKENTRY_SIZE 21 |
84 | 90 |
85 /** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2 | 91 /** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 int bytes = expectedsize ? ebml_num_size(expectedsize) : 8; | 217 int bytes = expectedsize ? ebml_num_size(expectedsize) : 8; |
212 put_ebml_id(pb, elementid); | 218 put_ebml_id(pb, elementid); |
213 put_ebml_size_unknown(pb, bytes); | 219 put_ebml_size_unknown(pb, bytes); |
214 return (ebml_master){ url_ftell(pb), bytes }; | 220 return (ebml_master){ url_ftell(pb), bytes }; |
215 } | 221 } |
216 | 222 |
217 static void end_ebml_master(ByteIOContext *pb, ebml_master master) | 223 static void end_ebml_master(ByteIOContext *pb, ebml_master master) |
218 { | 224 { |
219 int64_t pos = url_ftell(pb); | 225 int64_t pos = url_ftell(pb); |
220 | 226 |
221 // leave the unknown size for masters when streaming | 227 if (url_fseek(pb, master.pos - master.sizebytes, SEEK_SET) < 0) |
222 if (url_is_streamed(pb)) | |
223 return; | 228 return; |
224 | |
225 url_fseek(pb, master.pos - master.sizebytes, SEEK_SET); | |
226 put_ebml_num(pb, pos - master.pos, master.sizebytes); | 229 put_ebml_num(pb, pos - master.pos, master.sizebytes); |
227 url_fseek(pb, pos, SEEK_SET); | 230 url_fseek(pb, pos, SEEK_SET); |
228 } | 231 } |
229 | 232 |
230 static void put_xiph_size(ByteIOContext *pb, int size) | 233 static void put_xiph_size(ByteIOContext *pb, int size) |
231 { | 234 { |
232 int i; | 235 int i; |
233 for (i = 0; i < size / 255; i++) | 236 for (i = 0; i < size / 255; i++) |
234 put_byte(pb, 255); | 237 put_byte(pb, 255); |
235 put_byte(pb, size % 255); | 238 put_byte(pb, size % 255); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 seekhead->entries = entries; | 287 seekhead->entries = entries; |
285 return 0; | 288 return 0; |
286 } | 289 } |
287 | 290 |
288 /** | 291 /** |
289 * Write the seek head to the file and free it. If a maximum number of | 292 * Write the seek head to the file and free it. If a maximum number of |
290 * elements was specified to mkv_start_seekhead(), the seek head will | 293 * elements was specified to mkv_start_seekhead(), the seek head will |
291 * be written at the location reserved for it. Otherwise, it is written | 294 * be written at the location reserved for it. Otherwise, it is written |
292 * at the current location in the file. | 295 * at the current location in the file. |
293 * | 296 * |
294 * @return The file offset where the seekhead was written. | 297 * @return The file offset where the seekhead was written, |
| 298 * -1 if an error occurred. |
295 */ | 299 */ |
296 static int64_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead) | 300 static int64_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead) |
297 { | 301 { |
298 ebml_master metaseek, seekentry; | 302 ebml_master metaseek, seekentry; |
299 int64_t currentpos; | 303 int64_t currentpos; |
300 int i; | 304 int i; |
301 | 305 |
302 currentpos = url_ftell(pb); | 306 currentpos = url_ftell(pb); |
303 | 307 |
304 if (seekhead->reserved_size > 0) | 308 if (seekhead->reserved_size > 0) |
305 url_fseek(pb, seekhead->filepos, SEEK_SET); | 309 if (url_fseek(pb, seekhead->filepos, SEEK_SET) < 0) |
| 310 return -1; |
306 | 311 |
307 metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_si
ze); | 312 metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_si
ze); |
308 for (i = 0; i < seekhead->num_entries; i++) { | 313 for (i = 0; i < seekhead->num_entries; i++) { |
309 mkv_seekhead_entry *entry = &seekhead->entries[i]; | 314 mkv_seekhead_entry *entry = &seekhead->entries[i]; |
310 | 315 |
311 seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_S
IZE); | 316 seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_S
IZE); |
312 | 317 |
313 put_ebml_id(pb, MATROSKA_ID_SEEKID); | 318 put_ebml_id(pb, MATROSKA_ID_SEEKID); |
314 put_ebml_num(pb, ebml_id_size(entry->elementid), 0); | 319 put_ebml_num(pb, ebml_id_size(entry->elementid), 0); |
315 put_ebml_id(pb, entry->elementid); | 320 put_ebml_id(pb, entry->elementid); |
(...skipping 19 matching lines...) Expand all Loading... |
335 static mkv_cues * mkv_start_cues(int64_t segment_offset) | 340 static mkv_cues * mkv_start_cues(int64_t segment_offset) |
336 { | 341 { |
337 mkv_cues *cues = av_mallocz(sizeof(mkv_cues)); | 342 mkv_cues *cues = av_mallocz(sizeof(mkv_cues)); |
338 if (cues == NULL) | 343 if (cues == NULL) |
339 return NULL; | 344 return NULL; |
340 | 345 |
341 cues->segment_offset = segment_offset; | 346 cues->segment_offset = segment_offset; |
342 return cues; | 347 return cues; |
343 } | 348 } |
344 | 349 |
345 static int mkv_add_cuepoint(mkv_cues *cues, AVPacket *pkt, int64_t cluster_pos) | 350 static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus
ter_pos) |
346 { | 351 { |
347 mkv_cuepoint *entries = cues->entries; | 352 mkv_cuepoint *entries = cues->entries; |
348 | 353 |
349 entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint)
); | 354 entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint)
); |
350 if (entries == NULL) | 355 if (entries == NULL) |
351 return AVERROR(ENOMEM); | 356 return AVERROR(ENOMEM); |
352 | 357 |
353 entries[cues->num_entries ].pts = pkt->pts; | 358 if (ts < 0) |
354 entries[cues->num_entries ].tracknum = pkt->stream_index + 1; | 359 return 0; |
| 360 |
| 361 entries[cues->num_entries ].pts = ts; |
| 362 entries[cues->num_entries ].tracknum = stream + 1; |
355 entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offse
t; | 363 entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offse
t; |
356 | 364 |
357 cues->entries = entries; | 365 cues->entries = entries; |
358 return 0; | 366 return 0; |
359 } | 367 } |
360 | 368 |
361 static int64_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks) | 369 static int64_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks) |
362 { | 370 { |
363 ebml_master cues_element; | 371 ebml_master cues_element; |
364 int64_t currentpos; | 372 int64_t currentpos; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_
size); | 475 ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_
size); |
468 else if (codec->extradata_size) | 476 else if (codec->extradata_size) |
469 put_buffer(dyn_cp, codec->extradata, codec->extradata_size); | 477 put_buffer(dyn_cp, codec->extradata, codec->extradata_size); |
470 } else if (codec->codec_type == CODEC_TYPE_VIDEO) { | 478 } else if (codec->codec_type == CODEC_TYPE_VIDEO) { |
471 if (qt_id) { | 479 if (qt_id) { |
472 if (!codec->codec_tag) | 480 if (!codec->codec_tag) |
473 codec->codec_tag = ff_codec_get_tag(codec_movvideo_tags, codec->
codec_id); | 481 codec->codec_tag = ff_codec_get_tag(codec_movvideo_tags, codec->
codec_id); |
474 if (codec->extradata_size) | 482 if (codec->extradata_size) |
475 put_buffer(dyn_cp, codec->extradata, codec->extradata_size); | 483 put_buffer(dyn_cp, codec->extradata, codec->extradata_size); |
476 } else { | 484 } else { |
477 if (!codec->codec_tag) | 485 if (!codec->codec_tag) |
478 codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_
id); | 486 codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags, codec->co
dec_id); |
479 if (!codec->codec_tag) { | 487 if (!codec->codec_tag) { |
480 av_log(s, AV_LOG_ERROR, "No bmp codec ID found."); | 488 av_log(s, AV_LOG_ERROR, "No bmp codec ID found."); |
481 ret = -1; | 489 ret = -1; |
482 } | 490 } |
483 | 491 |
484 ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0); | 492 ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0); |
485 } | 493 } |
486 | 494 |
487 } else if (codec->codec_type == CODEC_TYPE_AUDIO) { | 495 } else if (codec->codec_type == CODEC_TYPE_AUDIO) { |
488 if (!codec->codec_tag) | 496 if (!codec->codec_tag) |
489 codec->codec_tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_
id); | 497 codec->codec_tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_
id); |
490 if (!codec->codec_tag) { | 498 if (!codec->codec_tag) { |
491 av_log(s, AV_LOG_ERROR, "No wav codec ID found."); | 499 av_log(s, AV_LOG_ERROR, "No wav codec ID found."); |
492 ret = -1; | 500 ret = -1; |
493 } | 501 } |
494 | 502 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 | 537 |
530 if (codec->codec_id == CODEC_ID_AAC) | 538 if (codec->codec_id == CODEC_ID_AAC) |
531 get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); | 539 get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate); |
532 | 540 |
533 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); | 541 track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); |
534 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); | 542 put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER , i + 1); |
535 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); | 543 put_ebml_uint (pb, MATROSKA_ID_TRACKUID , i + 1); |
536 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (ye
t) | 544 put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (ye
t) |
537 put_ebml_float(pb, MATROSKA_ID_TRACKTIMECODESCALE, 1.0); | 545 put_ebml_float(pb, MATROSKA_ID_TRACKTIMECODESCALE, 1.0); |
538 | 546 |
539 if ((tag = av_metadata_get(st->metadata, "description", NULL, 0))) | 547 if ((tag = av_metadata_get(st->metadata, "title", NULL, 0))) |
540 put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); | 548 put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); |
541 tag = av_metadata_get(st->metadata, "language", NULL, 0); | 549 tag = av_metadata_get(st->metadata, "language", NULL, 0); |
542 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); | 550 put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); |
543 | 551 |
544 if (st->disposition) | 552 if (st->disposition) |
545 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition &
AV_DISPOSITION_DEFAULT)); | 553 put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition &
AV_DISPOSITION_DEFAULT)); |
546 | 554 |
547 // look for a codec ID string specific to mkv to use, | 555 // look for a codec ID string specific to mkv to use, |
548 // if none are found, use AVI codes | 556 // if none are found, use AVI codes |
549 for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) { | 557 for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) { |
(...skipping 11 matching lines...) Expand all Loading... |
561 if (!native_id && | 569 if (!native_id && |
562 ff_codec_get_tag(codec_movvideo_tags, codec->codec_id) && | 570 ff_codec_get_tag(codec_movvideo_tags, codec->codec_id) && |
563 (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id) | 571 (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id) |
564 || codec->codec_id == CODEC_ID_SVQ1 | 572 || codec->codec_id == CODEC_ID_SVQ1 |
565 || codec->codec_id == CODEC_ID_SVQ3 | 573 || codec->codec_id == CODEC_ID_SVQ3 |
566 || codec->codec_id == CODEC_ID_CINEPAK)) | 574 || codec->codec_id == CODEC_ID_CINEPAK)) |
567 qt_id = 1; | 575 qt_id = 1; |
568 | 576 |
569 if (qt_id) | 577 if (qt_id) |
570 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); | 578 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); |
571 else if (!native_id) | 579 else if (!native_id) { |
572 // if there is no mkv-specific codec ID, use VFW mode | 580 // if there is no mkv-specific codec ID, use VFW mode |
573 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); | 581 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); |
| 582 mkv->tracks[i].write_dts = 1; |
| 583 } |
574 | 584 |
575 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); | 585 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); |
576 // XXX: interlace flag? | 586 // XXX: interlace flag? |
577 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); | 587 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); |
578 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); | 588 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); |
579 if (st->sample_aspect_ratio.num) { | 589 if (st->sample_aspect_ratio.num) { |
580 int d_width = codec->width*av_q2d(st->sample_aspect_ratio); | 590 int d_width = codec->width*av_q2d(st->sample_aspect_ratio); |
581 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); | 591 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width); |
582 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->hei
ght); | 592 put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->hei
ght); |
583 } | 593 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 static int mkv_write_header(AVFormatContext *s) | 677 static int mkv_write_header(AVFormatContext *s) |
668 { | 678 { |
669 MatroskaMuxContext *mkv = s->priv_data; | 679 MatroskaMuxContext *mkv = s->priv_data; |
670 ByteIOContext *pb = s->pb; | 680 ByteIOContext *pb = s->pb; |
671 ebml_master ebml_header, segment_info; | 681 ebml_master ebml_header, segment_info; |
672 AVMetadataTag *tag; | 682 AVMetadataTag *tag; |
673 int ret; | 683 int ret; |
674 | 684 |
675 mkv->md5_ctx = av_mallocz(av_md5_size); | 685 mkv->md5_ctx = av_mallocz(av_md5_size); |
676 av_md5_init(mkv->md5_ctx); | 686 av_md5_init(mkv->md5_ctx); |
| 687 mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks)); |
677 | 688 |
678 ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); | 689 ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); |
679 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); | 690 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); |
680 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); | 691 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); |
681 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); | 692 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); |
682 put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); | 693 put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); |
683 put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska"); | 694 put_ebml_string (pb, EBML_ID_DOCTYPE , "matroska"); |
684 put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); | 695 put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , 2); |
685 put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); | 696 put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION , 2); |
686 end_ebml_master(pb, ebml_header); | 697 end_ebml_master(pb, ebml_header); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 mkv->duration_offset = url_ftell(pb); | 730 mkv->duration_offset = url_ftell(pb); |
720 put_ebml_void(pb, 11); // assumes double-precision float to
be written | 731 put_ebml_void(pb, 11); // assumes double-precision float to
be written |
721 end_ebml_master(pb, segment_info); | 732 end_ebml_master(pb, segment_info); |
722 | 733 |
723 ret = mkv_write_tracks(s); | 734 ret = mkv_write_tracks(s); |
724 if (ret < 0) return ret; | 735 if (ret < 0) return ret; |
725 | 736 |
726 ret = mkv_write_chapters(s); | 737 ret = mkv_write_chapters(s); |
727 if (ret < 0) return ret; | 738 if (ret < 0) return ret; |
728 | 739 |
729 ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url
_ftell(pb)); | 740 if (url_is_streamed(s->pb)) |
730 if (ret < 0) return ret; | 741 mkv_write_seekhead(pb, mkv->main_seekhead); |
731 | |
732 mkv->cluster_pos = url_ftell(pb); | |
733 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); | |
734 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0); | |
735 mkv->cluster_pts = 0; | |
736 | 742 |
737 mkv->cues = mkv_start_cues(mkv->segment_offset); | 743 mkv->cues = mkv_start_cues(mkv->segment_offset); |
738 if (mkv->cues == NULL) | 744 if (mkv->cues == NULL) |
739 return AVERROR(ENOMEM); | 745 return AVERROR(ENOMEM); |
740 | 746 |
741 put_flush_packet(pb); | 747 put_flush_packet(pb); |
742 return 0; | 748 return 0; |
743 } | 749 } |
744 | 750 |
745 static int mkv_blockgroup_size(int pkt_size) | 751 static int mkv_blockgroup_size(int pkt_size) |
(...skipping 13 matching lines...) Expand all Loading... |
759 uint64_t start, end; | 765 uint64_t start, end; |
760 | 766 |
761 if (sscanf(p, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d", | 767 if (sscanf(p, "%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d", |
762 &sh, &sm, &ss, &sc, &eh, &em, &es, &ec) != 8) | 768 &sh, &sm, &ss, &sc, &eh, &em, &es, &ec) != 8) |
763 return 0; | 769 return 0; |
764 start = 3600000*sh + 60000*sm + 1000*ss + 10*sc; | 770 start = 3600000*sh + 60000*sm + 1000*ss + 10*sc; |
765 end = 3600000*eh + 60000*em + 1000*es + 10*ec; | 771 end = 3600000*eh + 60000*em + 1000*es + 10*ec; |
766 return end - start; | 772 return end - start; |
767 } | 773 } |
768 | 774 |
769 static int mkv_write_ass_blocks(AVFormatContext *s, AVPacket *pkt) | 775 static int mkv_write_ass_blocks(AVFormatContext *s, ByteIOContext *pb, AVPacket
*pkt) |
770 { | 776 { |
771 MatroskaMuxContext *mkv = s->priv_data; | 777 MatroskaMuxContext *mkv = s->priv_data; |
772 ByteIOContext *pb = s->pb; | |
773 int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size; | 778 int i, layer = 0, max_duration = 0, size, line_size, data_size = pkt->size; |
774 uint8_t *start, *end, *data = pkt->data; | 779 uint8_t *start, *end, *data = pkt->data; |
775 ebml_master blockgroup; | 780 ebml_master blockgroup; |
776 char buffer[2048]; | 781 char buffer[2048]; |
777 | 782 |
778 while (data_size) { | 783 while (data_size) { |
779 int duration = ass_get_duration(data); | 784 int duration = ass_get_duration(data); |
780 max_duration = FFMAX(duration, max_duration); | 785 max_duration = FFMAX(duration, max_duration); |
781 end = memchr(data, '\n', data_size); | 786 end = memchr(data, '\n', data_size); |
782 size = line_size = end ? end-data+1 : data_size; | 787 size = line_size = end ? end-data+1 : data_size; |
(...skipping 22 matching lines...) Expand all Loading... |
805 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); | 810 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); |
806 end_ebml_master(pb, blockgroup); | 811 end_ebml_master(pb, blockgroup); |
807 | 812 |
808 data += line_size; | 813 data += line_size; |
809 data_size -= line_size; | 814 data_size -= line_size; |
810 } | 815 } |
811 | 816 |
812 return max_duration; | 817 return max_duration; |
813 } | 818 } |
814 | 819 |
815 static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *
pkt, int flags) | 820 static void mkv_write_block(AVFormatContext *s, ByteIOContext *pb, |
| 821 unsigned int blockid, AVPacket *pkt, int flags) |
816 { | 822 { |
817 MatroskaMuxContext *mkv = s->priv_data; | 823 MatroskaMuxContext *mkv = s->priv_data; |
818 ByteIOContext *pb = s->pb; | |
819 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; | 824 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
820 uint8_t *data = NULL; | 825 uint8_t *data = NULL; |
821 int size = pkt->size; | 826 int size = pkt->size; |
| 827 int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; |
822 | 828 |
823 av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " | 829 av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " |
824 "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", | 830 "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", |
825 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); | 831 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); |
826 if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 && | 832 if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 && |
827 (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) | 833 (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) |
828 ff_avc_parse_nal_units_buf(pkt->data, &data, &size); | 834 ff_avc_parse_nal_units_buf(pkt->data, &data, &size); |
829 else | 835 else |
830 data = pkt->data; | 836 data = pkt->data; |
831 put_ebml_id(pb, blockid); | 837 put_ebml_id(pb, blockid); |
832 put_ebml_num(pb, size+4, 0); | 838 put_ebml_num(pb, size+4, 0); |
833 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_ind
ex is less than 126 | 839 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_ind
ex is less than 126 |
834 put_be16(pb, pkt->pts - mkv->cluster_pts); | 840 put_be16(pb, ts - mkv->cluster_pts); |
835 put_byte(pb, flags); | 841 put_byte(pb, flags); |
836 put_buffer(pb, data, size); | 842 put_buffer(pb, data, size); |
837 if (data != pkt->data) | 843 if (data != pkt->data) |
838 av_free(data); | 844 av_free(data); |
839 } | 845 } |
840 | 846 |
| 847 static void mkv_flush_dynbuf(AVFormatContext *s) |
| 848 { |
| 849 MatroskaMuxContext *mkv = s->priv_data; |
| 850 int bufsize; |
| 851 uint8_t *dyn_buf; |
| 852 |
| 853 if (!mkv->dyn_bc) |
| 854 return; |
| 855 |
| 856 bufsize = url_close_dyn_buf(mkv->dyn_bc, &dyn_buf); |
| 857 put_buffer(s->pb, dyn_buf, bufsize); |
| 858 av_free(dyn_buf); |
| 859 mkv->dyn_bc = NULL; |
| 860 } |
| 861 |
841 static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) | 862 static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) |
842 { | 863 { |
843 MatroskaMuxContext *mkv = s->priv_data; | 864 MatroskaMuxContext *mkv = s->priv_data; |
844 ByteIOContext *pb = s->pb; | 865 ByteIOContext *pb = s->pb; |
845 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; | 866 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
846 int keyframe = !!(pkt->flags & PKT_FLAG_KEY); | 867 int keyframe = !!(pkt->flags & PKT_FLAG_KEY); |
847 int duration = pkt->duration; | 868 int duration = pkt->duration; |
848 int ret; | 869 int ret; |
| 870 int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; |
849 | 871 |
850 // start a new cluster every 5 MB or 5 sec | 872 if (ts == AV_NOPTS_VALUE) { |
851 if (url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluste
r_pts + 5000) { | 873 av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); |
852 av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 | 874 return AVERROR(EINVAL); |
853 " bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts); | 875 } |
854 end_ebml_master(pb, mkv->cluster); | |
855 | 876 |
| 877 if (url_is_streamed(s->pb)) { |
| 878 if (!mkv->dyn_bc) |
| 879 url_open_dyn_buf(&mkv->dyn_bc); |
| 880 pb = mkv->dyn_bc; |
| 881 } |
| 882 |
| 883 if (!mkv->cluster_pos) { |
856 ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER,
url_ftell(pb)); | 884 ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER,
url_ftell(pb)); |
857 if (ret < 0) return ret; | 885 if (ret < 0) return ret; |
858 | 886 |
859 mkv->cluster_pos = url_ftell(pb); | 887 mkv->cluster_pos = url_ftell(s->pb); |
860 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); | 888 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); |
861 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts); | 889 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); |
862 mkv->cluster_pts = pkt->pts; | 890 mkv->cluster_pts = FFMAX(0, ts); |
863 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size)); | 891 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size)); |
864 } | 892 } |
865 | 893 |
866 if (codec->codec_type != CODEC_TYPE_SUBTITLE) { | 894 if (codec->codec_type != CODEC_TYPE_SUBTITLE) { |
867 mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); | 895 mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); |
868 } else if (codec->codec_id == CODEC_ID_SSA) { | 896 } else if (codec->codec_id == CODEC_ID_SSA) { |
869 duration = mkv_write_ass_blocks(s, pkt); | 897 duration = mkv_write_ass_blocks(s, pb, pkt); |
870 } else { | 898 } else { |
871 ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, m
kv_blockgroup_size(pkt->size)); | 899 ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, m
kv_blockgroup_size(pkt->size)); |
872 duration = pkt->convergence_duration; | 900 duration = pkt->convergence_duration; |
873 mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0); | 901 mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 0); |
874 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); | 902 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); |
875 end_ebml_master(pb, blockgroup); | 903 end_ebml_master(pb, blockgroup); |
876 } | 904 } |
877 | 905 |
878 if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) { | 906 if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) { |
879 ret = mkv_add_cuepoint(mkv->cues, pkt, mkv->cluster_pos); | 907 ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_po
s); |
880 if (ret < 0) return ret; | 908 if (ret < 0) return ret; |
881 } | 909 } |
882 | 910 |
883 mkv->duration = FFMAX(mkv->duration, pkt->pts + duration); | 911 // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming |
| 912 if (url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || ts > mkv->cluster_
pts + 1000) |
| 913 || url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || ts > mkv->cluster_
pts + 5000) { |
| 914 av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 |
| 915 " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts); |
| 916 end_ebml_master(pb, mkv->cluster); |
| 917 mkv->cluster_pos = 0; |
| 918 if (mkv->dyn_bc) |
| 919 mkv_flush_dynbuf(s); |
| 920 } |
| 921 |
| 922 mkv->duration = FFMAX(mkv->duration, ts + duration); |
884 return 0; | 923 return 0; |
885 } | 924 } |
886 | 925 |
887 static int mkv_write_trailer(AVFormatContext *s) | 926 static int mkv_write_trailer(AVFormatContext *s) |
888 { | 927 { |
889 MatroskaMuxContext *mkv = s->priv_data; | 928 MatroskaMuxContext *mkv = s->priv_data; |
890 ByteIOContext *pb = s->pb; | 929 ByteIOContext *pb = s->pb; |
891 int64_t currentpos, second_seekhead, cuespos; | 930 int64_t currentpos, second_seekhead, cuespos; |
892 int ret; | 931 int ret; |
893 | 932 |
894 end_ebml_master(pb, mkv->cluster); | 933 if (mkv->dyn_bc) { |
| 934 end_ebml_master(mkv->dyn_bc, mkv->cluster); |
| 935 mkv_flush_dynbuf(s); |
| 936 } else if (mkv->cluster_pos) { |
| 937 end_ebml_master(pb, mkv->cluster); |
| 938 } |
895 | 939 |
896 if (!url_is_streamed(pb)) { | 940 if (!url_is_streamed(pb)) { |
897 cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); | 941 cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
898 second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead); | 942 second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead); |
899 | 943 |
900 ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , c
uespos); | 944 ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , c
uespos); |
901 if (ret < 0) return ret; | 945 if (ret < 0) return ret; |
902 ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEAD, s
econd_seekhead); | 946 if (second_seekhead >= 0) { |
903 if (ret < 0) return ret; | 947 ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEA
D, second_seekhead); |
| 948 if (ret < 0) return ret; |
| 949 } |
904 mkv_write_seekhead(pb, mkv->main_seekhead); | 950 mkv_write_seekhead(pb, mkv->main_seekhead); |
905 | 951 |
906 // update the duration | 952 // update the duration |
907 av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); | 953 av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); |
908 currentpos = url_ftell(pb); | 954 currentpos = url_ftell(pb); |
909 url_fseek(pb, mkv->duration_offset, SEEK_SET); | 955 url_fseek(pb, mkv->duration_offset, SEEK_SET); |
910 put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration); | 956 put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration); |
911 | 957 |
912 // write the md5sum of some frames as the segment UID | 958 // write the md5sum of some frames as the segment UID |
913 if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { | 959 if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { |
914 uint8_t segment_uid[16]; | 960 uint8_t segment_uid[16]; |
915 av_md5_final(mkv->md5_ctx, segment_uid); | 961 av_md5_final(mkv->md5_ctx, segment_uid); |
916 url_fseek(pb, mkv->segment_uid, SEEK_SET); | 962 url_fseek(pb, mkv->segment_uid, SEEK_SET); |
917 put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16); | 963 put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16); |
918 } | 964 } |
919 url_fseek(pb, currentpos, SEEK_SET); | 965 url_fseek(pb, currentpos, SEEK_SET); |
920 } | 966 } |
921 | 967 |
922 end_ebml_master(pb, mkv->segment); | 968 end_ebml_master(pb, mkv->segment); |
923 av_free(mkv->md5_ctx); | 969 av_free(mkv->md5_ctx); |
| 970 av_free(mkv->tracks); |
924 put_flush_packet(pb); | 971 put_flush_packet(pb); |
925 return 0; | 972 return 0; |
926 } | 973 } |
927 | 974 |
928 AVOutputFormat matroska_muxer = { | 975 AVOutputFormat matroska_muxer = { |
929 "matroska", | 976 "matroska", |
930 NULL_IF_CONFIG_SMALL("Matroska file format"), | 977 NULL_IF_CONFIG_SMALL("Matroska file format"), |
931 "video/x-matroska", | 978 "video/x-matroska", |
932 "mkv", | 979 "mkv", |
933 sizeof(MatroskaMuxContext), | 980 sizeof(MatroskaMuxContext), |
(...skipping 14 matching lines...) Expand all Loading... |
948 "mka", | 995 "mka", |
949 sizeof(MatroskaMuxContext), | 996 sizeof(MatroskaMuxContext), |
950 CODEC_ID_MP2, | 997 CODEC_ID_MP2, |
951 CODEC_ID_NONE, | 998 CODEC_ID_NONE, |
952 mkv_write_header, | 999 mkv_write_header, |
953 mkv_write_packet, | 1000 mkv_write_packet, |
954 mkv_write_trailer, | 1001 mkv_write_trailer, |
955 .flags = AVFMT_GLOBALHEADER, | 1002 .flags = AVFMT_GLOBALHEADER, |
956 .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0}, | 1003 .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0}, |
957 }; | 1004 }; |
OLD | NEW |