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