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