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