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