1// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree. An additional intellectual property rights grant can be found
6// in the file PATENTS.  All contributing project authors may
7// be found in the AUTHORS file in the root of the source tree.
8
9#ifndef MKVMUXER_HPP
10#define MKVMUXER_HPP
11
12#include "mkvmuxertypes.hpp"
13
14// For a description of the WebM elements see
15// http://www.webmproject.org/code/specs/container/.
16
17namespace mkvparser {
18  class IMkvReader;
19}  // end namespace
20
21namespace mkvmuxer {
22
23class MkvWriter;
24class Segment;
25
26///////////////////////////////////////////////////////////////
27// Interface used by the mkvmuxer to write out the Mkv data.
28class IMkvWriter {
29 public:
30  // Writes out |len| bytes of |buf|. Returns 0 on success.
31  virtual int32 Write(const void* buf, uint32 len) = 0;
32
33  // Returns the offset of the output position from the beginning of the
34  // output.
35  virtual int64 Position() const = 0;
36
37  // Set the current File position. Returns 0 on success.
38  virtual int32 Position(int64 position) = 0;
39
40  // Returns true if the writer is seekable.
41  virtual bool Seekable() const = 0;
42
43  // Element start notification. Called whenever an element identifier is about
44  // to be written to the stream. |element_id| is the element identifier, and
45  // |position| is the location in the WebM stream where the first octet of the
46  // element identifier will be written.
47  // Note: the |MkvId| enumeration in webmids.hpp defines element values.
48  virtual void ElementStartNotify(uint64 element_id, int64 position) = 0;
49
50 protected:
51  IMkvWriter();
52  virtual ~IMkvWriter();
53
54 private:
55  LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter);
56};
57
58// Writes out the EBML header for a WebM file. This function must be called
59// before any other libwebm writing functions are called.
60bool WriteEbmlHeader(IMkvWriter* writer);
61
62// Copies in Chunk from source to destination between the given byte positions
63bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst,
64                 int64 start, int64 size);
65
66///////////////////////////////////////////////////////////////
67// Class to hold data the will be written to a block.
68class Frame {
69 public:
70  Frame();
71  ~Frame();
72
73  // Copies |frame| data into |frame_|. Returns true on success.
74  bool Init(const uint8* frame, uint64 length);
75
76  // Copies |additional| data into |additional_|. Returns true on success.
77  bool AddAdditionalData(const uint8* additional, uint64 length,
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.
132class 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.
181class 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
224class 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.
260class 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.
307class 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.
389class 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.
453class 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
484class 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//
537class 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//
667class 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.
707class 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
920class 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
973class 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.
1020class 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
1404