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