| 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 |