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