1 // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 9 #ifndef MKVMUXER_HPP 10 #define MKVMUXER_HPP 11 12 #include "mkvmuxertypes.hpp" 13 14 // For a description of the WebM elements see 15 // http://www.webmproject.org/code/specs/container/. 16 17 namespace mkvparser { 18 class IMkvReader; 19 } // end namespace 20 21 namespace mkvmuxer { 22 23 class MkvWriter; 24 class Segment; 25 26 /////////////////////////////////////////////////////////////// 27 // Interface used by the mkvmuxer to write out the Mkv data. 28 class IMkvWriter { 29 public: 30 // Writes out |len| bytes of |buf|. Returns 0 on success. 31 virtual int32 Write(const void* buf, uint32 len) = 0; 32 33 // Returns the offset of the output position from the beginning of the 34 // output. 35 virtual int64 Position() const = 0; 36 37 // Set the current File position. Returns 0 on success. 38 virtual int32 Position(int64 position) = 0; 39 40 // Returns true if the writer is seekable. 41 virtual bool Seekable() const = 0; 42 43 // Element start notification. Called whenever an element identifier is about 44 // to be written to the stream. |element_id| is the element identifier, and 45 // |position| is the location in the WebM stream where the first octet of the 46 // element identifier will be written. 47 // Note: the |MkvId| enumeration in webmids.hpp defines element values. 48 virtual void ElementStartNotify(uint64 element_id, int64 position) = 0; 49 50 protected: 51 IMkvWriter(); 52 virtual ~IMkvWriter(); 53 54 private: 55 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter); 56 }; 57 58 // Writes out the EBML header for a WebM file. This function must be called 59 // before any other libwebm writing functions are called. 60 bool WriteEbmlHeader(IMkvWriter* writer); 61 62 // Copies in Chunk from source to destination between the given byte positions 63 bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, 64 int64 start, int64 size); 65 66 /////////////////////////////////////////////////////////////// 67 // Class to hold data the will be written to a block. 68 class Frame { 69 public: 70 Frame(); 71 ~Frame(); 72 73 // Copies |frame| data into |frame_|. Returns true on success. 74 bool Init(const uint8* frame, uint64 length); 75 76 // Copies |additional| data into |additional_|. Returns true on success. 77 bool AddAdditionalData(const uint8* additional, uint64 length, 78 uint64 add_id); 79 add_id() const80 uint64 add_id() const { return add_id_; } additional() const81 const uint8* additional() const { return additional_; } additional_length() const82 uint64 additional_length() const { return additional_length_; } set_duration(uint64 duration)83 void set_duration(uint64 duration) { duration_ = duration; } duration() const84 uint64 duration() const { return duration_; } frame() const85 const uint8* frame() const { return frame_; } set_is_key(bool key)86 void set_is_key(bool key) { is_key_ = key; } is_key() const87 bool is_key() const { return is_key_; } length() const88 uint64 length() const { return length_; } set_track_number(uint64 track_number)89 void set_track_number(uint64 track_number) { track_number_ = track_number; } track_number() const90 uint64 track_number() const { return track_number_; } set_timestamp(uint64 timestamp)91 void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; } timestamp() const92 uint64 timestamp() const { return timestamp_; } set_discard_padding(uint64 discard_padding)93 void set_discard_padding(uint64 discard_padding) { 94 discard_padding_ = discard_padding; 95 } discard_padding() const96 uint64 discard_padding() const { return discard_padding_; } 97 98 private: 99 // Id of the Additional data. 100 uint64 add_id_; 101 102 // Pointer to additional data. Owned by this class. 103 uint8* additional_; 104 105 // Length of the additional data. 106 uint64 additional_length_; 107 108 // Duration of the frame in nanoseconds. 109 uint64 duration_; 110 111 // Pointer to the data. Owned by this class. 112 uint8* frame_; 113 114 // Flag telling if the data should set the key flag of a block. 115 bool is_key_; 116 117 // Length of the data. 118 uint64 length_; 119 120 // Mkv track number the data is associated with. 121 uint64 track_number_; 122 123 // Timestamp of the data in nanoseconds. 124 uint64 timestamp_; 125 126 // Discard padding for the frame. 127 int64 discard_padding_; 128 }; 129 130 /////////////////////////////////////////////////////////////// 131 // Class to hold one cue point in a Cues element. 132 class CuePoint { 133 public: 134 CuePoint(); 135 ~CuePoint(); 136 137 // Returns the size in bytes for the entire CuePoint element. 138 uint64 Size() const; 139 140 // Output the CuePoint element to the writer. Returns true on success. 141 bool Write(IMkvWriter* writer) const; 142 set_time(uint64 time)143 void set_time(uint64 time) { time_ = time; } time() const144 uint64 time() const { return time_; } set_track(uint64 track)145 void set_track(uint64 track) { track_ = track; } track() const146 uint64 track() const { return track_; } set_cluster_pos(uint64 cluster_pos)147 void set_cluster_pos(uint64 cluster_pos) { cluster_pos_ = cluster_pos; } cluster_pos() const148 uint64 cluster_pos() const { return cluster_pos_; } set_block_number(uint64 block_number)149 void set_block_number(uint64 block_number) { block_number_ = block_number; } block_number() const150 uint64 block_number() const { return block_number_; } set_output_block_number(bool output_block_number)151 void set_output_block_number(bool output_block_number) { 152 output_block_number_ = output_block_number; 153 } output_block_number() const154 bool output_block_number() const { return output_block_number_; } 155 156 private: 157 // Returns the size in bytes for the payload of the CuePoint element. 158 uint64 PayloadSize() const; 159 160 // Absolute timecode according to the segment time base. 161 uint64 time_; 162 163 // The Track element associated with the CuePoint. 164 uint64 track_; 165 166 // The position of the Cluster containing the Block. 167 uint64 cluster_pos_; 168 169 // Number of the Block within the Cluster, starting from 1. 170 uint64 block_number_; 171 172 // If true the muxer will write out the block number for the cue if the 173 // block number is different than the default of 1. Default is set to true. 174 bool output_block_number_; 175 176 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint); 177 }; 178 179 /////////////////////////////////////////////////////////////// 180 // Cues element. 181 class Cues { 182 public: 183 Cues(); 184 ~Cues(); 185 186 // Adds a cue point to the Cues element. Returns true on success. 187 bool AddCue(CuePoint* cue); 188 189 // Returns the cue point by index. Returns NULL if there is no cue point 190 // match. 191 CuePoint* GetCueByIndex(int32 index) const; 192 193 // Returns the total size of the Cues element 194 uint64 Size(); 195 196 // Output the Cues element to the writer. Returns true on success. 197 bool Write(IMkvWriter* writer) const; 198 cue_entries_size() const199 int32 cue_entries_size() const { return cue_entries_size_; } set_output_block_number(bool output_block_number)200 void set_output_block_number(bool output_block_number) { 201 output_block_number_ = output_block_number; 202 } output_block_number() const203 bool output_block_number() const { return output_block_number_; } 204 205 private: 206 // Number of allocated elements in |cue_entries_|. 207 int32 cue_entries_capacity_; 208 209 // Number of CuePoints in |cue_entries_|. 210 int32 cue_entries_size_; 211 212 // CuePoint list. 213 CuePoint** cue_entries_; 214 215 // If true the muxer will write out the block number for the cue if the 216 // block number is different than the default of 1. Default is set to true. 217 bool output_block_number_; 218 219 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues); 220 }; 221 222 /////////////////////////////////////////////////////////////// 223 // ContentEncAESSettings element 224 class ContentEncAESSettings { 225 public: 226 enum { 227 kCTR = 1 228 }; 229 230 ContentEncAESSettings(); ~ContentEncAESSettings()231 ~ContentEncAESSettings() {} 232 233 // Returns the size in bytes for the ContentEncAESSettings element. 234 uint64 Size() const; 235 236 // Writes out the ContentEncAESSettings element to |writer|. Returns true on 237 // success. 238 bool Write(IMkvWriter* writer) const; 239 cipher_mode() const240 uint64 cipher_mode() const { return cipher_mode_; } 241 242 private: 243 // Returns the size in bytes for the payload of the ContentEncAESSettings 244 // element. 245 uint64 PayloadSize() const; 246 247 // Sub elements 248 uint64 cipher_mode_; 249 250 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings); 251 }; 252 253 /////////////////////////////////////////////////////////////// 254 // ContentEncoding element 255 // Elements used to describe if the track data has been encrypted or 256 // compressed with zlib or header stripping. 257 // Currently only whole frames can be encrypted with AES. This dictates that 258 // ContentEncodingOrder will be 0, ContentEncodingScope will be 1, 259 // ContentEncodingType will be 1, and ContentEncAlgo will be 5. 260 class ContentEncoding { 261 public: 262 ContentEncoding(); 263 ~ContentEncoding(); 264 265 // Sets the content encryption id. Copies |length| bytes from |id| to 266 // |enc_key_id_|. Returns true on success. 267 bool SetEncryptionID(const uint8* id, uint64 length); 268 269 // Returns the size in bytes for the ContentEncoding element. 270 uint64 Size() const; 271 272 // Writes out the ContentEncoding element to |writer|. Returns true on 273 // success. 274 bool Write(IMkvWriter* writer) const; 275 enc_algo() const276 uint64 enc_algo() const { return enc_algo_; } encoding_order() const277 uint64 encoding_order() const { return encoding_order_; } encoding_scope() const278 uint64 encoding_scope() const { return encoding_scope_; } encoding_type() const279 uint64 encoding_type() const { return encoding_type_; } enc_aes_settings()280 ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; } 281 282 private: 283 // Returns the size in bytes for the encoding elements. 284 uint64 EncodingSize(uint64 compresion_size, uint64 encryption_size) const; 285 286 // Returns the size in bytes for the encryption elements. 287 uint64 EncryptionSize() const; 288 289 // Track element names 290 uint64 enc_algo_; 291 uint8* enc_key_id_; 292 uint64 encoding_order_; 293 uint64 encoding_scope_; 294 uint64 encoding_type_; 295 296 // ContentEncAESSettings element. 297 ContentEncAESSettings enc_aes_settings_; 298 299 // Size of the ContentEncKeyID data in bytes. 300 uint64 enc_key_id_length_; 301 302 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); 303 }; 304 305 /////////////////////////////////////////////////////////////// 306 // Track element. 307 class Track { 308 public: 309 // The |seed| parameter is used to synthesize a UID for the track. 310 explicit Track(unsigned int* seed); 311 virtual ~Track(); 312 313 // Adds a ContentEncoding element to the Track. Returns true on success. 314 virtual bool AddContentEncoding(); 315 316 // Returns the ContentEncoding by index. Returns NULL if there is no 317 // ContentEncoding match. 318 ContentEncoding* GetContentEncodingByIndex(uint32 index) const; 319 320 // Returns the size in bytes for the payload of the Track element. 321 virtual uint64 PayloadSize() const; 322 323 // Returns the size in bytes of the Track element. 324 virtual uint64 Size() const; 325 326 // Output the Track element to the writer. Returns true on success. 327 virtual bool Write(IMkvWriter* writer) const; 328 329 // Sets the CodecPrivate element of the Track element. Copies |length| 330 // bytes from |codec_private| to |codec_private_|. Returns true on success. 331 bool SetCodecPrivate(const uint8* codec_private, uint64 length); 332 333 void set_codec_id(const char* codec_id); codec_id() const334 const char* codec_id() const { return codec_id_; } codec_private() const335 const uint8* codec_private() const { return codec_private_; } 336 void set_language(const char* language); language() const337 const char* language() const { return language_; } set_max_block_additional_id(uint64 max_block_additional_id)338 void set_max_block_additional_id(uint64 max_block_additional_id) { 339 max_block_additional_id_ = max_block_additional_id; 340 } max_block_additional_id() const341 uint64 max_block_additional_id() const { return max_block_additional_id_; } 342 void set_name(const char* name); name() const343 const char* name() const { return name_; } set_number(uint64 number)344 void set_number(uint64 number) { number_ = number; } number() const345 uint64 number() const { return number_; } set_type(uint64 type)346 void set_type(uint64 type) { type_ = type; } type() const347 uint64 type() const { return type_; } set_uid(uint64 uid)348 void set_uid(uint64 uid) { uid_ = uid; } uid() const349 uint64 uid() const { return uid_; } set_codec_delay(uint64 codec_delay)350 void set_codec_delay(uint64 codec_delay) { codec_delay_ = codec_delay; } codec_delay() const351 uint64 codec_delay() const { return codec_delay_; } set_seek_pre_roll(uint64 seek_pre_roll)352 void set_seek_pre_roll(uint64 seek_pre_roll) { 353 seek_pre_roll_ = seek_pre_roll; 354 } seek_pre_roll() const355 uint64 seek_pre_roll() const { return seek_pre_roll_; } 356 codec_private_length() const357 uint64 codec_private_length() const { return codec_private_length_; } content_encoding_entries_size() const358 uint32 content_encoding_entries_size() const { 359 return content_encoding_entries_size_; 360 } 361 362 private: 363 // Track element names 364 char* codec_id_; 365 uint8* codec_private_; 366 char* language_; 367 uint64 max_block_additional_id_; 368 char* name_; 369 uint64 number_; 370 uint64 type_; 371 uint64 uid_; 372 uint64 codec_delay_; 373 uint64 seek_pre_roll_; 374 375 // Size of the CodecPrivate data in bytes. 376 uint64 codec_private_length_; 377 378 // ContentEncoding element list. 379 ContentEncoding** content_encoding_entries_; 380 381 // Number of ContentEncoding elements added. 382 uint32 content_encoding_entries_size_; 383 384 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track); 385 }; 386 387 /////////////////////////////////////////////////////////////// 388 // Track that has video specific elements. 389 class VideoTrack : public Track { 390 public: 391 // Supported modes for stereo 3D. 392 enum StereoMode { 393 kMono = 0, 394 kSideBySideLeftIsFirst = 1, 395 kTopBottomRightIsFirst = 2, 396 kTopBottomLeftIsFirst = 3, 397 kSideBySideRightIsFirst = 11 398 }; 399 400 enum AlphaMode { 401 kNoAlpha = 0, 402 kAlpha = 1 403 }; 404 405 // The |seed| parameter is used to synthesize a UID for the track. 406 explicit VideoTrack(unsigned int* seed); 407 virtual ~VideoTrack(); 408 409 // Returns the size in bytes for the payload of the Track element plus the 410 // video specific elements. 411 virtual uint64 PayloadSize() const; 412 413 // Output the VideoTrack element to the writer. Returns true on success. 414 virtual bool Write(IMkvWriter* writer) const; 415 416 // Sets the video's stereo mode. Returns true on success. 417 bool SetStereoMode(uint64 stereo_mode); 418 419 // Sets the video's alpha mode. Returns true on success. 420 bool SetAlphaMode(uint64 alpha_mode); 421 set_display_height(uint64 height)422 void set_display_height(uint64 height) { display_height_ = height; } display_height() const423 uint64 display_height() const { return display_height_; } set_display_width(uint64 width)424 void set_display_width(uint64 width) { display_width_ = width; } display_width() const425 uint64 display_width() const { return display_width_; } set_frame_rate(double frame_rate)426 void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; } frame_rate() const427 double frame_rate() const { return frame_rate_; } set_height(uint64 height)428 void set_height(uint64 height) { height_ = height; } height() const429 uint64 height() const { return height_; } stereo_mode()430 uint64 stereo_mode() { return stereo_mode_; } alpha_mode()431 uint64 alpha_mode() { return alpha_mode_; } set_width(uint64 width)432 void set_width(uint64 width) { width_ = width; } width() const433 uint64 width() const { return width_; } 434 435 private: 436 // Returns the size in bytes of the Video element. 437 uint64 VideoPayloadSize() const; 438 439 // Video track element names. 440 uint64 display_height_; 441 uint64 display_width_; 442 double frame_rate_; 443 uint64 height_; 444 uint64 stereo_mode_; 445 uint64 alpha_mode_; 446 uint64 width_; 447 448 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack); 449 }; 450 451 /////////////////////////////////////////////////////////////// 452 // Track that has audio specific elements. 453 class AudioTrack : public Track { 454 public: 455 // The |seed| parameter is used to synthesize a UID for the track. 456 explicit AudioTrack(unsigned int* seed); 457 virtual ~AudioTrack(); 458 459 // Returns the size in bytes for the payload of the Track element plus the 460 // audio specific elements. 461 virtual uint64 PayloadSize() const; 462 463 // Output the AudioTrack element to the writer. Returns true on success. 464 virtual bool Write(IMkvWriter* writer) const; 465 set_bit_depth(uint64 bit_depth)466 void set_bit_depth(uint64 bit_depth) { bit_depth_ = bit_depth; } bit_depth() const467 uint64 bit_depth() const { return bit_depth_; } set_channels(uint64 channels)468 void set_channels(uint64 channels) { channels_ = channels; } channels() const469 uint64 channels() const { return channels_; } set_sample_rate(double sample_rate)470 void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; } sample_rate() const471 double sample_rate() const { return sample_rate_; } 472 473 private: 474 // Audio track element names. 475 uint64 bit_depth_; 476 uint64 channels_; 477 double sample_rate_; 478 479 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack); 480 }; 481 482 /////////////////////////////////////////////////////////////// 483 // Tracks element 484 class Tracks { 485 public: 486 // Audio and video type defined by the Matroska specs. 487 enum { 488 kVideo = 0x1, 489 kAudio = 0x2 490 }; 491 // Opus, Vorbis, VP8, and VP9 codec ids defined by the Matroska specs. 492 static const char kOpusCodecId[]; 493 static const char kVorbisCodecId[]; 494 static const char kVp8CodecId[]; 495 static const char kVp9CodecId[]; 496 497 Tracks(); 498 ~Tracks(); 499 500 // Adds a Track element to the Tracks object. |track| will be owned and 501 // deleted by the Tracks object. Returns true on success. |number| is the 502 // number to use for the track. |number| must be >= 0. If |number| == 0 503 // then the muxer will decide on the track number. 504 bool AddTrack(Track* track, int32 number); 505 506 // Returns the track by index. Returns NULL if there is no track match. 507 const Track* GetTrackByIndex(uint32 idx) const; 508 509 // Search the Tracks and return the track that matches |tn|. Returns NULL 510 // if there is no track match. 511 Track* GetTrackByNumber(uint64 track_number) const; 512 513 // Returns true if the track number is an audio track. 514 bool TrackIsAudio(uint64 track_number) const; 515 516 // Returns true if the track number is a video track. 517 bool TrackIsVideo(uint64 track_number) const; 518 519 // Output the Tracks element to the writer. Returns true on success. 520 bool Write(IMkvWriter* writer) const; 521 track_entries_size() const522 uint32 track_entries_size() const { return track_entries_size_; } 523 524 private: 525 // Track element list. 526 Track** track_entries_; 527 528 // Number of Track elements added. 529 uint32 track_entries_size_; 530 531 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks); 532 }; 533 534 /////////////////////////////////////////////////////////////// 535 // Chapter element 536 // 537 class Chapter { 538 public: 539 // Set the identifier for this chapter. (This corresponds to the 540 // Cue Identifier line in WebVTT.) 541 // TODO(matthewjheaney): the actual serialization of this item in 542 // MKV is pending. 543 bool set_id(const char* id); 544 545 // Converts the nanosecond start and stop times of this chapter to 546 // their corresponding timecode values, and stores them that way. 547 void set_time(const Segment& segment, 548 uint64 start_time_ns, 549 uint64 end_time_ns); 550 551 // Sets the uid for this chapter. Primarily used to enable 552 // deterministic output from the muxer. set_uid(const uint64 uid)553 void set_uid(const uint64 uid) { uid_ = uid; } 554 555 // Add a title string to this chapter, per the semantics described 556 // here: 557 // http://www.matroska.org/technical/specs/index.html 558 // 559 // The title ("chapter string") is a UTF-8 string. 560 // 561 // The language has ISO 639-2 representation, described here: 562 // http://www.loc.gov/standards/iso639-2/englangn.html 563 // http://www.loc.gov/standards/iso639-2/php/English_list.php 564 // If you specify NULL as the language value, this implies 565 // English ("eng"). 566 // 567 // The country value corresponds to the codes listed here: 568 // http://www.iana.org/domains/root/db/ 569 // 570 // The function returns false if the string could not be allocated. 571 bool add_string(const char* title, 572 const char* language, 573 const char* country); 574 575 private: 576 friend class Chapters; 577 578 // For storage of chapter titles that differ by language. 579 class Display { 580 public: 581 // Establish representation invariant for new Display object. 582 void Init(); 583 584 // Reclaim resources, in anticipation of destruction. 585 void Clear(); 586 587 // Copies the title to the |title_| member. Returns false on 588 // error. 589 bool set_title(const char* title); 590 591 // Copies the language to the |language_| member. Returns false 592 // on error. 593 bool set_language(const char* language); 594 595 // Copies the country to the |country_| member. Returns false on 596 // error. 597 bool set_country(const char* country); 598 599 // If |writer| is non-NULL, serialize the Display sub-element of 600 // the Atom into the stream. Returns the Display element size on 601 // success, 0 if error. 602 uint64 WriteDisplay(IMkvWriter* writer) const; 603 604 private: 605 char* title_; 606 char* language_; 607 char* country_; 608 }; 609 610 Chapter(); 611 ~Chapter(); 612 613 // Establish the representation invariant for a newly-created 614 // Chapter object. The |seed| parameter is used to create the UID 615 // for this chapter atom. 616 void Init(unsigned int* seed); 617 618 // Copies this Chapter object to a different one. This is used when 619 // expanding a plain array of Chapter objects (see Chapters). 620 void ShallowCopy(Chapter* dst) const; 621 622 // Reclaim resources used by this Chapter object, pending its 623 // destruction. 624 void Clear(); 625 626 // If there is no storage remaining on the |displays_| array for a 627 // new display object, creates a new, longer array and copies the 628 // existing Display objects to the new array. Returns false if the 629 // array cannot be expanded. 630 bool ExpandDisplaysArray(); 631 632 // If |writer| is non-NULL, serialize the Atom sub-element into the 633 // stream. Returns the total size of the element on success, 0 if 634 // error. 635 uint64 WriteAtom(IMkvWriter* writer) const; 636 637 // The string identifier for this chapter (corresponds to WebVTT cue 638 // identifier). 639 char* id_; 640 641 // Start timecode of the chapter. 642 uint64 start_timecode_; 643 644 // Stop timecode of the chapter. 645 uint64 end_timecode_; 646 647 // The binary identifier for this chapter. 648 uint64 uid_; 649 650 // The Atom element can contain multiple Display sub-elements, as 651 // the same logical title can be rendered in different languages. 652 Display* displays_; 653 654 // The physical length (total size) of the |displays_| array. 655 int displays_size_; 656 657 // The logical length (number of active elements) on the |displays_| 658 // array. 659 int displays_count_; 660 661 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter); 662 }; 663 664 /////////////////////////////////////////////////////////////// 665 // Chapters element 666 // 667 class Chapters { 668 public: 669 Chapters(); 670 ~Chapters(); 671 672 Chapter* AddChapter(unsigned int* seed); 673 674 // Returns the number of chapters that have been added. 675 int Count() const; 676 677 // Output the Chapters element to the writer. Returns true on success. 678 bool Write(IMkvWriter* writer) const; 679 680 private: 681 // Expands the chapters_ array if there is not enough space to contain 682 // another chapter object. Returns true on success. 683 bool ExpandChaptersArray(); 684 685 // If |writer| is non-NULL, serialize the Edition sub-element of the 686 // Chapters element into the stream. Returns the Edition element 687 // size on success, 0 if error. 688 uint64 WriteEdition(IMkvWriter* writer) const; 689 690 // Total length of the chapters_ array. 691 int chapters_size_; 692 693 // Number of active chapters on the chapters_ array. 694 int chapters_count_; 695 696 // Array for storage of chapter objects. 697 Chapter* chapters_; 698 699 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters); 700 }; 701 702 /////////////////////////////////////////////////////////////// 703 // Cluster element 704 // 705 // Notes: 706 // |Init| must be called before any other method in this class. 707 class Cluster { 708 public: 709 Cluster(uint64 timecode, int64 cues_pos); 710 ~Cluster(); 711 712 // |timecode| is the absolute timecode of the cluster. |cues_pos| is the 713 // position for the cluster within the segment that should be written in 714 // the cues element. 715 bool Init(IMkvWriter* ptr_writer); 716 717 // Adds a frame to be output in the file. The frame is written out through 718 // |writer_| if successful. Returns true on success. 719 // Inputs: 720 // frame: Pointer to the data 721 // length: Length of the data 722 // track_number: Track to add the data to. Value returned by Add track 723 // functions. The range of allowed values is [1, 126]. 724 // timecode: Absolute (not relative to cluster) timestamp of the 725 // frame, expressed in timecode units. 726 // is_key: Flag telling whether or not this frame is a key frame. 727 bool AddFrame(const uint8* frame, 728 uint64 length, 729 uint64 track_number, 730 uint64 timecode, // timecode units (absolute) 731 bool is_key); 732 733 // Adds a frame to be output in the file. The frame is written out through 734 // |writer_| if successful. Returns true on success. 735 // Inputs: 736 // frame: Pointer to the data 737 // length: Length of the data 738 // additional: Pointer to the additional data 739 // additional_length: Length of the additional data 740 // add_id: Value of BlockAddID element 741 // track_number: Track to add the data to. Value returned by Add track 742 // functions. The range of allowed values is [1, 126]. 743 // abs_timecode: Absolute (not relative to cluster) timestamp of the 744 // frame, expressed in timecode units. 745 // is_key: Flag telling whether or not this frame is a key frame. 746 bool AddFrameWithAdditional(const uint8* frame, 747 uint64 length, 748 const uint8* additional, 749 uint64 additional_length, 750 uint64 add_id, 751 uint64 track_number, 752 uint64 abs_timecode, 753 bool is_key); 754 755 // Adds a frame to be output in the file. The frame is written out through 756 // |writer_| if successful. Returns true on success. 757 // Inputs: 758 // frame: Pointer to the data. 759 // length: Length of the data. 760 // discard_padding: DiscardPadding element value. 761 // track_number: Track to add the data to. Value returned by Add track 762 // functions. The range of allowed values is [1, 126]. 763 // abs_timecode: Absolute (not relative to cluster) timestamp of the 764 // frame, expressed in timecode units. 765 // is_key: Flag telling whether or not this frame is a key frame. 766 bool AddFrameWithDiscardPadding(const uint8* frame, 767 uint64 length, 768 int64 discard_padding, 769 uint64 track_number, 770 uint64 abs_timecode, 771 bool is_key); 772 773 // Writes a frame of metadata to the output medium; returns true on 774 // success. 775 // Inputs: 776 // frame: Pointer to the data 777 // length: Length of the data 778 // track_number: Track to add the data to. Value returned by Add track 779 // functions. The range of allowed values is [1, 126]. 780 // timecode: Absolute (not relative to cluster) timestamp of the 781 // metadata frame, expressed in timecode units. 782 // duration: Duration of metadata frame, in timecode units. 783 // 784 // The metadata frame is written as a block group, with a duration 785 // sub-element but no reference time sub-elements (indicating that 786 // it is considered a keyframe, per Matroska semantics). 787 bool AddMetadata(const uint8* frame, 788 uint64 length, 789 uint64 track_number, 790 uint64 timecode, // timecode units (absolute) 791 uint64 duration); // timecode units 792 793 // Increments the size of the cluster's data in bytes. 794 void AddPayloadSize(uint64 size); 795 796 // Closes the cluster so no more data can be written to it. Will update the 797 // cluster's size if |writer_| is seekable. Returns true on success. 798 bool Finalize(); 799 800 // Returns the size in bytes for the entire Cluster element. 801 uint64 Size() const; 802 size_position() const803 int64 size_position() const { return size_position_; } blocks_added() const804 int32 blocks_added() const { return blocks_added_; } payload_size() const805 uint64 payload_size() const { return payload_size_; } position_for_cues() const806 int64 position_for_cues() const { return position_for_cues_; } timecode() const807 uint64 timecode() const { return timecode_; } 808 809 private: 810 // Signature that matches either of WriteSimpleBlock or WriteMetadataBlock 811 // in the muxer utilities package. 812 typedef uint64 (*WriteBlock)(IMkvWriter* writer, 813 const uint8* data, 814 uint64 length, 815 uint64 track_number, 816 int64 timecode, 817 uint64 generic_arg); 818 819 // Signature that matches WriteBlockWithAdditional 820 // in the muxer utilities package. 821 typedef uint64 (*WriteBlockAdditional)(IMkvWriter* writer, 822 const uint8* data, 823 uint64 length, 824 const uint8* additional, 825 uint64 add_id, 826 uint64 additional_length, 827 uint64 track_number, 828 int64 timecode, 829 uint64 is_key); 830 831 // Signature that matches WriteBlockWithDiscardPadding 832 // in the muxer utilities package. 833 typedef uint64 (*WriteBlockDiscardPadding)(IMkvWriter* writer, 834 const uint8* data, 835 uint64 length, 836 int64 discard_padding, 837 uint64 track_number, 838 int64 timecode, 839 uint64 is_key); 840 841 // Utility method that confirms that blocks can still be added, and that the 842 // cluster header has been written. Used by |DoWriteBlock*|. Returns true 843 // when successful. 844 template <typename Type> 845 bool PreWriteBlock(Type* write_function); 846 847 // Utility method used by the |DoWriteBlock*| methods that handles the book 848 // keeping required after each block is written. 849 void PostWriteBlock(uint64 element_size); 850 851 // To simplify things, we require that there be fewer than 127 852 // tracks -- this allows us to serialize the track number value for 853 // a stream using a single byte, per the Matroska encoding. 854 bool IsValidTrackNumber(uint64 track_number) const; 855 856 // Given |abs_timecode|, calculates timecode relative to most recent timecode. 857 // Returns -1 on failure, or a relative timecode. 858 int64 GetRelativeTimecode(int64 abs_timecode) const; 859 860 // Used to implement AddFrame and AddMetadata. 861 bool DoWriteBlock(const uint8* frame, 862 uint64 length, 863 uint64 track_number, 864 uint64 absolute_timecode, 865 uint64 generic_arg, 866 WriteBlock write_block); 867 868 // Used to implement AddFrameWithAdditional 869 bool DoWriteBlockWithAdditional(const uint8* frame, 870 uint64 length, 871 const uint8* additional, 872 uint64 additional_length, 873 uint64 add_id, 874 uint64 track_number, 875 uint64 absolute_timecode, 876 uint64 generic_arg, 877 WriteBlockAdditional write_block); 878 879 // Used to implement AddFrameWithDiscardPadding 880 bool DoWriteBlockWithDiscardPadding(const uint8* frame, 881 uint64 length, 882 int64 discard_padding, 883 uint64 track_number, 884 uint64 absolute_timecode, 885 uint64 generic_arg, 886 WriteBlockDiscardPadding write_block); 887 888 // Outputs the Cluster header to |writer_|. Returns true on success. 889 bool WriteClusterHeader(); 890 891 // Number of blocks added to the cluster. 892 int32 blocks_added_; 893 894 // Flag telling if the cluster has been closed. 895 bool finalized_; 896 897 // Flag telling if the cluster's header has been written. 898 bool header_written_; 899 900 // The size of the cluster elements in bytes. 901 uint64 payload_size_; 902 903 // The file position used for cue points. 904 const int64 position_for_cues_; 905 906 // The file position of the cluster's size element. 907 int64 size_position_; 908 909 // The absolute timecode of the cluster. 910 const uint64 timecode_; 911 912 // Pointer to the writer object. Not owned by this class. 913 IMkvWriter* writer_; 914 915 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster); 916 }; 917 918 /////////////////////////////////////////////////////////////// 919 // SeekHead element 920 class SeekHead { 921 public: 922 SeekHead(); 923 ~SeekHead(); 924 925 // TODO(fgalligan): Change this to reserve a certain size. Then check how 926 // big the seek entry to be added is as not every seek entry will be the 927 // maximum size it could be. 928 // Adds a seek entry to be written out when the element is finalized. |id| 929 // must be the coded mkv element id. |pos| is the file position of the 930 // element. Returns true on success. 931 bool AddSeekEntry(uint32 id, uint64 pos); 932 933 // Writes out SeekHead and SeekEntry elements. Returns true on success. 934 bool Finalize(IMkvWriter* writer) const; 935 936 // Returns the id of the Seek Entry at the given index. Returns -1 if index is 937 // out of range. 938 uint32 GetId(int index) const; 939 940 // Returns the position of the Seek Entry at the given index. Returns -1 if 941 // index is out of range. 942 uint64 GetPosition(int index) const; 943 944 // Sets the Seek Entry id and position at given index. 945 // Returns true on success. 946 bool SetSeekEntry(int index, uint32 id, uint64 position); 947 948 // Reserves space by writing out a Void element which will be updated with 949 // a SeekHead element later. Returns true on success. 950 bool Write(IMkvWriter* writer); 951 952 // We are going to put a cap on the number of Seek Entries. 953 const static int32 kSeekEntryCount = 5; 954 955 private: 956 // Returns the maximum size in bytes of one seek entry. 957 uint64 MaxEntrySize() const; 958 959 // Seek entry id element list. 960 uint32 seek_entry_id_[kSeekEntryCount]; 961 962 // Seek entry pos element list. 963 uint64 seek_entry_pos_[kSeekEntryCount]; 964 965 // The file position of SeekHead element. 966 int64 start_pos_; 967 968 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead); 969 }; 970 971 /////////////////////////////////////////////////////////////// 972 // Segment Information element 973 class SegmentInfo { 974 public: 975 SegmentInfo(); 976 ~SegmentInfo(); 977 978 // Will update the duration if |duration_| is > 0.0. Returns true on success. 979 bool Finalize(IMkvWriter* writer) const; 980 981 // Sets |muxing_app_| and |writing_app_|. 982 bool Init(); 983 984 // Output the Segment Information element to the writer. Returns true on 985 // success. 986 bool Write(IMkvWriter* writer); 987 set_duration(double duration)988 void set_duration(double duration) { duration_ = duration; } duration() const989 double duration() const { return duration_; } 990 void set_muxing_app(const char* app); muxing_app() const991 const char* muxing_app() const { return muxing_app_; } set_timecode_scale(uint64 scale)992 void set_timecode_scale(uint64 scale) { timecode_scale_ = scale; } timecode_scale() const993 uint64 timecode_scale() const { return timecode_scale_; } 994 void set_writing_app(const char* app); writing_app() const995 const char* writing_app() const { return writing_app_; } 996 997 private: 998 // Segment Information element names. 999 // Initially set to -1 to signify that a duration has not been set and should 1000 // not be written out. 1001 double duration_; 1002 // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision. 1003 char* muxing_app_; 1004 uint64 timecode_scale_; 1005 // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision. 1006 char* writing_app_; 1007 1008 // The file position of the duration element. 1009 int64 duration_pos_; 1010 1011 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo); 1012 }; 1013 1014 /////////////////////////////////////////////////////////////// 1015 // This class represents the main segment in a WebM file. Currently only 1016 // supports one Segment element. 1017 // 1018 // Notes: 1019 // |Init| must be called before any other method in this class. 1020 class Segment { 1021 public: 1022 enum Mode { 1023 kLive = 0x1, 1024 kFile = 0x2 1025 }; 1026 1027 enum CuesPosition { 1028 kAfterClusters = 0x0, // Position Cues after Clusters - Default 1029 kBeforeClusters = 0x1 // Position Cues before Clusters 1030 }; 1031 1032 const static uint64 kDefaultMaxClusterDuration = 30000000000ULL; 1033 1034 Segment(); 1035 ~Segment(); 1036 1037 // Initializes |SegmentInfo| and returns result. Always returns false when 1038 // |ptr_writer| is NULL. 1039 bool Init(IMkvWriter* ptr_writer); 1040 1041 // Adds a generic track to the segment. Returns the newly-allocated 1042 // track object (which is owned by the segment) on success, NULL on 1043 // error. |number| is the number to use for the track. |number| 1044 // must be >= 0. If |number| == 0 then the muxer will decide on the 1045 // track number. 1046 Track* AddTrack(int32 number); 1047 1048 // Adds a Vorbis audio track to the segment. Returns the number of the track 1049 // on success, 0 on error. |number| is the number to use for the audio track. 1050 // |number| must be >= 0. If |number| == 0 then the muxer will decide on 1051 // the track number. 1052 uint64 AddAudioTrack(int32 sample_rate, int32 channels, int32 number); 1053 1054 // Adds an empty chapter to the chapters of this segment. Returns 1055 // non-NULL on success. After adding the chapter, the caller should 1056 // populate its fields via the Chapter member functions. 1057 Chapter* AddChapter(); 1058 1059 // Adds a cue point to the Cues element. |timestamp| is the time in 1060 // nanoseconds of the cue's time. |track| is the Track of the Cue. This 1061 // function must be called after AddFrame to calculate the correct 1062 // BlockNumber for the CuePoint. Returns true on success. 1063 bool AddCuePoint(uint64 timestamp, uint64 track); 1064 1065 // Adds a frame to be output in the file. Returns true on success. 1066 // Inputs: 1067 // frame: Pointer to the data 1068 // length: Length of the data 1069 // track_number: Track to add the data to. Value returned by Add track 1070 // functions. 1071 // timestamp: Timestamp of the frame in nanoseconds from 0. 1072 // is_key: Flag telling whether or not this frame is a key frame. 1073 bool AddFrame(const uint8* frame, 1074 uint64 length, 1075 uint64 track_number, 1076 uint64 timestamp_ns, 1077 bool is_key); 1078 1079 // Writes a frame of metadata to the output medium; returns true on 1080 // success. 1081 // Inputs: 1082 // frame: Pointer to the data 1083 // length: Length of the data 1084 // track_number: Track to add the data to. Value returned by Add track 1085 // functions. 1086 // timecode: Absolute timestamp of the metadata frame, expressed 1087 // in nanosecond units. 1088 // duration: Duration of metadata frame, in nanosecond units. 1089 // 1090 // The metadata frame is written as a block group, with a duration 1091 // sub-element but no reference time sub-elements (indicating that 1092 // it is considered a keyframe, per Matroska semantics). 1093 bool AddMetadata(const uint8* frame, 1094 uint64 length, 1095 uint64 track_number, 1096 uint64 timestamp_ns, 1097 uint64 duration_ns); 1098 1099 // Writes a frame with additional data to the output medium; returns true on 1100 // success. 1101 // Inputs: 1102 // frame: Pointer to the data. 1103 // length: Length of the data. 1104 // additional: Pointer to additional data. 1105 // additional_length: Length of additional data. 1106 // add_id: Additional ID which identifies the type of additional data. 1107 // track_number: Track to add the data to. Value returned by Add track 1108 // functions. 1109 // timestamp: Absolute timestamp of the frame, expressed in nanosecond 1110 // units. 1111 // is_key: Flag telling whether or not this frame is a key frame. 1112 bool AddFrameWithAdditional(const uint8* frame, 1113 uint64 length, 1114 const uint8* additional, 1115 uint64 additional_length, 1116 uint64 add_id, 1117 uint64 track_number, 1118 uint64 timestamp, 1119 bool is_key); 1120 1121 // Writes a frame with DiscardPadding to the output medium; returns true on 1122 // success. 1123 // Inputs: 1124 // frame: Pointer to the data. 1125 // length: Length of the data. 1126 // discard_padding: DiscardPadding element value. 1127 // track_number: Track to add the data to. Value returned by Add track 1128 // functions. 1129 // timestamp: Absolute timestamp of the frame, expressed in nanosecond 1130 // units. 1131 // is_key: Flag telling whether or not this frame is a key frame. 1132 bool AddFrameWithDiscardPadding(const uint8* frame, 1133 uint64 length, 1134 int64 discard_padding, 1135 uint64 track_number, 1136 uint64 timestamp, 1137 bool is_key); 1138 1139 // Writes a Frame to the output medium. Chooses the correct way of writing 1140 // the frame (Block vs SimpleBlock) based on the parameters passed. 1141 // Inputs: 1142 // frame: frame object 1143 bool AddGenericFrame(const Frame* frame); 1144 1145 // Adds a VP8 video track to the segment. Returns the number of the track on 1146 // success, 0 on error. |number| is the number to use for the video track. 1147 // |number| must be >= 0. If |number| == 0 then the muxer will decide on 1148 // the track number. 1149 uint64 AddVideoTrack(int32 width, int32 height, int32 number); 1150 1151 // This function must be called after Finalize() if you need a copy of the 1152 // output with Cues written before the Clusters. It will return false if the 1153 // writer is not seekable of if chunking is set to true. 1154 // Input parameters: 1155 // reader - an IMkvReader object created with the same underlying file of the 1156 // current writer object. Make sure to close the existing writer 1157 // object before creating this so that all the data is properly 1158 // flushed and available for reading. 1159 // writer - an IMkvWriter object pointing to a *different* file than the one 1160 // pointed by the current writer object. This file will contain the 1161 // Cues element before the Clusters. 1162 bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader, 1163 IMkvWriter* writer); 1164 1165 // Sets which track to use for the Cues element. Must have added the track 1166 // before calling this function. Returns true on success. |track_number| is 1167 // returned by the Add track functions. 1168 bool CuesTrack(uint64 track_number); 1169 1170 // This will force the muxer to create a new Cluster when the next frame is 1171 // added. 1172 void ForceNewClusterOnNextFrame(); 1173 1174 // Writes out any frames that have not been written out. Finalizes the last 1175 // cluster. May update the size and duration of the segment. May output the 1176 // Cues element. May finalize the SeekHead element. Returns true on success. 1177 bool Finalize(); 1178 1179 // Returns the Cues object. GetCues()1180 Cues* GetCues() { return &cues_; } 1181 1182 // Returns the Segment Information object. GetSegmentInfo() const1183 const SegmentInfo* GetSegmentInfo() const { return &segment_info_; } GetSegmentInfo()1184 SegmentInfo* GetSegmentInfo() { return &segment_info_; } 1185 1186 // Search the Tracks and return the track that matches |track_number|. 1187 // Returns NULL if there is no track match. 1188 Track* GetTrackByNumber(uint64 track_number) const; 1189 1190 // Toggles whether to output a cues element. 1191 void OutputCues(bool output_cues); 1192 1193 // Sets if the muxer will output files in chunks or not. |chunking| is a 1194 // flag telling whether or not to turn on chunking. |filename| is the base 1195 // filename for the chunk files. The header chunk file will be named 1196 // |filename|.hdr and the data chunks will be named 1197 // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing 1198 // to files so the muxer will use the default MkvWriter class to control 1199 // what data is written to what files. Returns true on success. 1200 // TODO: Should we change the IMkvWriter Interface to add Open and Close? 1201 // That will force the interface to be dependent on files. 1202 bool SetChunking(bool chunking, const char* filename); 1203 chunking() const1204 bool chunking() const { return chunking_; } cues_track() const1205 uint64 cues_track() const { return cues_track_; } set_max_cluster_duration(uint64 max_cluster_duration)1206 void set_max_cluster_duration(uint64 max_cluster_duration) { 1207 max_cluster_duration_ = max_cluster_duration; 1208 } max_cluster_duration() const1209 uint64 max_cluster_duration() const { return max_cluster_duration_; } set_max_cluster_size(uint64 max_cluster_size)1210 void set_max_cluster_size(uint64 max_cluster_size) { 1211 max_cluster_size_ = max_cluster_size; 1212 } max_cluster_size() const1213 uint64 max_cluster_size() const { return max_cluster_size_; } set_mode(Mode mode)1214 void set_mode(Mode mode) { mode_ = mode; } mode() const1215 Mode mode() const { return mode_; } cues_position() const1216 CuesPosition cues_position() const { return cues_position_; } output_cues() const1217 bool output_cues() const { return output_cues_; } segment_info() const1218 const SegmentInfo* segment_info() const { return &segment_info_; } 1219 1220 private: 1221 // Checks if header information has been output and initialized. If not it 1222 // will output the Segment element and initialize the SeekHead elment and 1223 // Cues elements. 1224 bool CheckHeaderInfo(); 1225 1226 // Sets |name| according to how many chunks have been written. |ext| is the 1227 // file extension. |name| must be deleted by the calling app. Returns true 1228 // on success. 1229 bool UpdateChunkName(const char* ext, char** name) const; 1230 1231 // Returns the maximum offset within the segment's payload. When chunking 1232 // this function is needed to determine offsets of elements within the 1233 // chunked files. Returns -1 on error. 1234 int64 MaxOffset(); 1235 1236 // Adds the frame to our frame array. 1237 bool QueueFrame(Frame* frame); 1238 1239 // Output all frames that are queued. Returns -1 on error, otherwise 1240 // it returns the number of frames written. 1241 int WriteFramesAll(); 1242 1243 // Output all frames that are queued that have an end time that is less 1244 // then |timestamp|. Returns true on success and if there are no frames 1245 // queued. 1246 bool WriteFramesLessThan(uint64 timestamp); 1247 1248 // Outputs the segment header, Segment Information element, SeekHead element, 1249 // and Tracks element to |writer_|. 1250 bool WriteSegmentHeader(); 1251 1252 // Given a frame with the specified timestamp (nanosecond units) and 1253 // keyframe status, determine whether a new cluster should be 1254 // created, before writing enqueued frames and the frame itself. The 1255 // function returns one of the following values: 1256 // -1 = error: an out-of-order frame was detected 1257 // 0 = do not create a new cluster, and write frame to the existing cluster 1258 // 1 = create a new cluster, and write frame to that new cluster 1259 // 2 = create a new cluster, and re-run test 1260 int TestFrame(uint64 track_num, uint64 timestamp_ns, bool key) const; 1261 1262 // Create a new cluster, using the earlier of the first enqueued 1263 // frame, or the indicated time. Returns true on success. 1264 bool MakeNewCluster(uint64 timestamp_ns); 1265 1266 // Checks whether a new cluster needs to be created, and if so 1267 // creates a new cluster. Returns false if creation of a new cluster 1268 // was necessary but creation was not successful. 1269 bool DoNewClusterProcessing(uint64 track_num, uint64 timestamp_ns, bool key); 1270 1271 1272 // Adjusts Cue Point values (to place Cues before Clusters) so that they 1273 // reflect the correct offsets. 1274 void MoveCuesBeforeClusters(); 1275 1276 // This function recursively computes the correct cluster offsets (this is 1277 // done to move the Cues before Clusters). It recursively updates the change 1278 // in size (which indicates a change in cluster offset) until no sizes change. 1279 // Parameters: 1280 // diff - indicates the difference in size of the Cues element that needs to 1281 // accounted for. 1282 // index - index in the list of Cues which is currently being adjusted. 1283 // cue_size - size of the Cues element. 1284 void MoveCuesBeforeClustersHelper(uint64 diff, int index, uint64* cue_size); 1285 1286 // Seeds the random number generator used to make UIDs. 1287 unsigned int seed_; 1288 1289 // WebM elements 1290 Cues cues_; 1291 SeekHead seek_head_; 1292 SegmentInfo segment_info_; 1293 Tracks tracks_; 1294 Chapters chapters_; 1295 1296 // Number of chunks written. 1297 int chunk_count_; 1298 1299 // Current chunk filename. 1300 char* chunk_name_; 1301 1302 // Default MkvWriter object created by this class used for writing clusters 1303 // out in separate files. 1304 MkvWriter* chunk_writer_cluster_; 1305 1306 // Default MkvWriter object created by this class used for writing Cues 1307 // element out to a file. 1308 MkvWriter* chunk_writer_cues_; 1309 1310 // Default MkvWriter object created by this class used for writing the 1311 // Matroska header out to a file. 1312 MkvWriter* chunk_writer_header_; 1313 1314 // Flag telling whether or not the muxer is chunking output to multiple 1315 // files. 1316 bool chunking_; 1317 1318 // Base filename for the chunked files. 1319 char* chunking_base_name_; 1320 1321 // File position offset where the Clusters end. 1322 int64 cluster_end_offset_; 1323 1324 // List of clusters. 1325 Cluster** cluster_list_; 1326 1327 // Number of cluster pointers allocated in the cluster list. 1328 int32 cluster_list_capacity_; 1329 1330 // Number of clusters in the cluster list. 1331 int32 cluster_list_size_; 1332 1333 // Indicates whether Cues should be written before or after Clusters 1334 CuesPosition cues_position_; 1335 1336 // Track number that is associated with the cues element for this segment. 1337 uint64 cues_track_; 1338 1339 // Tells the muxer to force a new cluster on the next Block. 1340 bool force_new_cluster_; 1341 1342 // List of stored audio frames. These variables are used to store frames so 1343 // the muxer can follow the guideline "Audio blocks that contain the video 1344 // key frame's timecode should be in the same cluster as the video key frame 1345 // block." 1346 Frame** frames_; 1347 1348 // Number of frame pointers allocated in the frame list. 1349 int32 frames_capacity_; 1350 1351 // Number of frames in the frame list. 1352 int32 frames_size_; 1353 1354 // Flag telling if a video track has been added to the segment. 1355 bool has_video_; 1356 1357 // Flag telling if the segment's header has been written. 1358 bool header_written_; 1359 1360 // Duration of the last block in nanoseconds. 1361 uint64 last_block_duration_; 1362 1363 // Last timestamp in nanoseconds added to a cluster. 1364 uint64 last_timestamp_; 1365 1366 // Maximum time in nanoseconds for a cluster duration. This variable is a 1367 // guideline and some clusters may have a longer duration. Default is 30 1368 // seconds. 1369 uint64 max_cluster_duration_; 1370 1371 // Maximum size in bytes for a cluster. This variable is a guideline and 1372 // some clusters may have a larger size. Default is 0 which signifies that 1373 // the muxer will decide the size. 1374 uint64 max_cluster_size_; 1375 1376 // The mode that segment is in. If set to |kLive| the writer must not 1377 // seek backwards. 1378 Mode mode_; 1379 1380 // Flag telling the muxer that a new cue point should be added. 1381 bool new_cuepoint_; 1382 1383 // TODO(fgalligan): Should we add support for more than one Cues element? 1384 // Flag whether or not the muxer should output a Cues element. 1385 bool output_cues_; 1386 1387 // The file position of the segment's payload. 1388 int64 payload_pos_; 1389 1390 // The file position of the element's size. 1391 int64 size_position_; 1392 1393 // Pointer to the writer objects. Not owned by this class. 1394 IMkvWriter* writer_cluster_; 1395 IMkvWriter* writer_cues_; 1396 IMkvWriter* writer_header_; 1397 1398 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment); 1399 }; 1400 1401 } //end namespace mkvmuxer 1402 1403 #endif //MKVMUXER_HPP 1404