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_MKVMUXER_H_ 10 #define MKVMUXER_MKVMUXER_H_ 11 12 #include <stdint.h> 13 14 #include <cstddef> 15 #include <list> 16 #include <map> 17 18 #include "common/webmids.h" 19 #include "mkvmuxer/mkvmuxertypes.h" 20 21 // For a description of the WebM elements see 22 // http://www.webmproject.org/code/specs/container/. 23 24 namespace mkvparser { 25 class IMkvReader; 26 } // namespace mkvparser 27 28 namespace mkvmuxer { 29 30 class MkvWriter; 31 class Segment; 32 33 const uint64_t kMaxTrackNumber = 126; 34 35 /////////////////////////////////////////////////////////////// 36 // Interface used by the mkvmuxer to write out the Mkv data. 37 class IMkvWriter { 38 public: 39 // Writes out |len| bytes of |buf|. Returns 0 on success. 40 virtual int32 Write(const void* buf, uint32 len) = 0; 41 42 // Returns the offset of the output position from the beginning of the 43 // output. 44 virtual int64 Position() const = 0; 45 46 // Set the current File position. Returns 0 on success. 47 virtual int32 Position(int64 position) = 0; 48 49 // Returns true if the writer is seekable. 50 virtual bool Seekable() const = 0; 51 52 // Element start notification. Called whenever an element identifier is about 53 // to be written to the stream. |element_id| is the element identifier, and 54 // |position| is the location in the WebM stream where the first octet of the 55 // element identifier will be written. 56 // Note: the |MkvId| enumeration in webmids.hpp defines element values. 57 virtual void ElementStartNotify(uint64 element_id, int64 position) = 0; 58 59 protected: 60 IMkvWriter(); 61 virtual ~IMkvWriter(); 62 63 private: 64 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter); 65 }; 66 67 // Writes out the EBML header for a WebM file, but allows caller to specify 68 // DocType. This function must be called before any other libwebm writing 69 // functions are called. 70 bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version, 71 const char* const doc_type); 72 73 // Writes out the EBML header for a WebM file. This function must be called 74 // before any other libwebm writing functions are called. 75 bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version); 76 77 // Deprecated. Writes out EBML header with doc_type_version as 78 // kDefaultDocTypeVersion. Exists for backward compatibility. 79 bool WriteEbmlHeader(IMkvWriter* writer); 80 81 // Copies in Chunk from source to destination between the given byte positions 82 bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64_t start, 83 int64_t size); 84 85 /////////////////////////////////////////////////////////////// 86 // Class to hold data the will be written to a block. 87 class Frame { 88 public: 89 Frame(); 90 ~Frame(); 91 92 // Sets this frame's contents based on |frame|. Returns true on success. On 93 // failure, this frame's existing contents may be lost. 94 bool CopyFrom(const Frame& frame); 95 96 // Copies |frame| data into |frame_|. Returns true on success. 97 bool Init(const uint8_t* frame, uint64_t length); 98 99 // Copies |additional| data into |additional_|. Returns true on success. 100 bool AddAdditionalData(const uint8_t* additional, uint64_t length, 101 uint64_t add_id); 102 103 // Returns true if the frame has valid parameters. 104 bool IsValid() const; 105 106 // Returns true if the frame can be written as a SimpleBlock based on current 107 // parameters. 108 bool CanBeSimpleBlock() const; 109 add_id()110 uint64_t add_id() const { return add_id_; } additional()111 const uint8_t* additional() const { return additional_; } additional_length()112 uint64_t additional_length() const { return additional_length_; } 113 void set_duration(uint64_t duration); duration()114 uint64_t duration() const { return duration_; } duration_set()115 bool duration_set() const { return duration_set_; } frame()116 const uint8_t* frame() const { return frame_; } set_is_key(bool key)117 void set_is_key(bool key) { is_key_ = key; } is_key()118 bool is_key() const { return is_key_; } length()119 uint64_t length() const { return length_; } set_track_number(uint64_t track_number)120 void set_track_number(uint64_t track_number) { track_number_ = track_number; } track_number()121 uint64_t track_number() const { return track_number_; } set_timestamp(uint64_t timestamp)122 void set_timestamp(uint64_t timestamp) { timestamp_ = timestamp; } timestamp()123 uint64_t timestamp() const { return timestamp_; } set_discard_padding(int64_t discard_padding)124 void set_discard_padding(int64_t discard_padding) { 125 discard_padding_ = discard_padding; 126 } discard_padding()127 int64_t discard_padding() const { return discard_padding_; } 128 void set_reference_block_timestamp(int64_t reference_block_timestamp); reference_block_timestamp()129 int64_t reference_block_timestamp() const { 130 return reference_block_timestamp_; 131 } reference_block_timestamp_set()132 bool reference_block_timestamp_set() const { 133 return reference_block_timestamp_set_; 134 } 135 136 private: 137 // Id of the Additional data. 138 uint64_t add_id_; 139 140 // Pointer to additional data. Owned by this class. 141 uint8_t* additional_; 142 143 // Length of the additional data. 144 uint64_t additional_length_; 145 146 // Duration of the frame in nanoseconds. 147 uint64_t duration_; 148 149 // Flag indicating that |duration_| has been set. Setting duration causes the 150 // frame to be written out as a Block with BlockDuration instead of as a 151 // SimpleBlock. 152 bool duration_set_; 153 154 // Pointer to the data. Owned by this class. 155 uint8_t* frame_; 156 157 // Flag telling if the data should set the key flag of a block. 158 bool is_key_; 159 160 // Length of the data. 161 uint64_t length_; 162 163 // Mkv track number the data is associated with. 164 uint64_t track_number_; 165 166 // Timestamp of the data in nanoseconds. 167 uint64_t timestamp_; 168 169 // Discard padding for the frame. 170 int64_t discard_padding_; 171 172 // Reference block timestamp. 173 int64_t reference_block_timestamp_; 174 175 // Flag indicating if |reference_block_timestamp_| has been set. 176 bool reference_block_timestamp_set_; 177 178 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame); 179 }; 180 181 /////////////////////////////////////////////////////////////// 182 // Class to hold one cue point in a Cues element. 183 class CuePoint { 184 public: 185 CuePoint(); 186 ~CuePoint(); 187 188 // Returns the size in bytes for the entire CuePoint element. 189 uint64_t Size() const; 190 191 // Output the CuePoint element to the writer. Returns true on success. 192 bool Write(IMkvWriter* writer) const; 193 set_time(uint64_t time)194 void set_time(uint64_t time) { time_ = time; } time()195 uint64_t time() const { return time_; } set_track(uint64_t track)196 void set_track(uint64_t track) { track_ = track; } track()197 uint64_t track() const { return track_; } set_cluster_pos(uint64_t cluster_pos)198 void set_cluster_pos(uint64_t cluster_pos) { cluster_pos_ = cluster_pos; } cluster_pos()199 uint64_t cluster_pos() const { return cluster_pos_; } set_block_number(uint64_t block_number)200 void set_block_number(uint64_t block_number) { block_number_ = block_number; } block_number()201 uint64_t block_number() const { return block_number_; } set_output_block_number(bool output_block_number)202 void set_output_block_number(bool output_block_number) { 203 output_block_number_ = output_block_number; 204 } output_block_number()205 bool output_block_number() const { return output_block_number_; } 206 207 private: 208 // Returns the size in bytes for the payload of the CuePoint element. 209 uint64_t PayloadSize() const; 210 211 // Absolute timecode according to the segment time base. 212 uint64_t time_; 213 214 // The Track element associated with the CuePoint. 215 uint64_t track_; 216 217 // The position of the Cluster containing the Block. 218 uint64_t cluster_pos_; 219 220 // Number of the Block within the Cluster, starting from 1. 221 uint64_t block_number_; 222 223 // If true the muxer will write out the block number for the cue if the 224 // block number is different than the default of 1. Default is set to true. 225 bool output_block_number_; 226 227 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint); 228 }; 229 230 /////////////////////////////////////////////////////////////// 231 // Cues element. 232 class Cues { 233 public: 234 Cues(); 235 ~Cues(); 236 237 // Adds a cue point to the Cues element. Returns true on success. 238 bool AddCue(CuePoint* cue); 239 240 // Returns the cue point by index. Returns NULL if there is no cue point 241 // match. 242 CuePoint* GetCueByIndex(int32_t index) const; 243 244 // Returns the total size of the Cues element 245 uint64_t Size(); 246 247 // Output the Cues element to the writer. Returns true on success. 248 bool Write(IMkvWriter* writer) const; 249 cue_entries_size()250 int32_t cue_entries_size() const { return cue_entries_size_; } set_output_block_number(bool output_block_number)251 void set_output_block_number(bool output_block_number) { 252 output_block_number_ = output_block_number; 253 } output_block_number()254 bool output_block_number() const { return output_block_number_; } 255 256 private: 257 // Number of allocated elements in |cue_entries_|. 258 int32_t cue_entries_capacity_; 259 260 // Number of CuePoints in |cue_entries_|. 261 int32_t cue_entries_size_; 262 263 // CuePoint list. 264 CuePoint** cue_entries_; 265 266 // If true the muxer will write out the block number for the cue if the 267 // block number is different than the default of 1. Default is set to true. 268 bool output_block_number_; 269 270 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues); 271 }; 272 273 /////////////////////////////////////////////////////////////// 274 // ContentEncAESSettings element 275 class ContentEncAESSettings { 276 public: 277 enum { kCTR = 1 }; 278 279 ContentEncAESSettings(); ~ContentEncAESSettings()280 ~ContentEncAESSettings() {} 281 282 // Returns the size in bytes for the ContentEncAESSettings element. 283 uint64_t Size() const; 284 285 // Writes out the ContentEncAESSettings element to |writer|. Returns true on 286 // success. 287 bool Write(IMkvWriter* writer) const; 288 cipher_mode()289 uint64_t cipher_mode() const { return cipher_mode_; } 290 291 private: 292 // Returns the size in bytes for the payload of the ContentEncAESSettings 293 // element. 294 uint64_t PayloadSize() const; 295 296 // Sub elements 297 uint64_t cipher_mode_; 298 299 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings); 300 }; 301 302 /////////////////////////////////////////////////////////////// 303 // ContentEncoding element 304 // Elements used to describe if the track data has been encrypted or 305 // compressed with zlib or header stripping. 306 // Currently only whole frames can be encrypted with AES. This dictates that 307 // ContentEncodingOrder will be 0, ContentEncodingScope will be 1, 308 // ContentEncodingType will be 1, and ContentEncAlgo will be 5. 309 class ContentEncoding { 310 public: 311 ContentEncoding(); 312 ~ContentEncoding(); 313 314 // Sets the content encryption id. Copies |length| bytes from |id| to 315 // |enc_key_id_|. Returns true on success. 316 bool SetEncryptionID(const uint8_t* id, uint64_t length); 317 318 // Returns the size in bytes for the ContentEncoding element. 319 uint64_t Size() const; 320 321 // Writes out the ContentEncoding element to |writer|. Returns true on 322 // success. 323 bool Write(IMkvWriter* writer) const; 324 enc_algo()325 uint64_t enc_algo() const { return enc_algo_; } encoding_order()326 uint64_t encoding_order() const { return encoding_order_; } encoding_scope()327 uint64_t encoding_scope() const { return encoding_scope_; } encoding_type()328 uint64_t encoding_type() const { return encoding_type_; } enc_aes_settings()329 ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; } 330 331 private: 332 // Returns the size in bytes for the encoding elements. 333 uint64_t EncodingSize(uint64_t compresion_size, 334 uint64_t encryption_size) const; 335 336 // Returns the size in bytes for the encryption elements. 337 uint64_t EncryptionSize() const; 338 339 // Track element names 340 uint64_t enc_algo_; 341 uint8_t* enc_key_id_; 342 uint64_t encoding_order_; 343 uint64_t encoding_scope_; 344 uint64_t encoding_type_; 345 346 // ContentEncAESSettings element. 347 ContentEncAESSettings enc_aes_settings_; 348 349 // Size of the ContentEncKeyID data in bytes. 350 uint64_t enc_key_id_length_; 351 352 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); 353 }; 354 355 /////////////////////////////////////////////////////////////// 356 // Colour element. 357 class PrimaryChromaticity { 358 public: 359 static const float kChromaticityMin; 360 static const float kChromaticityMax; 361 PrimaryChromaticity(float x_val,float y_val)362 PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {} PrimaryChromaticity()363 PrimaryChromaticity() : x_(0), y_(0) {} ~PrimaryChromaticity()364 ~PrimaryChromaticity() {} 365 366 // Returns sum of |x_id| and |y_id| element id sizes and payload sizes. 367 uint64_t PrimaryChromaticitySize(libwebm::MkvId x_id, 368 libwebm::MkvId y_id) const; 369 bool Valid() const; 370 bool Write(IMkvWriter* writer, libwebm::MkvId x_id, 371 libwebm::MkvId y_id) const; 372 x()373 float x() const { return x_; } set_x(float new_x)374 void set_x(float new_x) { x_ = new_x; } y()375 float y() const { return y_; } set_y(float new_y)376 void set_y(float new_y) { y_ = new_y; } 377 378 private: 379 float x_; 380 float y_; 381 }; 382 383 class MasteringMetadata { 384 public: 385 static const float kValueNotPresent; 386 static const float kMinLuminance; 387 static const float kMinLuminanceMax; 388 static const float kMaxLuminanceMax; 389 MasteringMetadata()390 MasteringMetadata() 391 : luminance_max_(kValueNotPresent), 392 luminance_min_(kValueNotPresent), 393 r_(NULL), 394 g_(NULL), 395 b_(NULL), 396 white_point_(NULL) {} ~MasteringMetadata()397 ~MasteringMetadata() { 398 delete r_; 399 delete g_; 400 delete b_; 401 delete white_point_; 402 } 403 404 // Returns total size of the MasteringMetadata element. 405 uint64_t MasteringMetadataSize() const; 406 bool Valid() const; 407 bool Write(IMkvWriter* writer) const; 408 409 // Copies non-null chromaticity. 410 bool SetChromaticity(const PrimaryChromaticity* r, 411 const PrimaryChromaticity* g, 412 const PrimaryChromaticity* b, 413 const PrimaryChromaticity* white_point); r()414 const PrimaryChromaticity* r() const { return r_; } g()415 const PrimaryChromaticity* g() const { return g_; } b()416 const PrimaryChromaticity* b() const { return b_; } white_point()417 const PrimaryChromaticity* white_point() const { return white_point_; } 418 luminance_max()419 float luminance_max() const { return luminance_max_; } set_luminance_max(float luminance_max)420 void set_luminance_max(float luminance_max) { 421 luminance_max_ = luminance_max; 422 } luminance_min()423 float luminance_min() const { return luminance_min_; } set_luminance_min(float luminance_min)424 void set_luminance_min(float luminance_min) { 425 luminance_min_ = luminance_min; 426 } 427 428 private: 429 // Returns size of MasteringMetadata child elements. 430 uint64_t PayloadSize() const; 431 432 float luminance_max_; 433 float luminance_min_; 434 PrimaryChromaticity* r_; 435 PrimaryChromaticity* g_; 436 PrimaryChromaticity* b_; 437 PrimaryChromaticity* white_point_; 438 }; 439 440 class Colour { 441 public: 442 enum MatrixCoefficients { 443 kGbr = 0, 444 kBt709 = 1, 445 kUnspecifiedMc = 2, 446 kReserved = 3, 447 kFcc = 4, 448 kBt470bg = 5, 449 kSmpte170MMc = 6, 450 kSmpte240MMc = 7, 451 kYcocg = 8, 452 kBt2020NonConstantLuminance = 9, 453 kBt2020ConstantLuminance = 10, 454 }; 455 enum ChromaSitingHorz { 456 kUnspecifiedCsh = 0, 457 kLeftCollocated = 1, 458 kHalfCsh = 2, 459 }; 460 enum ChromaSitingVert { 461 kUnspecifiedCsv = 0, 462 kTopCollocated = 1, 463 kHalfCsv = 2, 464 }; 465 enum Range { 466 kUnspecifiedCr = 0, 467 kBroadcastRange = 1, 468 kFullRange = 2, 469 kMcTcDefined = 3, // Defined by MatrixCoefficients/TransferCharacteristics. 470 }; 471 enum TransferCharacteristics { 472 kIturBt709Tc = 1, 473 kUnspecifiedTc = 2, 474 kReservedTc = 3, 475 kGamma22Curve = 4, 476 kGamma28Curve = 5, 477 kSmpte170MTc = 6, 478 kSmpte240MTc = 7, 479 kLinear = 8, 480 kLog = 9, 481 kLogSqrt = 10, 482 kIec6196624 = 11, 483 kIturBt1361ExtendedColourGamut = 12, 484 kIec6196621 = 13, 485 kIturBt202010bit = 14, 486 kIturBt202012bit = 15, 487 kSmpteSt2084 = 16, 488 kSmpteSt4281Tc = 17, 489 kAribStdB67Hlg = 18, 490 }; 491 enum Primaries { 492 kReservedP0 = 0, 493 kIturBt709P = 1, 494 kUnspecifiedP = 2, 495 kReservedP3 = 3, 496 kIturBt470M = 4, 497 kIturBt470Bg = 5, 498 kSmpte170MP = 6, 499 kSmpte240MP = 7, 500 kFilm = 8, 501 kIturBt2020 = 9, 502 kSmpteSt4281P = 10, 503 kJedecP22Phosphors = 22, 504 }; 505 static const uint64_t kValueNotPresent; Colour()506 Colour() 507 : matrix_coefficients_(kValueNotPresent), 508 bits_per_channel_(kValueNotPresent), 509 chroma_subsampling_horz_(kValueNotPresent), 510 chroma_subsampling_vert_(kValueNotPresent), 511 cb_subsampling_horz_(kValueNotPresent), 512 cb_subsampling_vert_(kValueNotPresent), 513 chroma_siting_horz_(kValueNotPresent), 514 chroma_siting_vert_(kValueNotPresent), 515 range_(kValueNotPresent), 516 transfer_characteristics_(kValueNotPresent), 517 primaries_(kValueNotPresent), 518 max_cll_(kValueNotPresent), 519 max_fall_(kValueNotPresent), 520 mastering_metadata_(NULL) {} ~Colour()521 ~Colour() { delete mastering_metadata_; } 522 523 // Returns total size of the Colour element. 524 uint64_t ColourSize() const; 525 bool Valid() const; 526 bool Write(IMkvWriter* writer) const; 527 528 // Deep copies |mastering_metadata|. 529 bool SetMasteringMetadata(const MasteringMetadata& mastering_metadata); 530 mastering_metadata()531 const MasteringMetadata* mastering_metadata() const { 532 return mastering_metadata_; 533 } 534 matrix_coefficients()535 uint64_t matrix_coefficients() const { return matrix_coefficients_; } set_matrix_coefficients(uint64_t matrix_coefficients)536 void set_matrix_coefficients(uint64_t matrix_coefficients) { 537 matrix_coefficients_ = matrix_coefficients; 538 } bits_per_channel()539 uint64_t bits_per_channel() const { return bits_per_channel_; } set_bits_per_channel(uint64_t bits_per_channel)540 void set_bits_per_channel(uint64_t bits_per_channel) { 541 bits_per_channel_ = bits_per_channel; 542 } chroma_subsampling_horz()543 uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; } set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz)544 void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) { 545 chroma_subsampling_horz_ = chroma_subsampling_horz; 546 } chroma_subsampling_vert()547 uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; } set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert)548 void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) { 549 chroma_subsampling_vert_ = chroma_subsampling_vert; 550 } cb_subsampling_horz()551 uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; } set_cb_subsampling_horz(uint64_t cb_subsampling_horz)552 void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) { 553 cb_subsampling_horz_ = cb_subsampling_horz; 554 } cb_subsampling_vert()555 uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; } set_cb_subsampling_vert(uint64_t cb_subsampling_vert)556 void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) { 557 cb_subsampling_vert_ = cb_subsampling_vert; 558 } chroma_siting_horz()559 uint64_t chroma_siting_horz() const { return chroma_siting_horz_; } set_chroma_siting_horz(uint64_t chroma_siting_horz)560 void set_chroma_siting_horz(uint64_t chroma_siting_horz) { 561 chroma_siting_horz_ = chroma_siting_horz; 562 } chroma_siting_vert()563 uint64_t chroma_siting_vert() const { return chroma_siting_vert_; } set_chroma_siting_vert(uint64_t chroma_siting_vert)564 void set_chroma_siting_vert(uint64_t chroma_siting_vert) { 565 chroma_siting_vert_ = chroma_siting_vert; 566 } range()567 uint64_t range() const { return range_; } set_range(uint64_t range)568 void set_range(uint64_t range) { range_ = range; } transfer_characteristics()569 uint64_t transfer_characteristics() const { 570 return transfer_characteristics_; 571 } set_transfer_characteristics(uint64_t transfer_characteristics)572 void set_transfer_characteristics(uint64_t transfer_characteristics) { 573 transfer_characteristics_ = transfer_characteristics; 574 } primaries()575 uint64_t primaries() const { return primaries_; } set_primaries(uint64_t primaries)576 void set_primaries(uint64_t primaries) { primaries_ = primaries; } max_cll()577 uint64_t max_cll() const { return max_cll_; } set_max_cll(uint64_t max_cll)578 void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; } max_fall()579 uint64_t max_fall() const { return max_fall_; } set_max_fall(uint64_t max_fall)580 void set_max_fall(uint64_t max_fall) { max_fall_ = max_fall; } 581 582 private: 583 // Returns size of Colour child elements. 584 uint64_t PayloadSize() const; 585 586 uint64_t matrix_coefficients_; 587 uint64_t bits_per_channel_; 588 uint64_t chroma_subsampling_horz_; 589 uint64_t chroma_subsampling_vert_; 590 uint64_t cb_subsampling_horz_; 591 uint64_t cb_subsampling_vert_; 592 uint64_t chroma_siting_horz_; 593 uint64_t chroma_siting_vert_; 594 uint64_t range_; 595 uint64_t transfer_characteristics_; 596 uint64_t primaries_; 597 uint64_t max_cll_; 598 uint64_t max_fall_; 599 600 MasteringMetadata* mastering_metadata_; 601 }; 602 603 /////////////////////////////////////////////////////////////// 604 // Projection element. 605 class Projection { 606 public: 607 enum ProjectionType { 608 kTypeNotPresent = -1, 609 kRectangular = 0, 610 kEquirectangular = 1, 611 kCubeMap = 2, 612 kMesh = 3, 613 }; 614 static const uint64_t kValueNotPresent; Projection()615 Projection() 616 : type_(kRectangular), 617 pose_yaw_(0.0), 618 pose_pitch_(0.0), 619 pose_roll_(0.0), 620 private_data_(NULL), 621 private_data_length_(0) {} ~Projection()622 ~Projection() { delete[] private_data_; } 623 624 uint64_t ProjectionSize() const; 625 bool Write(IMkvWriter* writer) const; 626 627 bool SetProjectionPrivate(const uint8_t* private_data, 628 uint64_t private_data_length); 629 type()630 ProjectionType type() const { return type_; } set_type(ProjectionType type)631 void set_type(ProjectionType type) { type_ = type; } pose_yaw()632 float pose_yaw() const { return pose_yaw_; } set_pose_yaw(float pose_yaw)633 void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; } pose_pitch()634 float pose_pitch() const { return pose_pitch_; } set_pose_pitch(float pose_pitch)635 void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; } pose_roll()636 float pose_roll() const { return pose_roll_; } set_pose_roll(float pose_roll)637 void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; } private_data()638 uint8_t* private_data() const { return private_data_; } private_data_length()639 uint64_t private_data_length() const { return private_data_length_; } 640 641 private: 642 // Returns size of VideoProjection child elements. 643 uint64_t PayloadSize() const; 644 645 ProjectionType type_; 646 float pose_yaw_; 647 float pose_pitch_; 648 float pose_roll_; 649 uint8_t* private_data_; 650 uint64_t private_data_length_; 651 }; 652 653 /////////////////////////////////////////////////////////////// 654 // Track element. 655 class Track { 656 public: 657 // The |seed| parameter is used to synthesize a UID for the track. 658 explicit Track(unsigned int* seed); 659 virtual ~Track(); 660 661 // Adds a ContentEncoding element to the Track. Returns true on success. 662 virtual bool AddContentEncoding(); 663 664 // Returns the ContentEncoding by index. Returns NULL if there is no 665 // ContentEncoding match. 666 ContentEncoding* GetContentEncodingByIndex(uint32_t index) const; 667 668 // Returns the size in bytes for the payload of the Track element. 669 virtual uint64_t PayloadSize() const; 670 671 // Returns the size in bytes of the Track element. 672 virtual uint64_t Size() const; 673 674 // Output the Track element to the writer. Returns true on success. 675 virtual bool Write(IMkvWriter* writer) const; 676 677 // Sets the CodecPrivate element of the Track element. Copies |length| 678 // bytes from |codec_private| to |codec_private_|. Returns true on success. 679 bool SetCodecPrivate(const uint8_t* codec_private, uint64_t length); 680 681 void set_codec_id(const char* codec_id); codec_id()682 const char* codec_id() const { return codec_id_; } codec_private()683 const uint8_t* codec_private() const { return codec_private_; } 684 void set_language(const char* language); language()685 const char* language() const { return language_; } set_max_block_additional_id(uint64_t max_block_additional_id)686 void set_max_block_additional_id(uint64_t max_block_additional_id) { 687 max_block_additional_id_ = max_block_additional_id; 688 } max_block_additional_id()689 uint64_t max_block_additional_id() const { return max_block_additional_id_; } 690 void set_name(const char* name); name()691 const char* name() const { return name_; } set_number(uint64_t number)692 void set_number(uint64_t number) { number_ = number; } number()693 uint64_t number() const { return number_; } set_type(uint64_t type)694 void set_type(uint64_t type) { type_ = type; } type()695 uint64_t type() const { return type_; } set_uid(uint64_t uid)696 void set_uid(uint64_t uid) { uid_ = uid; } uid()697 uint64_t uid() const { return uid_; } set_codec_delay(uint64_t codec_delay)698 void set_codec_delay(uint64_t codec_delay) { codec_delay_ = codec_delay; } codec_delay()699 uint64_t codec_delay() const { return codec_delay_; } set_seek_pre_roll(uint64_t seek_pre_roll)700 void set_seek_pre_roll(uint64_t seek_pre_roll) { 701 seek_pre_roll_ = seek_pre_roll; 702 } seek_pre_roll()703 uint64_t seek_pre_roll() const { return seek_pre_roll_; } set_default_duration(uint64_t default_duration)704 void set_default_duration(uint64_t default_duration) { 705 default_duration_ = default_duration; 706 } default_duration()707 uint64_t default_duration() const { return default_duration_; } 708 codec_private_length()709 uint64_t codec_private_length() const { return codec_private_length_; } content_encoding_entries_size()710 uint32_t content_encoding_entries_size() const { 711 return content_encoding_entries_size_; 712 } 713 714 private: 715 // Track element names. 716 char* codec_id_; 717 uint8_t* codec_private_; 718 char* language_; 719 uint64_t max_block_additional_id_; 720 char* name_; 721 uint64_t number_; 722 uint64_t type_; 723 uint64_t uid_; 724 uint64_t codec_delay_; 725 uint64_t seek_pre_roll_; 726 uint64_t default_duration_; 727 728 // Size of the CodecPrivate data in bytes. 729 uint64_t codec_private_length_; 730 731 // ContentEncoding element list. 732 ContentEncoding** content_encoding_entries_; 733 734 // Number of ContentEncoding elements added. 735 uint32_t content_encoding_entries_size_; 736 737 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track); 738 }; 739 740 /////////////////////////////////////////////////////////////// 741 // Track that has video specific elements. 742 class VideoTrack : public Track { 743 public: 744 // Supported modes for stereo 3D. 745 enum StereoMode { 746 kMono = 0, 747 kSideBySideLeftIsFirst = 1, 748 kTopBottomRightIsFirst = 2, 749 kTopBottomLeftIsFirst = 3, 750 kSideBySideRightIsFirst = 11 751 }; 752 753 enum AlphaMode { kNoAlpha = 0, kAlpha = 1 }; 754 755 // The |seed| parameter is used to synthesize a UID for the track. 756 explicit VideoTrack(unsigned int* seed); 757 virtual ~VideoTrack(); 758 759 // Returns the size in bytes for the payload of the Track element plus the 760 // video specific elements. 761 virtual uint64_t PayloadSize() const; 762 763 // Output the VideoTrack element to the writer. Returns true on success. 764 virtual bool Write(IMkvWriter* writer) const; 765 766 // Sets the video's stereo mode. Returns true on success. 767 bool SetStereoMode(uint64_t stereo_mode); 768 769 // Sets the video's alpha mode. Returns true on success. 770 bool SetAlphaMode(uint64_t alpha_mode); 771 set_display_height(uint64_t height)772 void set_display_height(uint64_t height) { display_height_ = height; } display_height()773 uint64_t display_height() const { return display_height_; } set_display_width(uint64_t width)774 void set_display_width(uint64_t width) { display_width_ = width; } display_width()775 uint64_t display_width() const { return display_width_; } set_pixel_height(uint64_t height)776 void set_pixel_height(uint64_t height) { pixel_height_ = height; } pixel_height()777 uint64_t pixel_height() const { return pixel_height_; } set_pixel_width(uint64_t width)778 void set_pixel_width(uint64_t width) { pixel_width_ = width; } pixel_width()779 uint64_t pixel_width() const { return pixel_width_; } 780 set_crop_left(uint64_t crop_left)781 void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; } crop_left()782 uint64_t crop_left() const { return crop_left_; } set_crop_right(uint64_t crop_right)783 void set_crop_right(uint64_t crop_right) { crop_right_ = crop_right; } crop_right()784 uint64_t crop_right() const { return crop_right_; } set_crop_top(uint64_t crop_top)785 void set_crop_top(uint64_t crop_top) { crop_top_ = crop_top; } crop_top()786 uint64_t crop_top() const { return crop_top_; } set_crop_bottom(uint64_t crop_bottom)787 void set_crop_bottom(uint64_t crop_bottom) { crop_bottom_ = crop_bottom; } crop_bottom()788 uint64_t crop_bottom() const { return crop_bottom_; } 789 set_frame_rate(double frame_rate)790 void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; } frame_rate()791 double frame_rate() const { return frame_rate_; } set_height(uint64_t height)792 void set_height(uint64_t height) { height_ = height; } height()793 uint64_t height() const { return height_; } stereo_mode()794 uint64_t stereo_mode() { return stereo_mode_; } alpha_mode()795 uint64_t alpha_mode() { return alpha_mode_; } set_width(uint64_t width)796 void set_width(uint64_t width) { width_ = width; } width()797 uint64_t width() const { return width_; } 798 void set_colour_space(const char* colour_space); colour_space()799 const char* colour_space() const { return colour_space_; } 800 colour()801 Colour* colour() { return colour_; } 802 803 // Deep copies |colour|. 804 bool SetColour(const Colour& colour); 805 projection()806 Projection* projection() { return projection_; } 807 808 // Deep copies |projection|. 809 bool SetProjection(const Projection& projection); 810 811 private: 812 // Returns the size in bytes of the Video element. 813 uint64_t VideoPayloadSize() const; 814 815 // Video track element names. 816 uint64_t display_height_; 817 uint64_t display_width_; 818 uint64_t pixel_height_; 819 uint64_t pixel_width_; 820 uint64_t crop_left_; 821 uint64_t crop_right_; 822 uint64_t crop_top_; 823 uint64_t crop_bottom_; 824 double frame_rate_; 825 uint64_t height_; 826 uint64_t stereo_mode_; 827 uint64_t alpha_mode_; 828 uint64_t width_; 829 char* colour_space_; 830 831 Colour* colour_; 832 Projection* projection_; 833 834 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack); 835 }; 836 837 /////////////////////////////////////////////////////////////// 838 // Track that has audio specific elements. 839 class AudioTrack : public Track { 840 public: 841 // The |seed| parameter is used to synthesize a UID for the track. 842 explicit AudioTrack(unsigned int* seed); 843 virtual ~AudioTrack(); 844 845 // Returns the size in bytes for the payload of the Track element plus the 846 // audio specific elements. 847 virtual uint64_t PayloadSize() const; 848 849 // Output the AudioTrack element to the writer. Returns true on success. 850 virtual bool Write(IMkvWriter* writer) const; 851 set_bit_depth(uint64_t bit_depth)852 void set_bit_depth(uint64_t bit_depth) { bit_depth_ = bit_depth; } bit_depth()853 uint64_t bit_depth() const { return bit_depth_; } set_channels(uint64_t channels)854 void set_channels(uint64_t channels) { channels_ = channels; } channels()855 uint64_t channels() const { return channels_; } set_sample_rate(double sample_rate)856 void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; } sample_rate()857 double sample_rate() const { return sample_rate_; } 858 859 private: 860 // Audio track element names. 861 uint64_t bit_depth_; 862 uint64_t channels_; 863 double sample_rate_; 864 865 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack); 866 }; 867 868 /////////////////////////////////////////////////////////////// 869 // Tracks element 870 class Tracks { 871 public: 872 // Audio and video type defined by the Matroska specs. 873 enum { kVideo = 0x1, kAudio = 0x2 }; 874 875 static const char kOpusCodecId[]; 876 static const char kVorbisCodecId[]; 877 static const char kAv1CodecId[]; 878 static const char kVp8CodecId[]; 879 static const char kVp9CodecId[]; 880 static const char kWebVttCaptionsId[]; 881 static const char kWebVttDescriptionsId[]; 882 static const char kWebVttMetadataId[]; 883 static const char kWebVttSubtitlesId[]; 884 885 Tracks(); 886 ~Tracks(); 887 888 // Adds a Track element to the Tracks object. |track| will be owned and 889 // deleted by the Tracks object. Returns true on success. |number| is the 890 // number to use for the track. |number| must be >= 0. If |number| == 0 891 // then the muxer will decide on the track number. 892 bool AddTrack(Track* track, int32_t number); 893 894 // Returns the track by index. Returns NULL if there is no track match. 895 const Track* GetTrackByIndex(uint32_t idx) const; 896 897 // Search the Tracks and return the track that matches |tn|. Returns NULL 898 // if there is no track match. 899 Track* GetTrackByNumber(uint64_t track_number) const; 900 901 // Returns true if the track number is an audio track. 902 bool TrackIsAudio(uint64_t track_number) const; 903 904 // Returns true if the track number is a video track. 905 bool TrackIsVideo(uint64_t track_number) const; 906 907 // Output the Tracks element to the writer. Returns true on success. 908 bool Write(IMkvWriter* writer) const; 909 track_entries_size()910 uint32_t track_entries_size() const { return track_entries_size_; } 911 912 private: 913 // Track element list. 914 Track** track_entries_; 915 916 // Number of Track elements added. 917 uint32_t track_entries_size_; 918 919 // Whether or not Tracks element has already been written via IMkvWriter. 920 mutable bool wrote_tracks_; 921 922 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks); 923 }; 924 925 /////////////////////////////////////////////////////////////// 926 // Chapter element 927 // 928 class Chapter { 929 public: 930 // Set the identifier for this chapter. (This corresponds to the 931 // Cue Identifier line in WebVTT.) 932 // TODO(matthewjheaney): the actual serialization of this item in 933 // MKV is pending. 934 bool set_id(const char* id); 935 936 // Converts the nanosecond start and stop times of this chapter to 937 // their corresponding timecode values, and stores them that way. 938 void set_time(const Segment& segment, uint64_t start_time_ns, 939 uint64_t end_time_ns); 940 941 // Sets the uid for this chapter. Primarily used to enable 942 // deterministic output from the muxer. set_uid(const uint64_t uid)943 void set_uid(const uint64_t uid) { uid_ = uid; } 944 945 // Add a title string to this chapter, per the semantics described 946 // here: 947 // http://www.matroska.org/technical/specs/index.html 948 // 949 // The title ("chapter string") is a UTF-8 string. 950 // 951 // The language has ISO 639-2 representation, described here: 952 // http://www.loc.gov/standards/iso639-2/englangn.html 953 // http://www.loc.gov/standards/iso639-2/php/English_list.php 954 // If you specify NULL as the language value, this implies 955 // English ("eng"). 956 // 957 // The country value corresponds to the codes listed here: 958 // http://www.iana.org/domains/root/db/ 959 // 960 // The function returns false if the string could not be allocated. 961 bool add_string(const char* title, const char* language, const char* country); 962 963 private: 964 friend class Chapters; 965 966 // For storage of chapter titles that differ by language. 967 class Display { 968 public: 969 // Establish representation invariant for new Display object. 970 void Init(); 971 972 // Reclaim resources, in anticipation of destruction. 973 void Clear(); 974 975 // Copies the title to the |title_| member. Returns false on 976 // error. 977 bool set_title(const char* title); 978 979 // Copies the language to the |language_| member. Returns false 980 // on error. 981 bool set_language(const char* language); 982 983 // Copies the country to the |country_| member. Returns false on 984 // error. 985 bool set_country(const char* country); 986 987 // If |writer| is non-NULL, serialize the Display sub-element of 988 // the Atom into the stream. Returns the Display element size on 989 // success, 0 if error. 990 uint64_t WriteDisplay(IMkvWriter* writer) const; 991 992 private: 993 char* title_; 994 char* language_; 995 char* country_; 996 }; 997 998 Chapter(); 999 ~Chapter(); 1000 1001 // Establish the representation invariant for a newly-created 1002 // Chapter object. The |seed| parameter is used to create the UID 1003 // for this chapter atom. 1004 void Init(unsigned int* seed); 1005 1006 // Copies this Chapter object to a different one. This is used when 1007 // expanding a plain array of Chapter objects (see Chapters). 1008 void ShallowCopy(Chapter* dst) const; 1009 1010 // Reclaim resources used by this Chapter object, pending its 1011 // destruction. 1012 void Clear(); 1013 1014 // If there is no storage remaining on the |displays_| array for a 1015 // new display object, creates a new, longer array and copies the 1016 // existing Display objects to the new array. Returns false if the 1017 // array cannot be expanded. 1018 bool ExpandDisplaysArray(); 1019 1020 // If |writer| is non-NULL, serialize the Atom sub-element into the 1021 // stream. Returns the total size of the element on success, 0 if 1022 // error. 1023 uint64_t WriteAtom(IMkvWriter* writer) const; 1024 1025 // The string identifier for this chapter (corresponds to WebVTT cue 1026 // identifier). 1027 char* id_; 1028 1029 // Start timecode of the chapter. 1030 uint64_t start_timecode_; 1031 1032 // Stop timecode of the chapter. 1033 uint64_t end_timecode_; 1034 1035 // The binary identifier for this chapter. 1036 uint64_t uid_; 1037 1038 // The Atom element can contain multiple Display sub-elements, as 1039 // the same logical title can be rendered in different languages. 1040 Display* displays_; 1041 1042 // The physical length (total size) of the |displays_| array. 1043 int displays_size_; 1044 1045 // The logical length (number of active elements) on the |displays_| 1046 // array. 1047 int displays_count_; 1048 1049 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter); 1050 }; 1051 1052 /////////////////////////////////////////////////////////////// 1053 // Chapters element 1054 // 1055 class Chapters { 1056 public: 1057 Chapters(); 1058 ~Chapters(); 1059 1060 Chapter* AddChapter(unsigned int* seed); 1061 1062 // Returns the number of chapters that have been added. 1063 int Count() const; 1064 1065 // Output the Chapters element to the writer. Returns true on success. 1066 bool Write(IMkvWriter* writer) const; 1067 1068 private: 1069 // Expands the chapters_ array if there is not enough space to contain 1070 // another chapter object. Returns true on success. 1071 bool ExpandChaptersArray(); 1072 1073 // If |writer| is non-NULL, serialize the Edition sub-element of the 1074 // Chapters element into the stream. Returns the Edition element 1075 // size on success, 0 if error. 1076 uint64_t WriteEdition(IMkvWriter* writer) const; 1077 1078 // Total length of the chapters_ array. 1079 int chapters_size_; 1080 1081 // Number of active chapters on the chapters_ array. 1082 int chapters_count_; 1083 1084 // Array for storage of chapter objects. 1085 Chapter* chapters_; 1086 1087 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters); 1088 }; 1089 1090 /////////////////////////////////////////////////////////////// 1091 // Tag element 1092 // 1093 class Tag { 1094 public: 1095 bool add_simple_tag(const char* tag_name, const char* tag_string); 1096 1097 private: 1098 // Tags calls Clear and the destructor of Tag 1099 friend class Tags; 1100 1101 // For storage of simple tags 1102 class SimpleTag { 1103 public: 1104 // Establish representation invariant for new SimpleTag object. 1105 void Init(); 1106 1107 // Reclaim resources, in anticipation of destruction. 1108 void Clear(); 1109 1110 // Copies the title to the |tag_name_| member. Returns false on 1111 // error. 1112 bool set_tag_name(const char* tag_name); 1113 1114 // Copies the language to the |tag_string_| member. Returns false 1115 // on error. 1116 bool set_tag_string(const char* tag_string); 1117 1118 // If |writer| is non-NULL, serialize the SimpleTag sub-element of 1119 // the Atom into the stream. Returns the SimpleTag element size on 1120 // success, 0 if error. 1121 uint64_t Write(IMkvWriter* writer) const; 1122 1123 private: 1124 char* tag_name_; 1125 char* tag_string_; 1126 }; 1127 1128 Tag(); 1129 ~Tag(); 1130 1131 // Copies this Tag object to a different one. This is used when 1132 // expanding a plain array of Tag objects (see Tags). 1133 void ShallowCopy(Tag* dst) const; 1134 1135 // Reclaim resources used by this Tag object, pending its 1136 // destruction. 1137 void Clear(); 1138 1139 // If there is no storage remaining on the |simple_tags_| array for a 1140 // new display object, creates a new, longer array and copies the 1141 // existing SimpleTag objects to the new array. Returns false if the 1142 // array cannot be expanded. 1143 bool ExpandSimpleTagsArray(); 1144 1145 // If |writer| is non-NULL, serialize the Tag sub-element into the 1146 // stream. Returns the total size of the element on success, 0 if 1147 // error. 1148 uint64_t Write(IMkvWriter* writer) const; 1149 1150 // The Atom element can contain multiple SimpleTag sub-elements 1151 SimpleTag* simple_tags_; 1152 1153 // The physical length (total size) of the |simple_tags_| array. 1154 int simple_tags_size_; 1155 1156 // The logical length (number of active elements) on the |simple_tags_| 1157 // array. 1158 int simple_tags_count_; 1159 1160 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag); 1161 }; 1162 1163 /////////////////////////////////////////////////////////////// 1164 // Tags element 1165 // 1166 class Tags { 1167 public: 1168 Tags(); 1169 ~Tags(); 1170 1171 Tag* AddTag(); 1172 1173 // Returns the number of tags that have been added. 1174 int Count() const; 1175 1176 // Output the Tags element to the writer. Returns true on success. 1177 bool Write(IMkvWriter* writer) const; 1178 1179 private: 1180 // Expands the tags_ array if there is not enough space to contain 1181 // another tag object. Returns true on success. 1182 bool ExpandTagsArray(); 1183 1184 // Total length of the tags_ array. 1185 int tags_size_; 1186 1187 // Number of active tags on the tags_ array. 1188 int tags_count_; 1189 1190 // Array for storage of tag objects. 1191 Tag* tags_; 1192 1193 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags); 1194 }; 1195 1196 /////////////////////////////////////////////////////////////// 1197 // Cluster element 1198 // 1199 // Notes: 1200 // |Init| must be called before any other method in this class. 1201 class Cluster { 1202 public: 1203 // |timecode| is the absolute timecode of the cluster. |cues_pos| is the 1204 // position for the cluster within the segment that should be written in 1205 // the cues element. |timecode_scale| is the timecode scale of the segment. 1206 Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale, 1207 bool write_last_frame_with_duration = false, 1208 bool fixed_size_timecode = false); 1209 ~Cluster(); 1210 1211 bool Init(IMkvWriter* ptr_writer); 1212 1213 // Adds a frame to be output in the file. The frame is written out through 1214 // |writer_| if successful. Returns true on success. 1215 bool AddFrame(const Frame* frame); 1216 1217 // Adds a frame to be output in the file. The frame is written out through 1218 // |writer_| if successful. Returns true on success. 1219 // Inputs: 1220 // data: Pointer to the data 1221 // length: Length of the data 1222 // track_number: Track to add the data to. Value returned by Add track 1223 // functions. The range of allowed values is [1, 126]. 1224 // timecode: Absolute (not relative to cluster) timestamp of the 1225 // frame, expressed in timecode units. 1226 // is_key: Flag telling whether or not this frame is a key frame. 1227 bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, 1228 uint64_t timecode, // timecode units (absolute) 1229 bool is_key); 1230 1231 // Adds a frame to be output in the file. The frame is written out through 1232 // |writer_| if successful. Returns true on success. 1233 // Inputs: 1234 // data: Pointer to the data 1235 // length: Length of the data 1236 // additional: Pointer to the additional data 1237 // additional_length: Length of the additional data 1238 // add_id: Value of BlockAddID element 1239 // track_number: Track to add the data to. Value returned by Add track 1240 // functions. The range of allowed values is [1, 126]. 1241 // abs_timecode: Absolute (not relative to cluster) timestamp of the 1242 // frame, expressed in timecode units. 1243 // is_key: Flag telling whether or not this frame is a key frame. 1244 bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, 1245 const uint8_t* additional, 1246 uint64_t additional_length, uint64_t add_id, 1247 uint64_t track_number, uint64_t abs_timecode, 1248 bool is_key); 1249 1250 // Adds a frame to be output in the file. The frame is written out through 1251 // |writer_| if successful. Returns true on success. 1252 // Inputs: 1253 // data: Pointer to the data. 1254 // length: Length of the data. 1255 // discard_padding: DiscardPadding element value. 1256 // track_number: Track to add the data to. Value returned by Add track 1257 // functions. The range of allowed values is [1, 126]. 1258 // abs_timecode: Absolute (not relative to cluster) timestamp of the 1259 // frame, expressed in timecode units. 1260 // is_key: Flag telling whether or not this frame is a key frame. 1261 bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, 1262 int64_t discard_padding, 1263 uint64_t track_number, uint64_t abs_timecode, 1264 bool is_key); 1265 1266 // Writes a frame of metadata to the output medium; returns true on 1267 // success. 1268 // Inputs: 1269 // data: Pointer to the data 1270 // length: Length of the data 1271 // track_number: Track to add the data to. Value returned by Add track 1272 // functions. The range of allowed values is [1, 126]. 1273 // timecode: Absolute (not relative to cluster) timestamp of the 1274 // metadata frame, expressed in timecode units. 1275 // duration: Duration of metadata frame, in timecode units. 1276 // 1277 // The metadata frame is written as a block group, with a duration 1278 // sub-element but no reference time sub-elements (indicating that 1279 // it is considered a keyframe, per Matroska semantics). 1280 bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, 1281 uint64_t timecode, uint64_t duration); 1282 1283 // Increments the size of the cluster's data in bytes. 1284 void AddPayloadSize(uint64_t size); 1285 1286 // Closes the cluster so no more data can be written to it. Will update the 1287 // cluster's size if |writer_| is seekable. Returns true on success. This 1288 // variant of Finalize() fails when |write_last_frame_with_duration_| is set 1289 // to true. 1290 bool Finalize(); 1291 1292 // Closes the cluster so no more data can be written to it. Will update the 1293 // cluster's size if |writer_| is seekable. Returns true on success. 1294 // Inputs: 1295 // set_last_frame_duration: Boolean indicating whether or not the duration 1296 // of the last frame should be set. If set to 1297 // false, the |duration| value is ignored and 1298 // |write_last_frame_with_duration_| will not be 1299 // honored. 1300 // duration: Duration of the Cluster in timecode scale. 1301 bool Finalize(bool set_last_frame_duration, uint64_t duration); 1302 1303 // Returns the size in bytes for the entire Cluster element. 1304 uint64_t Size() const; 1305 1306 // Given |abs_timecode|, calculates timecode relative to most recent timecode. 1307 // Returns -1 on failure, or a relative timecode. 1308 int64_t GetRelativeTimecode(int64_t abs_timecode) const; 1309 size_position()1310 int64_t size_position() const { return size_position_; } blocks_added()1311 int32_t blocks_added() const { return blocks_added_; } payload_size()1312 uint64_t payload_size() const { return payload_size_; } position_for_cues()1313 int64_t position_for_cues() const { return position_for_cues_; } timecode()1314 uint64_t timecode() const { return timecode_; } timecode_scale()1315 uint64_t timecode_scale() const { return timecode_scale_; } set_write_last_frame_with_duration(bool write_last_frame_with_duration)1316 void set_write_last_frame_with_duration(bool write_last_frame_with_duration) { 1317 write_last_frame_with_duration_ = write_last_frame_with_duration; 1318 } write_last_frame_with_duration()1319 bool write_last_frame_with_duration() const { 1320 return write_last_frame_with_duration_; 1321 } 1322 1323 private: 1324 // Iterator type for the |stored_frames_| map. 1325 typedef std::map<uint64_t, std::list<Frame*> >::iterator FrameMapIterator; 1326 1327 // Utility method that confirms that blocks can still be added, and that the 1328 // cluster header has been written. Used by |DoWriteFrame*|. Returns true 1329 // when successful. 1330 bool PreWriteBlock(); 1331 1332 // Utility method used by the |DoWriteFrame*| methods that handles the book 1333 // keeping required after each block is written. 1334 void PostWriteBlock(uint64_t element_size); 1335 1336 // Does some verification and calls WriteFrame. 1337 bool DoWriteFrame(const Frame* const frame); 1338 1339 // Either holds back the given frame, or writes it out depending on whether or 1340 // not |write_last_frame_with_duration_| is set. 1341 bool QueueOrWriteFrame(const Frame* const frame); 1342 1343 // Outputs the Cluster header to |writer_|. Returns true on success. 1344 bool WriteClusterHeader(); 1345 1346 // Number of blocks added to the cluster. 1347 int32_t blocks_added_; 1348 1349 // Flag telling if the cluster has been closed. 1350 bool finalized_; 1351 1352 // Flag indicating whether the cluster's timecode will always be written out 1353 // using 8 bytes. 1354 bool fixed_size_timecode_; 1355 1356 // Flag telling if the cluster's header has been written. 1357 bool header_written_; 1358 1359 // The size of the cluster elements in bytes. 1360 uint64_t payload_size_; 1361 1362 // The file position used for cue points. 1363 const int64_t position_for_cues_; 1364 1365 // The file position of the cluster's size element. 1366 int64_t size_position_; 1367 1368 // The absolute timecode of the cluster. 1369 const uint64_t timecode_; 1370 1371 // The timecode scale of the Segment containing the cluster. 1372 const uint64_t timecode_scale_; 1373 1374 // Flag indicating whether the last frame of the cluster should be written as 1375 // a Block with Duration. If set to true, then it will result in holding back 1376 // of frames and the parameterized version of Finalize() must be called to 1377 // finish writing the Cluster. 1378 bool write_last_frame_with_duration_; 1379 1380 // Map used to hold back frames, if required. Track number is the key. 1381 std::map<uint64_t, std::list<Frame*> > stored_frames_; 1382 1383 // Map from track number to the timestamp of the last block written for that 1384 // track. 1385 std::map<uint64_t, uint64_t> last_block_timestamp_; 1386 1387 // Pointer to the writer object. Not owned by this class. 1388 IMkvWriter* writer_; 1389 1390 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster); 1391 }; 1392 1393 /////////////////////////////////////////////////////////////// 1394 // SeekHead element 1395 class SeekHead { 1396 public: 1397 SeekHead(); 1398 ~SeekHead(); 1399 1400 // TODO(fgalligan): Change this to reserve a certain size. Then check how 1401 // big the seek entry to be added is as not every seek entry will be the 1402 // maximum size it could be. 1403 // Adds a seek entry to be written out when the element is finalized. |id| 1404 // must be the coded mkv element id. |pos| is the file position of the 1405 // element. Returns true on success. 1406 bool AddSeekEntry(uint32_t id, uint64_t pos); 1407 1408 // Writes out SeekHead and SeekEntry elements. Returns true on success. 1409 bool Finalize(IMkvWriter* writer) const; 1410 1411 // Returns the id of the Seek Entry at the given index. Returns -1 if index is 1412 // out of range. 1413 uint32_t GetId(int index) const; 1414 1415 // Returns the position of the Seek Entry at the given index. Returns -1 if 1416 // index is out of range. 1417 uint64_t GetPosition(int index) const; 1418 1419 // Sets the Seek Entry id and position at given index. 1420 // Returns true on success. 1421 bool SetSeekEntry(int index, uint32_t id, uint64_t position); 1422 1423 // Reserves space by writing out a Void element which will be updated with 1424 // a SeekHead element later. Returns true on success. 1425 bool Write(IMkvWriter* writer); 1426 1427 // We are going to put a cap on the number of Seek Entries. 1428 const static int32_t kSeekEntryCount = 5; 1429 1430 private: 1431 // Returns the maximum size in bytes of one seek entry. 1432 uint64_t MaxEntrySize() const; 1433 1434 // Seek entry id element list. 1435 uint32_t seek_entry_id_[kSeekEntryCount]; 1436 1437 // Seek entry pos element list. 1438 uint64_t seek_entry_pos_[kSeekEntryCount]; 1439 1440 // The file position of SeekHead element. 1441 int64_t start_pos_; 1442 1443 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead); 1444 }; 1445 1446 /////////////////////////////////////////////////////////////// 1447 // Segment Information element 1448 class SegmentInfo { 1449 public: 1450 SegmentInfo(); 1451 ~SegmentInfo(); 1452 1453 // Will update the duration if |duration_| is > 0.0. Returns true on success. 1454 bool Finalize(IMkvWriter* writer) const; 1455 1456 // Sets |muxing_app_| and |writing_app_|. 1457 bool Init(); 1458 1459 // Output the Segment Information element to the writer. Returns true on 1460 // success. 1461 bool Write(IMkvWriter* writer); 1462 set_duration(double duration)1463 void set_duration(double duration) { duration_ = duration; } duration()1464 double duration() const { return duration_; } 1465 void set_muxing_app(const char* app); muxing_app()1466 const char* muxing_app() const { return muxing_app_; } set_timecode_scale(uint64_t scale)1467 void set_timecode_scale(uint64_t scale) { timecode_scale_ = scale; } timecode_scale()1468 uint64_t timecode_scale() const { return timecode_scale_; } 1469 void set_writing_app(const char* app); writing_app()1470 const char* writing_app() const { return writing_app_; } set_date_utc(int64_t date_utc)1471 void set_date_utc(int64_t date_utc) { date_utc_ = date_utc; } date_utc()1472 int64_t date_utc() const { return date_utc_; } 1473 1474 private: 1475 // Segment Information element names. 1476 // Initially set to -1 to signify that a duration has not been set and should 1477 // not be written out. 1478 double duration_; 1479 // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision. 1480 char* muxing_app_; 1481 uint64_t timecode_scale_; 1482 // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision. 1483 char* writing_app_; 1484 // LLONG_MIN when DateUTC is not set. 1485 int64_t date_utc_; 1486 1487 // The file position of the duration element. 1488 int64_t duration_pos_; 1489 1490 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo); 1491 }; 1492 1493 /////////////////////////////////////////////////////////////// 1494 // This class represents the main segment in a WebM file. Currently only 1495 // supports one Segment element. 1496 // 1497 // Notes: 1498 // |Init| must be called before any other method in this class. 1499 class Segment { 1500 public: 1501 enum Mode { kLive = 0x1, kFile = 0x2 }; 1502 1503 enum CuesPosition { 1504 kAfterClusters = 0x0, // Position Cues after Clusters - Default 1505 kBeforeClusters = 0x1 // Position Cues before Clusters 1506 }; 1507 1508 static const uint32_t kDefaultDocTypeVersion = 4; 1509 static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL; 1510 1511 Segment(); 1512 ~Segment(); 1513 1514 // Initializes |SegmentInfo| and returns result. Always returns false when 1515 // |ptr_writer| is NULL. 1516 bool Init(IMkvWriter* ptr_writer); 1517 1518 // Adds a generic track to the segment. Returns the newly-allocated 1519 // track object (which is owned by the segment) on success, NULL on 1520 // error. |number| is the number to use for the track. |number| 1521 // must be >= 0. If |number| == 0 then the muxer will decide on the 1522 // track number. 1523 Track* AddTrack(int32_t number); 1524 1525 // Adds a Vorbis audio track to the segment. Returns the number of the track 1526 // on success, 0 on error. |number| is the number to use for the audio track. 1527 // |number| must be >= 0. If |number| == 0 then the muxer will decide on 1528 // the track number. 1529 uint64_t AddAudioTrack(int32_t sample_rate, int32_t channels, int32_t number); 1530 1531 // Adds an empty chapter to the chapters of this segment. Returns 1532 // non-NULL on success. After adding the chapter, the caller should 1533 // populate its fields via the Chapter member functions. 1534 Chapter* AddChapter(); 1535 1536 // Adds an empty tag to the tags of this segment. Returns 1537 // non-NULL on success. After adding the tag, the caller should 1538 // populate its fields via the Tag member functions. 1539 Tag* AddTag(); 1540 1541 // Adds a cue point to the Cues element. |timestamp| is the time in 1542 // nanoseconds of the cue's time. |track| is the Track of the Cue. This 1543 // function must be called after AddFrame to calculate the correct 1544 // BlockNumber for the CuePoint. Returns true on success. 1545 bool AddCuePoint(uint64_t timestamp, uint64_t track); 1546 1547 // Adds a frame to be output in the file. Returns true on success. 1548 // Inputs: 1549 // data: Pointer to the data 1550 // length: Length of the data 1551 // track_number: Track to add the data to. Value returned by Add track 1552 // functions. 1553 // timestamp: Timestamp of the frame in nanoseconds from 0. 1554 // is_key: Flag telling whether or not this frame is a key frame. 1555 bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, 1556 uint64_t timestamp_ns, bool is_key); 1557 1558 // Writes a frame of metadata to the output medium; returns true on 1559 // success. 1560 // Inputs: 1561 // data: Pointer to the data 1562 // length: Length of the data 1563 // track_number: Track to add the data to. Value returned by Add track 1564 // functions. 1565 // timecode: Absolute timestamp of the metadata frame, expressed 1566 // in nanosecond units. 1567 // duration: Duration of metadata frame, in nanosecond units. 1568 // 1569 // The metadata frame is written as a block group, with a duration 1570 // sub-element but no reference time sub-elements (indicating that 1571 // it is considered a keyframe, per Matroska semantics). 1572 bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, 1573 uint64_t timestamp_ns, uint64_t duration_ns); 1574 1575 // Writes a frame with additional data to the output medium; returns true on 1576 // success. 1577 // Inputs: 1578 // data: Pointer to the data. 1579 // length: Length of the data. 1580 // additional: Pointer to additional data. 1581 // additional_length: Length of additional data. 1582 // add_id: Additional ID which identifies the type of additional data. 1583 // track_number: Track to add the data to. Value returned by Add track 1584 // functions. 1585 // timestamp: Absolute timestamp of the frame, expressed in nanosecond 1586 // units. 1587 // is_key: Flag telling whether or not this frame is a key frame. 1588 bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, 1589 const uint8_t* additional, 1590 uint64_t additional_length, uint64_t add_id, 1591 uint64_t track_number, uint64_t timestamp, 1592 bool is_key); 1593 1594 // Writes a frame with DiscardPadding to the output medium; returns true on 1595 // success. 1596 // Inputs: 1597 // data: Pointer to the data. 1598 // length: Length of the data. 1599 // discard_padding: DiscardPadding element value. 1600 // track_number: Track to add the data to. Value returned by Add track 1601 // functions. 1602 // timestamp: Absolute timestamp of the frame, expressed in nanosecond 1603 // units. 1604 // is_key: Flag telling whether or not this frame is a key frame. 1605 bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, 1606 int64_t discard_padding, 1607 uint64_t track_number, uint64_t timestamp, 1608 bool is_key); 1609 1610 // Writes a Frame to the output medium. Chooses the correct way of writing 1611 // the frame (Block vs SimpleBlock) based on the parameters passed. 1612 // Inputs: 1613 // frame: frame object 1614 bool AddGenericFrame(const Frame* frame); 1615 1616 // Adds a VP8 video track to the segment. Returns the number of the track on 1617 // success, 0 on error. |number| is the number to use for the video track. 1618 // |number| must be >= 0. If |number| == 0 then the muxer will decide on 1619 // the track number. 1620 uint64_t AddVideoTrack(int32_t width, int32_t height, int32_t number); 1621 1622 // This function must be called after Finalize() if you need a copy of the 1623 // output with Cues written before the Clusters. It will return false if the 1624 // writer is not seekable of if chunking is set to true. 1625 // Input parameters: 1626 // reader - an IMkvReader object created with the same underlying file of the 1627 // current writer object. Make sure to close the existing writer 1628 // object before creating this so that all the data is properly 1629 // flushed and available for reading. 1630 // writer - an IMkvWriter object pointing to a *different* file than the one 1631 // pointed by the current writer object. This file will contain the 1632 // Cues element before the Clusters. 1633 bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader, 1634 IMkvWriter* writer); 1635 1636 // Sets which track to use for the Cues element. Must have added the track 1637 // before calling this function. Returns true on success. |track_number| is 1638 // returned by the Add track functions. 1639 bool CuesTrack(uint64_t track_number); 1640 1641 // This will force the muxer to create a new Cluster when the next frame is 1642 // added. 1643 void ForceNewClusterOnNextFrame(); 1644 1645 // Writes out any frames that have not been written out. Finalizes the last 1646 // cluster. May update the size and duration of the segment. May output the 1647 // Cues element. May finalize the SeekHead element. Returns true on success. 1648 bool Finalize(); 1649 1650 // Returns the Cues object. GetCues()1651 Cues* GetCues() { return &cues_; } 1652 1653 // Returns the Segment Information object. GetSegmentInfo()1654 const SegmentInfo* GetSegmentInfo() const { return &segment_info_; } GetSegmentInfo()1655 SegmentInfo* GetSegmentInfo() { return &segment_info_; } 1656 1657 // Search the Tracks and return the track that matches |track_number|. 1658 // Returns NULL if there is no track match. 1659 Track* GetTrackByNumber(uint64_t track_number) const; 1660 1661 // Toggles whether to output a cues element. 1662 void OutputCues(bool output_cues); 1663 1664 // Toggles whether to write the last frame in each Cluster with Duration. 1665 void AccurateClusterDuration(bool accurate_cluster_duration); 1666 1667 // Toggles whether to write the Cluster Timecode using exactly 8 bytes. 1668 void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode); 1669 1670 // Sets if the muxer will output files in chunks or not. |chunking| is a 1671 // flag telling whether or not to turn on chunking. |filename| is the base 1672 // filename for the chunk files. The header chunk file will be named 1673 // |filename|.hdr and the data chunks will be named 1674 // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing 1675 // to files so the muxer will use the default MkvWriter class to control 1676 // what data is written to what files. Returns true on success. 1677 // TODO: Should we change the IMkvWriter Interface to add Open and Close? 1678 // That will force the interface to be dependent on files. 1679 bool SetChunking(bool chunking, const char* filename); 1680 chunking()1681 bool chunking() const { return chunking_; } cues_track()1682 uint64_t cues_track() const { return cues_track_; } set_max_cluster_duration(uint64_t max_cluster_duration)1683 void set_max_cluster_duration(uint64_t max_cluster_duration) { 1684 max_cluster_duration_ = max_cluster_duration; 1685 } max_cluster_duration()1686 uint64_t max_cluster_duration() const { return max_cluster_duration_; } set_max_cluster_size(uint64_t max_cluster_size)1687 void set_max_cluster_size(uint64_t max_cluster_size) { 1688 max_cluster_size_ = max_cluster_size; 1689 } max_cluster_size()1690 uint64_t max_cluster_size() const { return max_cluster_size_; } set_mode(Mode mode)1691 void set_mode(Mode mode) { mode_ = mode; } mode()1692 Mode mode() const { return mode_; } cues_position()1693 CuesPosition cues_position() const { return cues_position_; } output_cues()1694 bool output_cues() const { return output_cues_; } set_estimate_file_duration(bool estimate_duration)1695 void set_estimate_file_duration(bool estimate_duration) { 1696 estimate_file_duration_ = estimate_duration; 1697 } estimate_file_duration()1698 bool estimate_file_duration() const { return estimate_file_duration_; } segment_info()1699 const SegmentInfo* segment_info() const { return &segment_info_; } set_duration(double duration)1700 void set_duration(double duration) { duration_ = duration; } duration()1701 double duration() const { return duration_; } 1702 1703 // Returns true when codec IDs are valid for WebM. 1704 bool DocTypeIsWebm() const; 1705 1706 private: 1707 // Checks if header information has been output and initialized. If not it 1708 // will output the Segment element and initialize the SeekHead elment and 1709 // Cues elements. 1710 bool CheckHeaderInfo(); 1711 1712 // Sets |doc_type_version_| based on the current element requirements. 1713 void UpdateDocTypeVersion(); 1714 1715 // Sets |name| according to how many chunks have been written. |ext| is the 1716 // file extension. |name| must be deleted by the calling app. Returns true 1717 // on success. 1718 bool UpdateChunkName(const char* ext, char** name) const; 1719 1720 // Returns the maximum offset within the segment's payload. When chunking 1721 // this function is needed to determine offsets of elements within the 1722 // chunked files. Returns -1 on error. 1723 int64_t MaxOffset(); 1724 1725 // Adds the frame to our frame array. 1726 bool QueueFrame(Frame* frame); 1727 1728 // Output all frames that are queued. Returns -1 on error, otherwise 1729 // it returns the number of frames written. 1730 int WriteFramesAll(); 1731 1732 // Output all frames that are queued that have an end time that is less 1733 // then |timestamp|. Returns true on success and if there are no frames 1734 // queued. 1735 bool WriteFramesLessThan(uint64_t timestamp); 1736 1737 // Outputs the segment header, Segment Information element, SeekHead element, 1738 // and Tracks element to |writer_|. 1739 bool WriteSegmentHeader(); 1740 1741 // Given a frame with the specified timestamp (nanosecond units) and 1742 // keyframe status, determine whether a new cluster should be 1743 // created, before writing enqueued frames and the frame itself. The 1744 // function returns one of the following values: 1745 // -1 = error: an out-of-order frame was detected 1746 // 0 = do not create a new cluster, and write frame to the existing cluster 1747 // 1 = create a new cluster, and write frame to that new cluster 1748 // 2 = create a new cluster, and re-run test 1749 int TestFrame(uint64_t track_num, uint64_t timestamp_ns, bool key) const; 1750 1751 // Create a new cluster, using the earlier of the first enqueued 1752 // frame, or the indicated time. Returns true on success. 1753 bool MakeNewCluster(uint64_t timestamp_ns); 1754 1755 // Checks whether a new cluster needs to be created, and if so 1756 // creates a new cluster. Returns false if creation of a new cluster 1757 // was necessary but creation was not successful. 1758 bool DoNewClusterProcessing(uint64_t track_num, uint64_t timestamp_ns, 1759 bool key); 1760 1761 // Adjusts Cue Point values (to place Cues before Clusters) so that they 1762 // reflect the correct offsets. 1763 void MoveCuesBeforeClusters(); 1764 1765 // This function recursively computes the correct cluster offsets (this is 1766 // done to move the Cues before Clusters). It recursively updates the change 1767 // in size (which indicates a change in cluster offset) until no sizes change. 1768 // Parameters: 1769 // diff - indicates the difference in size of the Cues element that needs to 1770 // accounted for. 1771 // index - index in the list of Cues which is currently being adjusted. 1772 // cue_size - sum of size of all the CuePoint elements. 1773 void MoveCuesBeforeClustersHelper(uint64_t diff, int index, 1774 uint64_t* cue_size); 1775 1776 // Seeds the random number generator used to make UIDs. 1777 unsigned int seed_; 1778 1779 // WebM elements 1780 Cues cues_; 1781 SeekHead seek_head_; 1782 SegmentInfo segment_info_; 1783 Tracks tracks_; 1784 Chapters chapters_; 1785 Tags tags_; 1786 1787 // Number of chunks written. 1788 int chunk_count_; 1789 1790 // Current chunk filename. 1791 char* chunk_name_; 1792 1793 // Default MkvWriter object created by this class used for writing clusters 1794 // out in separate files. 1795 MkvWriter* chunk_writer_cluster_; 1796 1797 // Default MkvWriter object created by this class used for writing Cues 1798 // element out to a file. 1799 MkvWriter* chunk_writer_cues_; 1800 1801 // Default MkvWriter object created by this class used for writing the 1802 // Matroska header out to a file. 1803 MkvWriter* chunk_writer_header_; 1804 1805 // Flag telling whether or not the muxer is chunking output to multiple 1806 // files. 1807 bool chunking_; 1808 1809 // Base filename for the chunked files. 1810 char* chunking_base_name_; 1811 1812 // File position offset where the Clusters end. 1813 int64_t cluster_end_offset_; 1814 1815 // List of clusters. 1816 Cluster** cluster_list_; 1817 1818 // Number of cluster pointers allocated in the cluster list. 1819 int32_t cluster_list_capacity_; 1820 1821 // Number of clusters in the cluster list. 1822 int32_t cluster_list_size_; 1823 1824 // Indicates whether Cues should be written before or after Clusters 1825 CuesPosition cues_position_; 1826 1827 // Track number that is associated with the cues element for this segment. 1828 uint64_t cues_track_; 1829 1830 // Tells the muxer to force a new cluster on the next Block. 1831 bool force_new_cluster_; 1832 1833 // List of stored audio frames. These variables are used to store frames so 1834 // the muxer can follow the guideline "Audio blocks that contain the video 1835 // key frame's timecode should be in the same cluster as the video key frame 1836 // block." 1837 Frame** frames_; 1838 1839 // Number of frame pointers allocated in the frame list. 1840 int32_t frames_capacity_; 1841 1842 // Number of frames in the frame list. 1843 int32_t frames_size_; 1844 1845 // Flag telling if a video track has been added to the segment. 1846 bool has_video_; 1847 1848 // Flag telling if the segment's header has been written. 1849 bool header_written_; 1850 1851 // Duration of the last block in nanoseconds. 1852 uint64_t last_block_duration_; 1853 1854 // Last timestamp in nanoseconds added to a cluster. 1855 uint64_t last_timestamp_; 1856 1857 // Last timestamp in nanoseconds by track number added to a cluster. 1858 uint64_t last_track_timestamp_[kMaxTrackNumber]; 1859 1860 // Number of frames written per track. 1861 uint64_t track_frames_written_[kMaxTrackNumber]; 1862 1863 // Maximum time in nanoseconds for a cluster duration. This variable is a 1864 // guideline and some clusters may have a longer duration. Default is 30 1865 // seconds. 1866 uint64_t max_cluster_duration_; 1867 1868 // Maximum size in bytes for a cluster. This variable is a guideline and 1869 // some clusters may have a larger size. Default is 0 which signifies that 1870 // the muxer will decide the size. 1871 uint64_t max_cluster_size_; 1872 1873 // The mode that segment is in. If set to |kLive| the writer must not 1874 // seek backwards. 1875 Mode mode_; 1876 1877 // Flag telling the muxer that a new cue point should be added. 1878 bool new_cuepoint_; 1879 1880 // TODO(fgalligan): Should we add support for more than one Cues element? 1881 // Flag whether or not the muxer should output a Cues element. 1882 bool output_cues_; 1883 1884 // Flag whether or not the last frame in each Cluster will have a Duration 1885 // element in it. 1886 bool accurate_cluster_duration_; 1887 1888 // Flag whether or not to write the Cluster Timecode using exactly 8 bytes. 1889 bool fixed_size_cluster_timecode_; 1890 1891 // Flag whether or not to estimate the file duration. 1892 bool estimate_file_duration_; 1893 1894 // The size of the EBML header, used to validate the header if 1895 // WriteEbmlHeader() is called more than once. 1896 int32_t ebml_header_size_; 1897 1898 // The file position of the segment's payload. 1899 int64_t payload_pos_; 1900 1901 // The file position of the element's size. 1902 int64_t size_position_; 1903 1904 // Current DocTypeVersion (|doc_type_version_|) and that written in 1905 // WriteSegmentHeader(). 1906 // WriteEbmlHeader() will be called from Finalize() if |doc_type_version_| 1907 // differs from |doc_type_version_written_|. 1908 uint32_t doc_type_version_; 1909 uint32_t doc_type_version_written_; 1910 1911 // If |duration_| is > 0, then explicitly set the duration of the segment. 1912 double duration_; 1913 1914 // Pointer to the writer objects. Not owned by this class. 1915 IMkvWriter* writer_cluster_; 1916 IMkvWriter* writer_cues_; 1917 IMkvWriter* writer_header_; 1918 1919 LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment); 1920 }; 1921 1922 } // namespace mkvmuxer 1923 1924 #endif // MKVMUXER_MKVMUXER_H_ 1925