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