Home | History | Annotate | Download | only in mkvmuxer
      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_MKVMUXER_H_
     10 #define MKVMUXER_MKVMUXER_H_
     11 
     12 #include <stdint.h>
     13 
     14 #include <cstddef>
     15 #include <list>
     16 #include <map>
     17 
     18 #include "common/webmids.h"
     19 #include "mkvmuxer/mkvmuxertypes.h"
     20 
     21 // For a description of the WebM elements see
     22 // http://www.webmproject.org/code/specs/container/.
     23 
     24 namespace mkvparser {
     25 class IMkvReader;
     26 }  // namespace mkvparser
     27 
     28 namespace mkvmuxer {
     29 
     30 class MkvWriter;
     31 class Segment;
     32 
     33 const uint64_t kMaxTrackNumber = 126;
     34 
     35 ///////////////////////////////////////////////////////////////
     36 // Interface used by the mkvmuxer to write out the Mkv data.
     37 class IMkvWriter {
     38  public:
     39   // Writes out |len| bytes of |buf|. Returns 0 on success.
     40   virtual int32 Write(const void* buf, uint32 len) = 0;
     41 
     42   // Returns the offset of the output position from the beginning of the
     43   // output.
     44   virtual int64 Position() const = 0;
     45 
     46   // Set the current File position. Returns 0 on success.
     47   virtual int32 Position(int64 position) = 0;
     48 
     49   // Returns true if the writer is seekable.
     50   virtual bool Seekable() const = 0;
     51 
     52   // Element start notification. Called whenever an element identifier is about
     53   // to be written to the stream. |element_id| is the element identifier, and
     54   // |position| is the location in the WebM stream where the first octet of the
     55   // element identifier will be written.
     56   // Note: the |MkvId| enumeration in webmids.hpp defines element values.
     57   virtual void ElementStartNotify(uint64 element_id, int64 position) = 0;
     58 
     59  protected:
     60   IMkvWriter();
     61   virtual ~IMkvWriter();
     62 
     63  private:
     64   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter);
     65 };
     66 
     67 // Writes out the EBML header for a WebM file, but allows caller to specify
     68 // DocType. This function must be called before any other libwebm writing
     69 // functions are called.
     70 bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version,
     71                      const char* const doc_type);
     72 
     73 // Writes out the EBML header for a WebM file. This function must be called
     74 // before any other libwebm writing functions are called.
     75 bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version);
     76 
     77 // Deprecated. Writes out EBML header with doc_type_version as
     78 // kDefaultDocTypeVersion. Exists for backward compatibility.
     79 bool WriteEbmlHeader(IMkvWriter* writer);
     80 
     81 // Copies in Chunk from source to destination between the given byte positions
     82 bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64_t start,
     83                  int64_t size);
     84 
     85 ///////////////////////////////////////////////////////////////
     86 // Class to hold data the will be written to a block.
     87 class Frame {
     88  public:
     89   Frame();
     90   ~Frame();
     91 
     92   // Sets this frame's contents based on |frame|. Returns true on success. On
     93   // failure, this frame's existing contents may be lost.
     94   bool CopyFrom(const Frame& frame);
     95 
     96   // Copies |frame| data into |frame_|. Returns true on success.
     97   bool Init(const uint8_t* frame, uint64_t length);
     98 
     99   // Copies |additional| data into |additional_|. Returns true on success.
    100   bool AddAdditionalData(const uint8_t* additional, uint64_t length,
    101                          uint64_t add_id);
    102 
    103   // Returns true if the frame has valid parameters.
    104   bool IsValid() const;
    105 
    106   // Returns true if the frame can be written as a SimpleBlock based on current
    107   // parameters.
    108   bool CanBeSimpleBlock() const;
    109 
    110   uint64_t add_id() const { return add_id_; }
    111   const uint8_t* additional() const { return additional_; }
    112   uint64_t additional_length() const { return additional_length_; }
    113   void set_duration(uint64_t duration);
    114   uint64_t duration() const { return duration_; }
    115   bool duration_set() const { return duration_set_; }
    116   const uint8_t* frame() const { return frame_; }
    117   void set_is_key(bool key) { is_key_ = key; }
    118   bool is_key() const { return is_key_; }
    119   uint64_t length() const { return length_; }
    120   void set_track_number(uint64_t track_number) { track_number_ = track_number; }
    121   uint64_t track_number() const { return track_number_; }
    122   void set_timestamp(uint64_t timestamp) { timestamp_ = timestamp; }
    123   uint64_t timestamp() const { return timestamp_; }
    124   void set_discard_padding(int64_t discard_padding) {
    125     discard_padding_ = discard_padding;
    126   }
    127   int64_t discard_padding() const { return discard_padding_; }
    128   void set_reference_block_timestamp(int64_t reference_block_timestamp);
    129   int64_t reference_block_timestamp() const {
    130     return reference_block_timestamp_;
    131   }
    132   bool reference_block_timestamp_set() const {
    133     return reference_block_timestamp_set_;
    134   }
    135 
    136  private:
    137   // Id of the Additional data.
    138   uint64_t add_id_;
    139 
    140   // Pointer to additional data. Owned by this class.
    141   uint8_t* additional_;
    142 
    143   // Length of the additional data.
    144   uint64_t additional_length_;
    145 
    146   // Duration of the frame in nanoseconds.
    147   uint64_t duration_;
    148 
    149   // Flag indicating that |duration_| has been set. Setting duration causes the
    150   // frame to be written out as a Block with BlockDuration instead of as a
    151   // SimpleBlock.
    152   bool duration_set_;
    153 
    154   // Pointer to the data. Owned by this class.
    155   uint8_t* frame_;
    156 
    157   // Flag telling if the data should set the key flag of a block.
    158   bool is_key_;
    159 
    160   // Length of the data.
    161   uint64_t length_;
    162 
    163   // Mkv track number the data is associated with.
    164   uint64_t track_number_;
    165 
    166   // Timestamp of the data in nanoseconds.
    167   uint64_t timestamp_;
    168 
    169   // Discard padding for the frame.
    170   int64_t discard_padding_;
    171 
    172   // Reference block timestamp.
    173   int64_t reference_block_timestamp_;
    174 
    175   // Flag indicating if |reference_block_timestamp_| has been set.
    176   bool reference_block_timestamp_set_;
    177 
    178   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame);
    179 };
    180 
    181 ///////////////////////////////////////////////////////////////
    182 // Class to hold one cue point in a Cues element.
    183 class CuePoint {
    184  public:
    185   CuePoint();
    186   ~CuePoint();
    187 
    188   // Returns the size in bytes for the entire CuePoint element.
    189   uint64_t Size() const;
    190 
    191   // Output the CuePoint element to the writer. Returns true on success.
    192   bool Write(IMkvWriter* writer) const;
    193 
    194   void set_time(uint64_t time) { time_ = time; }
    195   uint64_t time() const { return time_; }
    196   void set_track(uint64_t track) { track_ = track; }
    197   uint64_t track() const { return track_; }
    198   void set_cluster_pos(uint64_t cluster_pos) { cluster_pos_ = cluster_pos; }
    199   uint64_t cluster_pos() const { return cluster_pos_; }
    200   void set_block_number(uint64_t block_number) { block_number_ = block_number; }
    201   uint64_t block_number() const { return block_number_; }
    202   void set_output_block_number(bool output_block_number) {
    203     output_block_number_ = output_block_number;
    204   }
    205   bool output_block_number() const { return output_block_number_; }
    206 
    207  private:
    208   // Returns the size in bytes for the payload of the CuePoint element.
    209   uint64_t PayloadSize() const;
    210 
    211   // Absolute timecode according to the segment time base.
    212   uint64_t time_;
    213 
    214   // The Track element associated with the CuePoint.
    215   uint64_t track_;
    216 
    217   // The position of the Cluster containing the Block.
    218   uint64_t cluster_pos_;
    219 
    220   // Number of the Block within the Cluster, starting from 1.
    221   uint64_t block_number_;
    222 
    223   // If true the muxer will write out the block number for the cue if the
    224   // block number is different than the default of 1. Default is set to true.
    225   bool output_block_number_;
    226 
    227   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint);
    228 };
    229 
    230 ///////////////////////////////////////////////////////////////
    231 // Cues element.
    232 class Cues {
    233  public:
    234   Cues();
    235   ~Cues();
    236 
    237   // Adds a cue point to the Cues element. Returns true on success.
    238   bool AddCue(CuePoint* cue);
    239 
    240   // Returns the cue point by index. Returns NULL if there is no cue point
    241   // match.
    242   CuePoint* GetCueByIndex(int32_t index) const;
    243 
    244   // Returns the total size of the Cues element
    245   uint64_t Size();
    246 
    247   // Output the Cues element to the writer. Returns true on success.
    248   bool Write(IMkvWriter* writer) const;
    249 
    250   int32_t cue_entries_size() const { return cue_entries_size_; }
    251   void set_output_block_number(bool output_block_number) {
    252     output_block_number_ = output_block_number;
    253   }
    254   bool output_block_number() const { return output_block_number_; }
    255 
    256  private:
    257   // Number of allocated elements in |cue_entries_|.
    258   int32_t cue_entries_capacity_;
    259 
    260   // Number of CuePoints in |cue_entries_|.
    261   int32_t cue_entries_size_;
    262 
    263   // CuePoint list.
    264   CuePoint** cue_entries_;
    265 
    266   // If true the muxer will write out the block number for the cue if the
    267   // block number is different than the default of 1. Default is set to true.
    268   bool output_block_number_;
    269 
    270   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues);
    271 };
    272 
    273 ///////////////////////////////////////////////////////////////
    274 // ContentEncAESSettings element
    275 class ContentEncAESSettings {
    276  public:
    277   enum { kCTR = 1 };
    278 
    279   ContentEncAESSettings();
    280   ~ContentEncAESSettings() {}
    281 
    282   // Returns the size in bytes for the ContentEncAESSettings element.
    283   uint64_t Size() const;
    284 
    285   // Writes out the ContentEncAESSettings element to |writer|. Returns true on
    286   // success.
    287   bool Write(IMkvWriter* writer) const;
    288 
    289   uint64_t cipher_mode() const { return cipher_mode_; }
    290 
    291  private:
    292   // Returns the size in bytes for the payload of the ContentEncAESSettings
    293   // element.
    294   uint64_t PayloadSize() const;
    295 
    296   // Sub elements
    297   uint64_t cipher_mode_;
    298 
    299   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings);
    300 };
    301 
    302 ///////////////////////////////////////////////////////////////
    303 // ContentEncoding element
    304 // Elements used to describe if the track data has been encrypted or
    305 // compressed with zlib or header stripping.
    306 // Currently only whole frames can be encrypted with AES. This dictates that
    307 // ContentEncodingOrder will be 0, ContentEncodingScope will be 1,
    308 // ContentEncodingType will be 1, and ContentEncAlgo will be 5.
    309 class ContentEncoding {
    310  public:
    311   ContentEncoding();
    312   ~ContentEncoding();
    313 
    314   // Sets the content encryption id. Copies |length| bytes from |id| to
    315   // |enc_key_id_|. Returns true on success.
    316   bool SetEncryptionID(const uint8_t* id, uint64_t length);
    317 
    318   // Returns the size in bytes for the ContentEncoding element.
    319   uint64_t Size() const;
    320 
    321   // Writes out the ContentEncoding element to |writer|. Returns true on
    322   // success.
    323   bool Write(IMkvWriter* writer) const;
    324 
    325   uint64_t enc_algo() const { return enc_algo_; }
    326   uint64_t encoding_order() const { return encoding_order_; }
    327   uint64_t encoding_scope() const { return encoding_scope_; }
    328   uint64_t encoding_type() const { return encoding_type_; }
    329   ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; }
    330 
    331  private:
    332   // Returns the size in bytes for the encoding elements.
    333   uint64_t EncodingSize(uint64_t compresion_size,
    334                         uint64_t encryption_size) const;
    335 
    336   // Returns the size in bytes for the encryption elements.
    337   uint64_t EncryptionSize() const;
    338 
    339   // Track element names
    340   uint64_t enc_algo_;
    341   uint8_t* enc_key_id_;
    342   uint64_t encoding_order_;
    343   uint64_t encoding_scope_;
    344   uint64_t encoding_type_;
    345 
    346   // ContentEncAESSettings element.
    347   ContentEncAESSettings enc_aes_settings_;
    348 
    349   // Size of the ContentEncKeyID data in bytes.
    350   uint64_t enc_key_id_length_;
    351 
    352   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
    353 };
    354 
    355 ///////////////////////////////////////////////////////////////
    356 // Colour element.
    357 class PrimaryChromaticity {
    358  public:
    359   static const float kChromaticityMin;
    360   static const float kChromaticityMax;
    361 
    362   PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {}
    363   PrimaryChromaticity() : x_(0), y_(0) {}
    364   ~PrimaryChromaticity() {}
    365 
    366   // Returns sum of |x_id| and |y_id| element id sizes and payload sizes.
    367   uint64_t PrimaryChromaticitySize(libwebm::MkvId x_id,
    368                                    libwebm::MkvId y_id) const;
    369   bool Valid() const;
    370   bool Write(IMkvWriter* writer, libwebm::MkvId x_id,
    371              libwebm::MkvId y_id) const;
    372 
    373   float x() const { return x_; }
    374   void set_x(float new_x) { x_ = new_x; }
    375   float y() const { return y_; }
    376   void set_y(float new_y) { y_ = new_y; }
    377 
    378  private:
    379   float x_;
    380   float y_;
    381 };
    382 
    383 class MasteringMetadata {
    384  public:
    385   static const float kValueNotPresent;
    386   static const float kMinLuminance;
    387   static const float kMinLuminanceMax;
    388   static const float kMaxLuminanceMax;
    389 
    390   MasteringMetadata()
    391       : luminance_max_(kValueNotPresent),
    392         luminance_min_(kValueNotPresent),
    393         r_(NULL),
    394         g_(NULL),
    395         b_(NULL),
    396         white_point_(NULL) {}
    397   ~MasteringMetadata() {
    398     delete r_;
    399     delete g_;
    400     delete b_;
    401     delete white_point_;
    402   }
    403 
    404   // Returns total size of the MasteringMetadata element.
    405   uint64_t MasteringMetadataSize() const;
    406   bool Valid() const;
    407   bool Write(IMkvWriter* writer) const;
    408 
    409   // Copies non-null chromaticity.
    410   bool SetChromaticity(const PrimaryChromaticity* r,
    411                        const PrimaryChromaticity* g,
    412                        const PrimaryChromaticity* b,
    413                        const PrimaryChromaticity* white_point);
    414   const PrimaryChromaticity* r() const { return r_; }
    415   const PrimaryChromaticity* g() const { return g_; }
    416   const PrimaryChromaticity* b() const { return b_; }
    417   const PrimaryChromaticity* white_point() const { return white_point_; }
    418 
    419   float luminance_max() const { return luminance_max_; }
    420   void set_luminance_max(float luminance_max) {
    421     luminance_max_ = luminance_max;
    422   }
    423   float luminance_min() const { return luminance_min_; }
    424   void set_luminance_min(float luminance_min) {
    425     luminance_min_ = luminance_min;
    426   }
    427 
    428  private:
    429   // Returns size of MasteringMetadata child elements.
    430   uint64_t PayloadSize() const;
    431 
    432   float luminance_max_;
    433   float luminance_min_;
    434   PrimaryChromaticity* r_;
    435   PrimaryChromaticity* g_;
    436   PrimaryChromaticity* b_;
    437   PrimaryChromaticity* white_point_;
    438 };
    439 
    440 class Colour {
    441  public:
    442   enum MatrixCoefficients {
    443     kGbr = 0,
    444     kBt709 = 1,
    445     kUnspecifiedMc = 2,
    446     kReserved = 3,
    447     kFcc = 4,
    448     kBt470bg = 5,
    449     kSmpte170MMc = 6,
    450     kSmpte240MMc = 7,
    451     kYcocg = 8,
    452     kBt2020NonConstantLuminance = 9,
    453     kBt2020ConstantLuminance = 10,
    454   };
    455   enum ChromaSitingHorz {
    456     kUnspecifiedCsh = 0,
    457     kLeftCollocated = 1,
    458     kHalfCsh = 2,
    459   };
    460   enum ChromaSitingVert {
    461     kUnspecifiedCsv = 0,
    462     kTopCollocated = 1,
    463     kHalfCsv = 2,
    464   };
    465   enum Range {
    466     kUnspecifiedCr = 0,
    467     kBroadcastRange = 1,
    468     kFullRange = 2,
    469     kMcTcDefined = 3,  // Defined by MatrixCoefficients/TransferCharacteristics.
    470   };
    471   enum TransferCharacteristics {
    472     kIturBt709Tc = 1,
    473     kUnspecifiedTc = 2,
    474     kReservedTc = 3,
    475     kGamma22Curve = 4,
    476     kGamma28Curve = 5,
    477     kSmpte170MTc = 6,
    478     kSmpte240MTc = 7,
    479     kLinear = 8,
    480     kLog = 9,
    481     kLogSqrt = 10,
    482     kIec6196624 = 11,
    483     kIturBt1361ExtendedColourGamut = 12,
    484     kIec6196621 = 13,
    485     kIturBt202010bit = 14,
    486     kIturBt202012bit = 15,
    487     kSmpteSt2084 = 16,
    488     kSmpteSt4281Tc = 17,
    489     kAribStdB67Hlg = 18,
    490   };
    491   enum Primaries {
    492     kReservedP0 = 0,
    493     kIturBt709P = 1,
    494     kUnspecifiedP = 2,
    495     kReservedP3 = 3,
    496     kIturBt470M = 4,
    497     kIturBt470Bg = 5,
    498     kSmpte170MP = 6,
    499     kSmpte240MP = 7,
    500     kFilm = 8,
    501     kIturBt2020 = 9,
    502     kSmpteSt4281P = 10,
    503     kJedecP22Phosphors = 22,
    504   };
    505   static const uint64_t kValueNotPresent;
    506   Colour()
    507       : matrix_coefficients_(kValueNotPresent),
    508         bits_per_channel_(kValueNotPresent),
    509         chroma_subsampling_horz_(kValueNotPresent),
    510         chroma_subsampling_vert_(kValueNotPresent),
    511         cb_subsampling_horz_(kValueNotPresent),
    512         cb_subsampling_vert_(kValueNotPresent),
    513         chroma_siting_horz_(kValueNotPresent),
    514         chroma_siting_vert_(kValueNotPresent),
    515         range_(kValueNotPresent),
    516         transfer_characteristics_(kValueNotPresent),
    517         primaries_(kValueNotPresent),
    518         max_cll_(kValueNotPresent),
    519         max_fall_(kValueNotPresent),
    520         mastering_metadata_(NULL) {}
    521   ~Colour() { delete mastering_metadata_; }
    522 
    523   // Returns total size of the Colour element.
    524   uint64_t ColourSize() const;
    525   bool Valid() const;
    526   bool Write(IMkvWriter* writer) const;
    527 
    528   // Deep copies |mastering_metadata|.
    529   bool SetMasteringMetadata(const MasteringMetadata& mastering_metadata);
    530 
    531   const MasteringMetadata* mastering_metadata() const {
    532     return mastering_metadata_;
    533   }
    534 
    535   uint64_t matrix_coefficients() const { return matrix_coefficients_; }
    536   void set_matrix_coefficients(uint64_t matrix_coefficients) {
    537     matrix_coefficients_ = matrix_coefficients;
    538   }
    539   uint64_t bits_per_channel() const { return bits_per_channel_; }
    540   void set_bits_per_channel(uint64_t bits_per_channel) {
    541     bits_per_channel_ = bits_per_channel;
    542   }
    543   uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; }
    544   void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) {
    545     chroma_subsampling_horz_ = chroma_subsampling_horz;
    546   }
    547   uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; }
    548   void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) {
    549     chroma_subsampling_vert_ = chroma_subsampling_vert;
    550   }
    551   uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; }
    552   void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) {
    553     cb_subsampling_horz_ = cb_subsampling_horz;
    554   }
    555   uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; }
    556   void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) {
    557     cb_subsampling_vert_ = cb_subsampling_vert;
    558   }
    559   uint64_t chroma_siting_horz() const { return chroma_siting_horz_; }
    560   void set_chroma_siting_horz(uint64_t chroma_siting_horz) {
    561     chroma_siting_horz_ = chroma_siting_horz;
    562   }
    563   uint64_t chroma_siting_vert() const { return chroma_siting_vert_; }
    564   void set_chroma_siting_vert(uint64_t chroma_siting_vert) {
    565     chroma_siting_vert_ = chroma_siting_vert;
    566   }
    567   uint64_t range() const { return range_; }
    568   void set_range(uint64_t range) { range_ = range; }
    569   uint64_t transfer_characteristics() const {
    570     return transfer_characteristics_;
    571   }
    572   void set_transfer_characteristics(uint64_t transfer_characteristics) {
    573     transfer_characteristics_ = transfer_characteristics;
    574   }
    575   uint64_t primaries() const { return primaries_; }
    576   void set_primaries(uint64_t primaries) { primaries_ = primaries; }
    577   uint64_t max_cll() const { return max_cll_; }
    578   void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; }
    579   uint64_t max_fall() const { return max_fall_; }
    580   void set_max_fall(uint64_t max_fall) { max_fall_ = max_fall; }
    581 
    582  private:
    583   // Returns size of Colour child elements.
    584   uint64_t PayloadSize() const;
    585 
    586   uint64_t matrix_coefficients_;
    587   uint64_t bits_per_channel_;
    588   uint64_t chroma_subsampling_horz_;
    589   uint64_t chroma_subsampling_vert_;
    590   uint64_t cb_subsampling_horz_;
    591   uint64_t cb_subsampling_vert_;
    592   uint64_t chroma_siting_horz_;
    593   uint64_t chroma_siting_vert_;
    594   uint64_t range_;
    595   uint64_t transfer_characteristics_;
    596   uint64_t primaries_;
    597   uint64_t max_cll_;
    598   uint64_t max_fall_;
    599 
    600   MasteringMetadata* mastering_metadata_;
    601 };
    602 
    603 ///////////////////////////////////////////////////////////////
    604 // Projection element.
    605 class Projection {
    606  public:
    607   enum ProjectionType {
    608     kTypeNotPresent = -1,
    609     kRectangular = 0,
    610     kEquirectangular = 1,
    611     kCubeMap = 2,
    612     kMesh = 3,
    613   };
    614   static const uint64_t kValueNotPresent;
    615   Projection()
    616       : type_(kRectangular),
    617         pose_yaw_(0.0),
    618         pose_pitch_(0.0),
    619         pose_roll_(0.0),
    620         private_data_(NULL),
    621         private_data_length_(0) {}
    622   ~Projection() { delete[] private_data_; }
    623 
    624   uint64_t ProjectionSize() const;
    625   bool Write(IMkvWriter* writer) const;
    626 
    627   bool SetProjectionPrivate(const uint8_t* private_data,
    628                             uint64_t private_data_length);
    629 
    630   ProjectionType type() const { return type_; }
    631   void set_type(ProjectionType type) { type_ = type; }
    632   float pose_yaw() const { return pose_yaw_; }
    633   void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; }
    634   float pose_pitch() const { return pose_pitch_; }
    635   void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; }
    636   float pose_roll() const { return pose_roll_; }
    637   void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; }
    638   uint8_t* private_data() const { return private_data_; }
    639   uint64_t private_data_length() const { return private_data_length_; }
    640 
    641  private:
    642   // Returns size of VideoProjection child elements.
    643   uint64_t PayloadSize() const;
    644 
    645   ProjectionType type_;
    646   float pose_yaw_;
    647   float pose_pitch_;
    648   float pose_roll_;
    649   uint8_t* private_data_;
    650   uint64_t private_data_length_;
    651 };
    652 
    653 ///////////////////////////////////////////////////////////////
    654 // Track element.
    655 class Track {
    656  public:
    657   // The |seed| parameter is used to synthesize a UID for the track.
    658   explicit Track(unsigned int* seed);
    659   virtual ~Track();
    660 
    661   // Adds a ContentEncoding element to the Track. Returns true on success.
    662   virtual bool AddContentEncoding();
    663 
    664   // Returns the ContentEncoding by index. Returns NULL if there is no
    665   // ContentEncoding match.
    666   ContentEncoding* GetContentEncodingByIndex(uint32_t index) const;
    667 
    668   // Returns the size in bytes for the payload of the Track element.
    669   virtual uint64_t PayloadSize() const;
    670 
    671   // Returns the size in bytes of the Track element.
    672   virtual uint64_t Size() const;
    673 
    674   // Output the Track element to the writer. Returns true on success.
    675   virtual bool Write(IMkvWriter* writer) const;
    676 
    677   // Sets the CodecPrivate element of the Track element. Copies |length|
    678   // bytes from |codec_private| to |codec_private_|. Returns true on success.
    679   bool SetCodecPrivate(const uint8_t* codec_private, uint64_t length);
    680 
    681   void set_codec_id(const char* codec_id);
    682   const char* codec_id() const { return codec_id_; }
    683   const uint8_t* codec_private() const { return codec_private_; }
    684   void set_language(const char* language);
    685   const char* language() const { return language_; }
    686   void set_max_block_additional_id(uint64_t max_block_additional_id) {
    687     max_block_additional_id_ = max_block_additional_id;
    688   }
    689   uint64_t max_block_additional_id() const { return max_block_additional_id_; }
    690   void set_name(const char* name);
    691   const char* name() const { return name_; }
    692   void set_number(uint64_t number) { number_ = number; }
    693   uint64_t number() const { return number_; }
    694   void set_type(uint64_t type) { type_ = type; }
    695   uint64_t type() const { return type_; }
    696   void set_uid(uint64_t uid) { uid_ = uid; }
    697   uint64_t uid() const { return uid_; }
    698   void set_codec_delay(uint64_t codec_delay) { codec_delay_ = codec_delay; }
    699   uint64_t codec_delay() const { return codec_delay_; }
    700   void set_seek_pre_roll(uint64_t seek_pre_roll) {
    701     seek_pre_roll_ = seek_pre_roll;
    702   }
    703   uint64_t seek_pre_roll() const { return seek_pre_roll_; }
    704   void set_default_duration(uint64_t default_duration) {
    705     default_duration_ = default_duration;
    706   }
    707   uint64_t default_duration() const { return default_duration_; }
    708 
    709   uint64_t codec_private_length() const { return codec_private_length_; }
    710   uint32_t content_encoding_entries_size() const {
    711     return content_encoding_entries_size_;
    712   }
    713 
    714  private:
    715   // Track element names.
    716   char* codec_id_;
    717   uint8_t* codec_private_;
    718   char* language_;
    719   uint64_t max_block_additional_id_;
    720   char* name_;
    721   uint64_t number_;
    722   uint64_t type_;
    723   uint64_t uid_;
    724   uint64_t codec_delay_;
    725   uint64_t seek_pre_roll_;
    726   uint64_t default_duration_;
    727 
    728   // Size of the CodecPrivate data in bytes.
    729   uint64_t codec_private_length_;
    730 
    731   // ContentEncoding element list.
    732   ContentEncoding** content_encoding_entries_;
    733 
    734   // Number of ContentEncoding elements added.
    735   uint32_t content_encoding_entries_size_;
    736 
    737   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track);
    738 };
    739 
    740 ///////////////////////////////////////////////////////////////
    741 // Track that has video specific elements.
    742 class VideoTrack : public Track {
    743  public:
    744   // Supported modes for stereo 3D.
    745   enum StereoMode {
    746     kMono = 0,
    747     kSideBySideLeftIsFirst = 1,
    748     kTopBottomRightIsFirst = 2,
    749     kTopBottomLeftIsFirst = 3,
    750     kSideBySideRightIsFirst = 11
    751   };
    752 
    753   enum AlphaMode { kNoAlpha = 0, kAlpha = 1 };
    754 
    755   // The |seed| parameter is used to synthesize a UID for the track.
    756   explicit VideoTrack(unsigned int* seed);
    757   virtual ~VideoTrack();
    758 
    759   // Returns the size in bytes for the payload of the Track element plus the
    760   // video specific elements.
    761   virtual uint64_t PayloadSize() const;
    762 
    763   // Output the VideoTrack element to the writer. Returns true on success.
    764   virtual bool Write(IMkvWriter* writer) const;
    765 
    766   // Sets the video's stereo mode. Returns true on success.
    767   bool SetStereoMode(uint64_t stereo_mode);
    768 
    769   // Sets the video's alpha mode. Returns true on success.
    770   bool SetAlphaMode(uint64_t alpha_mode);
    771 
    772   void set_display_height(uint64_t height) { display_height_ = height; }
    773   uint64_t display_height() const { return display_height_; }
    774   void set_display_width(uint64_t width) { display_width_ = width; }
    775   uint64_t display_width() const { return display_width_; }
    776   void set_pixel_height(uint64_t height) { pixel_height_ = height; }
    777   uint64_t pixel_height() const { return pixel_height_; }
    778   void set_pixel_width(uint64_t width) { pixel_width_ = width; }
    779   uint64_t pixel_width() const { return pixel_width_; }
    780 
    781   void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; }
    782   uint64_t crop_left() const { return crop_left_; }
    783   void set_crop_right(uint64_t crop_right) { crop_right_ = crop_right; }
    784   uint64_t crop_right() const { return crop_right_; }
    785   void set_crop_top(uint64_t crop_top) { crop_top_ = crop_top; }
    786   uint64_t crop_top() const { return crop_top_; }
    787   void set_crop_bottom(uint64_t crop_bottom) { crop_bottom_ = crop_bottom; }
    788   uint64_t crop_bottom() const { return crop_bottom_; }
    789 
    790   void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
    791   double frame_rate() const { return frame_rate_; }
    792   void set_height(uint64_t height) { height_ = height; }
    793   uint64_t height() const { return height_; }
    794   uint64_t stereo_mode() { return stereo_mode_; }
    795   uint64_t alpha_mode() { return alpha_mode_; }
    796   void set_width(uint64_t width) { width_ = width; }
    797   uint64_t width() const { return width_; }
    798 
    799   Colour* colour() { return colour_; }
    800 
    801   // Deep copies |colour|.
    802   bool SetColour(const Colour& colour);
    803 
    804   Projection* projection() { return projection_; }
    805 
    806   // Deep copies |projection|.
    807   bool SetProjection(const Projection& projection);
    808 
    809  private:
    810   // Returns the size in bytes of the Video element.
    811   uint64_t VideoPayloadSize() const;
    812 
    813   // Video track element names.
    814   uint64_t display_height_;
    815   uint64_t display_width_;
    816   uint64_t pixel_height_;
    817   uint64_t pixel_width_;
    818   uint64_t crop_left_;
    819   uint64_t crop_right_;
    820   uint64_t crop_top_;
    821   uint64_t crop_bottom_;
    822   double frame_rate_;
    823   uint64_t height_;
    824   uint64_t stereo_mode_;
    825   uint64_t alpha_mode_;
    826   uint64_t width_;
    827 
    828   Colour* colour_;
    829   Projection* projection_;
    830 
    831   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
    832 };
    833 
    834 ///////////////////////////////////////////////////////////////
    835 // Track that has audio specific elements.
    836 class AudioTrack : public Track {
    837  public:
    838   // The |seed| parameter is used to synthesize a UID for the track.
    839   explicit AudioTrack(unsigned int* seed);
    840   virtual ~AudioTrack();
    841 
    842   // Returns the size in bytes for the payload of the Track element plus the
    843   // audio specific elements.
    844   virtual uint64_t PayloadSize() const;
    845 
    846   // Output the AudioTrack element to the writer. Returns true on success.
    847   virtual bool Write(IMkvWriter* writer) const;
    848 
    849   void set_bit_depth(uint64_t bit_depth) { bit_depth_ = bit_depth; }
    850   uint64_t bit_depth() const { return bit_depth_; }
    851   void set_channels(uint64_t channels) { channels_ = channels; }
    852   uint64_t channels() const { return channels_; }
    853   void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; }
    854   double sample_rate() const { return sample_rate_; }
    855 
    856  private:
    857   // Audio track element names.
    858   uint64_t bit_depth_;
    859   uint64_t channels_;
    860   double sample_rate_;
    861 
    862   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack);
    863 };
    864 
    865 ///////////////////////////////////////////////////////////////
    866 // Tracks element
    867 class Tracks {
    868  public:
    869   // Audio and video type defined by the Matroska specs.
    870   enum { kVideo = 0x1, kAudio = 0x2 };
    871 
    872   static const char kOpusCodecId[];
    873   static const char kVorbisCodecId[];
    874   static const char kVp8CodecId[];
    875   static const char kVp9CodecId[];
    876   static const char kVp10CodecId[];
    877   static const char kWebVttCaptionsId[];
    878   static const char kWebVttDescriptionsId[];
    879   static const char kWebVttMetadataId[];
    880   static const char kWebVttSubtitlesId[];
    881 
    882   Tracks();
    883   ~Tracks();
    884 
    885   // Adds a Track element to the Tracks object. |track| will be owned and
    886   // deleted by the Tracks object. Returns true on success. |number| is the
    887   // number to use for the track. |number| must be >= 0. If |number| == 0
    888   // then the muxer will decide on the track number.
    889   bool AddTrack(Track* track, int32_t number);
    890 
    891   // Returns the track by index. Returns NULL if there is no track match.
    892   const Track* GetTrackByIndex(uint32_t idx) const;
    893 
    894   // Search the Tracks and return the track that matches |tn|. Returns NULL
    895   // if there is no track match.
    896   Track* GetTrackByNumber(uint64_t track_number) const;
    897 
    898   // Returns true if the track number is an audio track.
    899   bool TrackIsAudio(uint64_t track_number) const;
    900 
    901   // Returns true if the track number is a video track.
    902   bool TrackIsVideo(uint64_t track_number) const;
    903 
    904   // Output the Tracks element to the writer. Returns true on success.
    905   bool Write(IMkvWriter* writer) const;
    906 
    907   uint32_t track_entries_size() const { return track_entries_size_; }
    908 
    909  private:
    910   // Track element list.
    911   Track** track_entries_;
    912 
    913   // Number of Track elements added.
    914   uint32_t track_entries_size_;
    915 
    916   // Whether or not Tracks element has already been written via IMkvWriter.
    917   mutable bool wrote_tracks_;
    918 
    919   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
    920 };
    921 
    922 ///////////////////////////////////////////////////////////////
    923 // Chapter element
    924 //
    925 class Chapter {
    926  public:
    927   // Set the identifier for this chapter.  (This corresponds to the
    928   // Cue Identifier line in WebVTT.)
    929   // TODO(matthewjheaney): the actual serialization of this item in
    930   // MKV is pending.
    931   bool set_id(const char* id);
    932 
    933   // Converts the nanosecond start and stop times of this chapter to
    934   // their corresponding timecode values, and stores them that way.
    935   void set_time(const Segment& segment, uint64_t start_time_ns,
    936                 uint64_t end_time_ns);
    937 
    938   // Sets the uid for this chapter. Primarily used to enable
    939   // deterministic output from the muxer.
    940   void set_uid(const uint64_t uid) { uid_ = uid; }
    941 
    942   // Add a title string to this chapter, per the semantics described
    943   // here:
    944   //  http://www.matroska.org/technical/specs/index.html
    945   //
    946   // The title ("chapter string") is a UTF-8 string.
    947   //
    948   // The language has ISO 639-2 representation, described here:
    949   //  http://www.loc.gov/standards/iso639-2/englangn.html
    950   //  http://www.loc.gov/standards/iso639-2/php/English_list.php
    951   // If you specify NULL as the language value, this implies
    952   // English ("eng").
    953   //
    954   // The country value corresponds to the codes listed here:
    955   //  http://www.iana.org/domains/root/db/
    956   //
    957   // The function returns false if the string could not be allocated.
    958   bool add_string(const char* title, const char* language, const char* country);
    959 
    960  private:
    961   friend class Chapters;
    962 
    963   // For storage of chapter titles that differ by language.
    964   class Display {
    965    public:
    966     // Establish representation invariant for new Display object.
    967     void Init();
    968 
    969     // Reclaim resources, in anticipation of destruction.
    970     void Clear();
    971 
    972     // Copies the title to the |title_| member.  Returns false on
    973     // error.
    974     bool set_title(const char* title);
    975 
    976     // Copies the language to the |language_| member.  Returns false
    977     // on error.
    978     bool set_language(const char* language);
    979 
    980     // Copies the country to the |country_| member.  Returns false on
    981     // error.
    982     bool set_country(const char* country);
    983 
    984     // If |writer| is non-NULL, serialize the Display sub-element of
    985     // the Atom into the stream.  Returns the Display element size on
    986     // success, 0 if error.
    987     uint64_t WriteDisplay(IMkvWriter* writer) const;
    988 
    989    private:
    990     char* title_;
    991     char* language_;
    992     char* country_;
    993   };
    994 
    995   Chapter();
    996   ~Chapter();
    997 
    998   // Establish the representation invariant for a newly-created
    999   // Chapter object.  The |seed| parameter is used to create the UID
   1000   // for this chapter atom.
   1001   void Init(unsigned int* seed);
   1002 
   1003   // Copies this Chapter object to a different one.  This is used when
   1004   // expanding a plain array of Chapter objects (see Chapters).
   1005   void ShallowCopy(Chapter* dst) const;
   1006 
   1007   // Reclaim resources used by this Chapter object, pending its
   1008   // destruction.
   1009   void Clear();
   1010 
   1011   // If there is no storage remaining on the |displays_| array for a
   1012   // new display object, creates a new, longer array and copies the
   1013   // existing Display objects to the new array.  Returns false if the
   1014   // array cannot be expanded.
   1015   bool ExpandDisplaysArray();
   1016 
   1017   // If |writer| is non-NULL, serialize the Atom sub-element into the
   1018   // stream.  Returns the total size of the element on success, 0 if
   1019   // error.
   1020   uint64_t WriteAtom(IMkvWriter* writer) const;
   1021 
   1022   // The string identifier for this chapter (corresponds to WebVTT cue
   1023   // identifier).
   1024   char* id_;
   1025 
   1026   // Start timecode of the chapter.
   1027   uint64_t start_timecode_;
   1028 
   1029   // Stop timecode of the chapter.
   1030   uint64_t end_timecode_;
   1031 
   1032   // The binary identifier for this chapter.
   1033   uint64_t uid_;
   1034 
   1035   // The Atom element can contain multiple Display sub-elements, as
   1036   // the same logical title can be rendered in different languages.
   1037   Display* displays_;
   1038 
   1039   // The physical length (total size) of the |displays_| array.
   1040   int displays_size_;
   1041 
   1042   // The logical length (number of active elements) on the |displays_|
   1043   // array.
   1044   int displays_count_;
   1045 
   1046   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter);
   1047 };
   1048 
   1049 ///////////////////////////////////////////////////////////////
   1050 // Chapters element
   1051 //
   1052 class Chapters {
   1053  public:
   1054   Chapters();
   1055   ~Chapters();
   1056 
   1057   Chapter* AddChapter(unsigned int* seed);
   1058 
   1059   // Returns the number of chapters that have been added.
   1060   int Count() const;
   1061 
   1062   // Output the Chapters element to the writer. Returns true on success.
   1063   bool Write(IMkvWriter* writer) const;
   1064 
   1065  private:
   1066   // Expands the chapters_ array if there is not enough space to contain
   1067   // another chapter object.  Returns true on success.
   1068   bool ExpandChaptersArray();
   1069 
   1070   // If |writer| is non-NULL, serialize the Edition sub-element of the
   1071   // Chapters element into the stream.  Returns the Edition element
   1072   // size on success, 0 if error.
   1073   uint64_t WriteEdition(IMkvWriter* writer) const;
   1074 
   1075   // Total length of the chapters_ array.
   1076   int chapters_size_;
   1077 
   1078   // Number of active chapters on the chapters_ array.
   1079   int chapters_count_;
   1080 
   1081   // Array for storage of chapter objects.
   1082   Chapter* chapters_;
   1083 
   1084   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters);
   1085 };
   1086 
   1087 ///////////////////////////////////////////////////////////////
   1088 // Tag element
   1089 //
   1090 class Tag {
   1091  public:
   1092   bool add_simple_tag(const char* tag_name, const char* tag_string);
   1093 
   1094  private:
   1095   // Tags calls Clear and the destructor of Tag
   1096   friend class Tags;
   1097 
   1098   // For storage of simple tags
   1099   class SimpleTag {
   1100    public:
   1101     // Establish representation invariant for new SimpleTag object.
   1102     void Init();
   1103 
   1104     // Reclaim resources, in anticipation of destruction.
   1105     void Clear();
   1106 
   1107     // Copies the title to the |tag_name_| member.  Returns false on
   1108     // error.
   1109     bool set_tag_name(const char* tag_name);
   1110 
   1111     // Copies the language to the |tag_string_| member.  Returns false
   1112     // on error.
   1113     bool set_tag_string(const char* tag_string);
   1114 
   1115     // If |writer| is non-NULL, serialize the SimpleTag sub-element of
   1116     // the Atom into the stream.  Returns the SimpleTag element size on
   1117     // success, 0 if error.
   1118     uint64_t Write(IMkvWriter* writer) const;
   1119 
   1120    private:
   1121     char* tag_name_;
   1122     char* tag_string_;
   1123   };
   1124 
   1125   Tag();
   1126   ~Tag();
   1127 
   1128   // Copies this Tag object to a different one.  This is used when
   1129   // expanding a plain array of Tag objects (see Tags).
   1130   void ShallowCopy(Tag* dst) const;
   1131 
   1132   // Reclaim resources used by this Tag object, pending its
   1133   // destruction.
   1134   void Clear();
   1135 
   1136   // If there is no storage remaining on the |simple_tags_| array for a
   1137   // new display object, creates a new, longer array and copies the
   1138   // existing SimpleTag objects to the new array.  Returns false if the
   1139   // array cannot be expanded.
   1140   bool ExpandSimpleTagsArray();
   1141 
   1142   // If |writer| is non-NULL, serialize the Tag sub-element into the
   1143   // stream.  Returns the total size of the element on success, 0 if
   1144   // error.
   1145   uint64_t Write(IMkvWriter* writer) const;
   1146 
   1147   // The Atom element can contain multiple SimpleTag sub-elements
   1148   SimpleTag* simple_tags_;
   1149 
   1150   // The physical length (total size) of the |simple_tags_| array.
   1151   int simple_tags_size_;
   1152 
   1153   // The logical length (number of active elements) on the |simple_tags_|
   1154   // array.
   1155   int simple_tags_count_;
   1156 
   1157   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag);
   1158 };
   1159 
   1160 ///////////////////////////////////////////////////////////////
   1161 // Tags element
   1162 //
   1163 class Tags {
   1164  public:
   1165   Tags();
   1166   ~Tags();
   1167 
   1168   Tag* AddTag();
   1169 
   1170   // Returns the number of tags that have been added.
   1171   int Count() const;
   1172 
   1173   // Output the Tags element to the writer. Returns true on success.
   1174   bool Write(IMkvWriter* writer) const;
   1175 
   1176  private:
   1177   // Expands the tags_ array if there is not enough space to contain
   1178   // another tag object.  Returns true on success.
   1179   bool ExpandTagsArray();
   1180 
   1181   // Total length of the tags_ array.
   1182   int tags_size_;
   1183 
   1184   // Number of active tags on the tags_ array.
   1185   int tags_count_;
   1186 
   1187   // Array for storage of tag objects.
   1188   Tag* tags_;
   1189 
   1190   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags);
   1191 };
   1192 
   1193 ///////////////////////////////////////////////////////////////
   1194 // Cluster element
   1195 //
   1196 // Notes:
   1197 //  |Init| must be called before any other method in this class.
   1198 class Cluster {
   1199  public:
   1200   // |timecode| is the absolute timecode of the cluster. |cues_pos| is the
   1201   // position for the cluster within the segment that should be written in
   1202   // the cues element. |timecode_scale| is the timecode scale of the segment.
   1203   Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
   1204           bool write_last_frame_with_duration = false,
   1205           bool fixed_size_timecode = false);
   1206   ~Cluster();
   1207 
   1208   bool Init(IMkvWriter* ptr_writer);
   1209 
   1210   // Adds a frame to be output in the file. The frame is written out through
   1211   // |writer_| if successful. Returns true on success.
   1212   bool AddFrame(const Frame* frame);
   1213 
   1214   // Adds a frame to be output in the file. The frame is written out through
   1215   // |writer_| if successful. Returns true on success.
   1216   // Inputs:
   1217   //   data: Pointer to the data
   1218   //   length: Length of the data
   1219   //   track_number: Track to add the data to. Value returned by Add track
   1220   //                 functions.  The range of allowed values is [1, 126].
   1221   //   timecode:     Absolute (not relative to cluster) timestamp of the
   1222   //                 frame, expressed in timecode units.
   1223   //   is_key:       Flag telling whether or not this frame is a key frame.
   1224   bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number,
   1225                 uint64_t timecode,  // timecode units (absolute)
   1226                 bool is_key);
   1227 
   1228   // Adds a frame to be output in the file. The frame is written out through
   1229   // |writer_| if successful. Returns true on success.
   1230   // Inputs:
   1231   //   data: Pointer to the data
   1232   //   length: Length of the data
   1233   //   additional: Pointer to the additional data
   1234   //   additional_length: Length of the additional data
   1235   //   add_id: Value of BlockAddID element
   1236   //   track_number: Track to add the data to. Value returned by Add track
   1237   //                 functions.  The range of allowed values is [1, 126].
   1238   //   abs_timecode: Absolute (not relative to cluster) timestamp of the
   1239   //                 frame, expressed in timecode units.
   1240   //   is_key:       Flag telling whether or not this frame is a key frame.
   1241   bool AddFrameWithAdditional(const uint8_t* data, uint64_t length,
   1242                               const uint8_t* additional,
   1243                               uint64_t additional_length, uint64_t add_id,
   1244                               uint64_t track_number, uint64_t abs_timecode,
   1245                               bool is_key);
   1246 
   1247   // Adds a frame to be output in the file. The frame is written out through
   1248   // |writer_| if successful. Returns true on success.
   1249   // Inputs:
   1250   //   data: Pointer to the data.
   1251   //   length: Length of the data.
   1252   //   discard_padding: DiscardPadding element value.
   1253   //   track_number: Track to add the data to. Value returned by Add track
   1254   //                 functions.  The range of allowed values is [1, 126].
   1255   //   abs_timecode: Absolute (not relative to cluster) timestamp of the
   1256   //                 frame, expressed in timecode units.
   1257   //   is_key:       Flag telling whether or not this frame is a key frame.
   1258   bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
   1259                                   int64_t discard_padding,
   1260                                   uint64_t track_number, uint64_t abs_timecode,
   1261                                   bool is_key);
   1262 
   1263   // Writes a frame of metadata to the output medium; returns true on
   1264   // success.
   1265   // Inputs:
   1266   //   data: Pointer to the data
   1267   //   length: Length of the data
   1268   //   track_number: Track to add the data to. Value returned by Add track
   1269   //                 functions.  The range of allowed values is [1, 126].
   1270   //   timecode:     Absolute (not relative to cluster) timestamp of the
   1271   //                 metadata frame, expressed in timecode units.
   1272   //   duration:     Duration of metadata frame, in timecode units.
   1273   //
   1274   // The metadata frame is written as a block group, with a duration
   1275   // sub-element but no reference time sub-elements (indicating that
   1276   // it is considered a keyframe, per Matroska semantics).
   1277   bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number,
   1278                    uint64_t timecode, uint64_t duration);
   1279 
   1280   // Increments the size of the cluster's data in bytes.
   1281   void AddPayloadSize(uint64_t size);
   1282 
   1283   // Closes the cluster so no more data can be written to it. Will update the
   1284   // cluster's size if |writer_| is seekable. Returns true on success. This
   1285   // variant of Finalize() fails when |write_last_frame_with_duration_| is set
   1286   // to true.
   1287   bool Finalize();
   1288 
   1289   // Closes the cluster so no more data can be written to it. Will update the
   1290   // cluster's size if |writer_| is seekable. Returns true on success.
   1291   // Inputs:
   1292   //   set_last_frame_duration: Boolean indicating whether or not the duration
   1293   //                            of the last frame should be set. If set to
   1294   //                            false, the |duration| value is ignored and
   1295   //                            |write_last_frame_with_duration_| will not be
   1296   //                            honored.
   1297   //   duration: Duration of the Cluster in timecode scale.
   1298   bool Finalize(bool set_last_frame_duration, uint64_t duration);
   1299 
   1300   // Returns the size in bytes for the entire Cluster element.
   1301   uint64_t Size() const;
   1302 
   1303   // Given |abs_timecode|, calculates timecode relative to most recent timecode.
   1304   // Returns -1 on failure, or a relative timecode.
   1305   int64_t GetRelativeTimecode(int64_t abs_timecode) const;
   1306 
   1307   int64_t size_position() const { return size_position_; }
   1308   int32_t blocks_added() const { return blocks_added_; }
   1309   uint64_t payload_size() const { return payload_size_; }
   1310   int64_t position_for_cues() const { return position_for_cues_; }
   1311   uint64_t timecode() const { return timecode_; }
   1312   uint64_t timecode_scale() const { return timecode_scale_; }
   1313   void set_write_last_frame_with_duration(bool write_last_frame_with_duration) {
   1314     write_last_frame_with_duration_ = write_last_frame_with_duration;
   1315   }
   1316   bool write_last_frame_with_duration() const {
   1317     return write_last_frame_with_duration_;
   1318   }
   1319 
   1320  private:
   1321   // Iterator type for the |stored_frames_| map.
   1322   typedef std::map<uint64_t, std::list<Frame*> >::iterator FrameMapIterator;
   1323 
   1324   // Utility method that confirms that blocks can still be added, and that the
   1325   // cluster header has been written. Used by |DoWriteFrame*|. Returns true
   1326   // when successful.
   1327   bool PreWriteBlock();
   1328 
   1329   // Utility method used by the |DoWriteFrame*| methods that handles the book
   1330   // keeping required after each block is written.
   1331   void PostWriteBlock(uint64_t element_size);
   1332 
   1333   // Does some verification and calls WriteFrame.
   1334   bool DoWriteFrame(const Frame* const frame);
   1335 
   1336   // Either holds back the given frame, or writes it out depending on whether or
   1337   // not |write_last_frame_with_duration_| is set.
   1338   bool QueueOrWriteFrame(const Frame* const frame);
   1339 
   1340   // Outputs the Cluster header to |writer_|. Returns true on success.
   1341   bool WriteClusterHeader();
   1342 
   1343   // Number of blocks added to the cluster.
   1344   int32_t blocks_added_;
   1345 
   1346   // Flag telling if the cluster has been closed.
   1347   bool finalized_;
   1348 
   1349   // Flag indicating whether the cluster's timecode will always be written out
   1350   // using 8 bytes.
   1351   bool fixed_size_timecode_;
   1352 
   1353   // Flag telling if the cluster's header has been written.
   1354   bool header_written_;
   1355 
   1356   // The size of the cluster elements in bytes.
   1357   uint64_t payload_size_;
   1358 
   1359   // The file position used for cue points.
   1360   const int64_t position_for_cues_;
   1361 
   1362   // The file position of the cluster's size element.
   1363   int64_t size_position_;
   1364 
   1365   // The absolute timecode of the cluster.
   1366   const uint64_t timecode_;
   1367 
   1368   // The timecode scale of the Segment containing the cluster.
   1369   const uint64_t timecode_scale_;
   1370 
   1371   // Flag indicating whether the last frame of the cluster should be written as
   1372   // a Block with Duration. If set to true, then it will result in holding back
   1373   // of frames and the parameterized version of Finalize() must be called to
   1374   // finish writing the Cluster.
   1375   bool write_last_frame_with_duration_;
   1376 
   1377   // Map used to hold back frames, if required. Track number is the key.
   1378   std::map<uint64_t, std::list<Frame*> > stored_frames_;
   1379 
   1380   // Map from track number to the timestamp of the last block written for that
   1381   // track.
   1382   std::map<uint64_t, uint64_t> last_block_timestamp_;
   1383 
   1384   // Pointer to the writer object. Not owned by this class.
   1385   IMkvWriter* writer_;
   1386 
   1387   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster);
   1388 };
   1389 
   1390 ///////////////////////////////////////////////////////////////
   1391 // SeekHead element
   1392 class SeekHead {
   1393  public:
   1394   SeekHead();
   1395   ~SeekHead();
   1396 
   1397   // TODO(fgalligan): Change this to reserve a certain size. Then check how
   1398   // big the seek entry to be added is as not every seek entry will be the
   1399   // maximum size it could be.
   1400   // Adds a seek entry to be written out when the element is finalized. |id|
   1401   // must be the coded mkv element id. |pos| is the file position of the
   1402   // element. Returns true on success.
   1403   bool AddSeekEntry(uint32_t id, uint64_t pos);
   1404 
   1405   // Writes out SeekHead and SeekEntry elements. Returns true on success.
   1406   bool Finalize(IMkvWriter* writer) const;
   1407 
   1408   // Returns the id of the Seek Entry at the given index. Returns -1 if index is
   1409   // out of range.
   1410   uint32_t GetId(int index) const;
   1411 
   1412   // Returns the position of the Seek Entry at the given index. Returns -1 if
   1413   // index is out of range.
   1414   uint64_t GetPosition(int index) const;
   1415 
   1416   // Sets the Seek Entry id and position at given index.
   1417   // Returns true on success.
   1418   bool SetSeekEntry(int index, uint32_t id, uint64_t position);
   1419 
   1420   // Reserves space by writing out a Void element which will be updated with
   1421   // a SeekHead element later. Returns true on success.
   1422   bool Write(IMkvWriter* writer);
   1423 
   1424   // We are going to put a cap on the number of Seek Entries.
   1425   const static int32_t kSeekEntryCount = 5;
   1426 
   1427  private:
   1428   // Returns the maximum size in bytes of one seek entry.
   1429   uint64_t MaxEntrySize() const;
   1430 
   1431   // Seek entry id element list.
   1432   uint32_t seek_entry_id_[kSeekEntryCount];
   1433 
   1434   // Seek entry pos element list.
   1435   uint64_t seek_entry_pos_[kSeekEntryCount];
   1436 
   1437   // The file position of SeekHead element.
   1438   int64_t start_pos_;
   1439 
   1440   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead);
   1441 };
   1442 
   1443 ///////////////////////////////////////////////////////////////
   1444 // Segment Information element
   1445 class SegmentInfo {
   1446  public:
   1447   SegmentInfo();
   1448   ~SegmentInfo();
   1449 
   1450   // Will update the duration if |duration_| is > 0.0. Returns true on success.
   1451   bool Finalize(IMkvWriter* writer) const;
   1452 
   1453   // Sets |muxing_app_| and |writing_app_|.
   1454   bool Init();
   1455 
   1456   // Output the Segment Information element to the writer. Returns true on
   1457   // success.
   1458   bool Write(IMkvWriter* writer);
   1459 
   1460   void set_duration(double duration) { duration_ = duration; }
   1461   double duration() const { return duration_; }
   1462   void set_muxing_app(const char* app);
   1463   const char* muxing_app() const { return muxing_app_; }
   1464   void set_timecode_scale(uint64_t scale) { timecode_scale_ = scale; }
   1465   uint64_t timecode_scale() const { return timecode_scale_; }
   1466   void set_writing_app(const char* app);
   1467   const char* writing_app() const { return writing_app_; }
   1468   void set_date_utc(int64_t date_utc) { date_utc_ = date_utc; }
   1469   int64_t date_utc() const { return date_utc_; }
   1470 
   1471  private:
   1472   // Segment Information element names.
   1473   // Initially set to -1 to signify that a duration has not been set and should
   1474   // not be written out.
   1475   double duration_;
   1476   // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
   1477   char* muxing_app_;
   1478   uint64_t timecode_scale_;
   1479   // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
   1480   char* writing_app_;
   1481   // LLONG_MIN when DateUTC is not set.
   1482   int64_t date_utc_;
   1483 
   1484   // The file position of the duration element.
   1485   int64_t duration_pos_;
   1486 
   1487   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo);
   1488 };
   1489 
   1490 ///////////////////////////////////////////////////////////////
   1491 // This class represents the main segment in a WebM file. Currently only
   1492 // supports one Segment element.
   1493 //
   1494 // Notes:
   1495 //  |Init| must be called before any other method in this class.
   1496 class Segment {
   1497  public:
   1498   enum Mode { kLive = 0x1, kFile = 0x2 };
   1499 
   1500   enum CuesPosition {
   1501     kAfterClusters = 0x0,  // Position Cues after Clusters - Default
   1502     kBeforeClusters = 0x1  // Position Cues before Clusters
   1503   };
   1504 
   1505   static const uint32_t kDefaultDocTypeVersion = 4;
   1506   static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL;
   1507 
   1508   Segment();
   1509   ~Segment();
   1510 
   1511   // Initializes |SegmentInfo| and returns result. Always returns false when
   1512   // |ptr_writer| is NULL.
   1513   bool Init(IMkvWriter* ptr_writer);
   1514 
   1515   // Adds a generic track to the segment.  Returns the newly-allocated
   1516   // track object (which is owned by the segment) on success, NULL on
   1517   // error. |number| is the number to use for the track.  |number|
   1518   // must be >= 0. If |number| == 0 then the muxer will decide on the
   1519   // track number.
   1520   Track* AddTrack(int32_t number);
   1521 
   1522   // Adds a Vorbis audio track to the segment. Returns the number of the track
   1523   // on success, 0 on error. |number| is the number to use for the audio track.
   1524   // |number| must be >= 0. If |number| == 0 then the muxer will decide on
   1525   // the track number.
   1526   uint64_t AddAudioTrack(int32_t sample_rate, int32_t channels, int32_t number);
   1527 
   1528   // Adds an empty chapter to the chapters of this segment.  Returns
   1529   // non-NULL on success.  After adding the chapter, the caller should
   1530   // populate its fields via the Chapter member functions.
   1531   Chapter* AddChapter();
   1532 
   1533   // Adds an empty tag to the tags of this segment.  Returns
   1534   // non-NULL on success.  After adding the tag, the caller should
   1535   // populate its fields via the Tag member functions.
   1536   Tag* AddTag();
   1537 
   1538   // Adds a cue point to the Cues element. |timestamp| is the time in
   1539   // nanoseconds of the cue's time. |track| is the Track of the Cue. This
   1540   // function must be called after AddFrame to calculate the correct
   1541   // BlockNumber for the CuePoint. Returns true on success.
   1542   bool AddCuePoint(uint64_t timestamp, uint64_t track);
   1543 
   1544   // Adds a frame to be output in the file. Returns true on success.
   1545   // Inputs:
   1546   //   data: Pointer to the data
   1547   //   length: Length of the data
   1548   //   track_number: Track to add the data to. Value returned by Add track
   1549   //                 functions.
   1550   //   timestamp:    Timestamp of the frame in nanoseconds from 0.
   1551   //   is_key:       Flag telling whether or not this frame is a key frame.
   1552   bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number,
   1553                 uint64_t timestamp_ns, bool is_key);
   1554 
   1555   // Writes a frame of metadata to the output medium; returns true on
   1556   // success.
   1557   // Inputs:
   1558   //   data: Pointer to the data
   1559   //   length: Length of the data
   1560   //   track_number: Track to add the data to. Value returned by Add track
   1561   //                 functions.
   1562   //   timecode:     Absolute timestamp of the metadata frame, expressed
   1563   //                 in nanosecond units.
   1564   //   duration:     Duration of metadata frame, in nanosecond units.
   1565   //
   1566   // The metadata frame is written as a block group, with a duration
   1567   // sub-element but no reference time sub-elements (indicating that
   1568   // it is considered a keyframe, per Matroska semantics).
   1569   bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number,
   1570                    uint64_t timestamp_ns, uint64_t duration_ns);
   1571 
   1572   // Writes a frame with additional data to the output medium; returns true on
   1573   // success.
   1574   // Inputs:
   1575   //   data: Pointer to the data.
   1576   //   length: Length of the data.
   1577   //   additional: Pointer to additional data.
   1578   //   additional_length: Length of additional data.
   1579   //   add_id: Additional ID which identifies the type of additional data.
   1580   //   track_number: Track to add the data to. Value returned by Add track
   1581   //                 functions.
   1582   //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond
   1583   //                 units.
   1584   //   is_key:       Flag telling whether or not this frame is a key frame.
   1585   bool AddFrameWithAdditional(const uint8_t* data, uint64_t length,
   1586                               const uint8_t* additional,
   1587                               uint64_t additional_length, uint64_t add_id,
   1588                               uint64_t track_number, uint64_t timestamp,
   1589                               bool is_key);
   1590 
   1591   // Writes a frame with DiscardPadding to the output medium; returns true on
   1592   // success.
   1593   // Inputs:
   1594   //   data: Pointer to the data.
   1595   //   length: Length of the data.
   1596   //   discard_padding: DiscardPadding element value.
   1597   //   track_number: Track to add the data to. Value returned by Add track
   1598   //                 functions.
   1599   //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond
   1600   //                 units.
   1601   //   is_key:       Flag telling whether or not this frame is a key frame.
   1602   bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
   1603                                   int64_t discard_padding,
   1604                                   uint64_t track_number, uint64_t timestamp,
   1605                                   bool is_key);
   1606 
   1607   // Writes a Frame to the output medium. Chooses the correct way of writing
   1608   // the frame (Block vs SimpleBlock) based on the parameters passed.
   1609   // Inputs:
   1610   //   frame: frame object
   1611   bool AddGenericFrame(const Frame* frame);
   1612 
   1613   // Adds a VP8 video track to the segment. Returns the number of the track on
   1614   // success, 0 on error. |number| is the number to use for the video track.
   1615   // |number| must be >= 0. If |number| == 0 then the muxer will decide on
   1616   // the track number.
   1617   uint64_t AddVideoTrack(int32_t width, int32_t height, int32_t number);
   1618 
   1619   // This function must be called after Finalize() if you need a copy of the
   1620   // output with Cues written before the Clusters. It will return false if the
   1621   // writer is not seekable of if chunking is set to true.
   1622   // Input parameters:
   1623   // reader - an IMkvReader object created with the same underlying file of the
   1624   //          current writer object. Make sure to close the existing writer
   1625   //          object before creating this so that all the data is properly
   1626   //          flushed and available for reading.
   1627   // writer - an IMkvWriter object pointing to a *different* file than the one
   1628   //          pointed by the current writer object. This file will contain the
   1629   //          Cues element before the Clusters.
   1630   bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
   1631                                      IMkvWriter* writer);
   1632 
   1633   // Sets which track to use for the Cues element. Must have added the track
   1634   // before calling this function. Returns true on success. |track_number| is
   1635   // returned by the Add track functions.
   1636   bool CuesTrack(uint64_t track_number);
   1637 
   1638   // This will force the muxer to create a new Cluster when the next frame is
   1639   // added.
   1640   void ForceNewClusterOnNextFrame();
   1641 
   1642   // Writes out any frames that have not been written out. Finalizes the last
   1643   // cluster. May update the size and duration of the segment. May output the
   1644   // Cues element. May finalize the SeekHead element. Returns true on success.
   1645   bool Finalize();
   1646 
   1647   // Returns the Cues object.
   1648   Cues* GetCues() { return &cues_; }
   1649 
   1650   // Returns the Segment Information object.
   1651   const SegmentInfo* GetSegmentInfo() const { return &segment_info_; }
   1652   SegmentInfo* GetSegmentInfo() { return &segment_info_; }
   1653 
   1654   // Search the Tracks and return the track that matches |track_number|.
   1655   // Returns NULL if there is no track match.
   1656   Track* GetTrackByNumber(uint64_t track_number) const;
   1657 
   1658   // Toggles whether to output a cues element.
   1659   void OutputCues(bool output_cues);
   1660 
   1661   // Toggles whether to write the last frame in each Cluster with Duration.
   1662   void AccurateClusterDuration(bool accurate_cluster_duration);
   1663 
   1664   // Toggles whether to write the Cluster Timecode using exactly 8 bytes.
   1665   void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode);
   1666 
   1667   // Sets if the muxer will output files in chunks or not. |chunking| is a
   1668   // flag telling whether or not to turn on chunking. |filename| is the base
   1669   // filename for the chunk files. The header chunk file will be named
   1670   // |filename|.hdr and the data chunks will be named
   1671   // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing
   1672   // to files so the muxer will use the default MkvWriter class to control
   1673   // what data is written to what files. Returns true on success.
   1674   // TODO: Should we change the IMkvWriter Interface to add Open and Close?
   1675   // That will force the interface to be dependent on files.
   1676   bool SetChunking(bool chunking, const char* filename);
   1677 
   1678   bool chunking() const { return chunking_; }
   1679   uint64_t cues_track() const { return cues_track_; }
   1680   void set_max_cluster_duration(uint64_t max_cluster_duration) {
   1681     max_cluster_duration_ = max_cluster_duration;
   1682   }
   1683   uint64_t max_cluster_duration() const { return max_cluster_duration_; }
   1684   void set_max_cluster_size(uint64_t max_cluster_size) {
   1685     max_cluster_size_ = max_cluster_size;
   1686   }
   1687   uint64_t max_cluster_size() const { return max_cluster_size_; }
   1688   void set_mode(Mode mode) { mode_ = mode; }
   1689   Mode mode() const { return mode_; }
   1690   CuesPosition cues_position() const { return cues_position_; }
   1691   bool output_cues() const { return output_cues_; }
   1692   void set_estimate_file_duration(bool estimate_duration) {
   1693     estimate_file_duration_ = estimate_duration;
   1694   }
   1695   bool estimate_file_duration() const { return estimate_file_duration_; }
   1696   const SegmentInfo* segment_info() const { return &segment_info_; }
   1697   void set_duration(double duration) { duration_ = duration; }
   1698   double duration() const { return duration_; }
   1699 
   1700   // Returns true when codec IDs are valid for WebM.
   1701   bool DocTypeIsWebm() const;
   1702 
   1703  private:
   1704   // Checks if header information has been output and initialized. If not it
   1705   // will output the Segment element and initialize the SeekHead elment and
   1706   // Cues elements.
   1707   bool CheckHeaderInfo();
   1708 
   1709   // Sets |doc_type_version_| based on the current element requirements.
   1710   void UpdateDocTypeVersion();
   1711 
   1712   // Sets |name| according to how many chunks have been written. |ext| is the
   1713   // file extension. |name| must be deleted by the calling app. Returns true
   1714   // on success.
   1715   bool UpdateChunkName(const char* ext, char** name) const;
   1716 
   1717   // Returns the maximum offset within the segment's payload. When chunking
   1718   // this function is needed to determine offsets of elements within the
   1719   // chunked files. Returns -1 on error.
   1720   int64_t MaxOffset();
   1721 
   1722   // Adds the frame to our frame array.
   1723   bool QueueFrame(Frame* frame);
   1724 
   1725   // Output all frames that are queued. Returns -1 on error, otherwise
   1726   // it returns the number of frames written.
   1727   int WriteFramesAll();
   1728 
   1729   // Output all frames that are queued that have an end time that is less
   1730   // then |timestamp|. Returns true on success and if there are no frames
   1731   // queued.
   1732   bool WriteFramesLessThan(uint64_t timestamp);
   1733 
   1734   // Outputs the segment header, Segment Information element, SeekHead element,
   1735   // and Tracks element to |writer_|.
   1736   bool WriteSegmentHeader();
   1737 
   1738   // Given a frame with the specified timestamp (nanosecond units) and
   1739   // keyframe status, determine whether a new cluster should be
   1740   // created, before writing enqueued frames and the frame itself. The
   1741   // function returns one of the following values:
   1742   //  -1 = error: an out-of-order frame was detected
   1743   //  0 = do not create a new cluster, and write frame to the existing cluster
   1744   //  1 = create a new cluster, and write frame to that new cluster
   1745   //  2 = create a new cluster, and re-run test
   1746   int TestFrame(uint64_t track_num, uint64_t timestamp_ns, bool key) const;
   1747 
   1748   // Create a new cluster, using the earlier of the first enqueued
   1749   // frame, or the indicated time. Returns true on success.
   1750   bool MakeNewCluster(uint64_t timestamp_ns);
   1751 
   1752   // Checks whether a new cluster needs to be created, and if so
   1753   // creates a new cluster. Returns false if creation of a new cluster
   1754   // was necessary but creation was not successful.
   1755   bool DoNewClusterProcessing(uint64_t track_num, uint64_t timestamp_ns,
   1756                               bool key);
   1757 
   1758   // Adjusts Cue Point values (to place Cues before Clusters) so that they
   1759   // reflect the correct offsets.
   1760   void MoveCuesBeforeClusters();
   1761 
   1762   // This function recursively computes the correct cluster offsets (this is
   1763   // done to move the Cues before Clusters). It recursively updates the change
   1764   // in size (which indicates a change in cluster offset) until no sizes change.
   1765   // Parameters:
   1766   // diff - indicates the difference in size of the Cues element that needs to
   1767   //        accounted for.
   1768   // index - index in the list of Cues which is currently being adjusted.
   1769   // cue_size - sum of size of all the CuePoint elements.
   1770   void MoveCuesBeforeClustersHelper(uint64_t diff, int index,
   1771                                     uint64_t* cue_size);
   1772 
   1773   // Seeds the random number generator used to make UIDs.
   1774   unsigned int seed_;
   1775 
   1776   // WebM elements
   1777   Cues cues_;
   1778   SeekHead seek_head_;
   1779   SegmentInfo segment_info_;
   1780   Tracks tracks_;
   1781   Chapters chapters_;
   1782   Tags tags_;
   1783 
   1784   // Number of chunks written.
   1785   int chunk_count_;
   1786 
   1787   // Current chunk filename.
   1788   char* chunk_name_;
   1789 
   1790   // Default MkvWriter object created by this class used for writing clusters
   1791   // out in separate files.
   1792   MkvWriter* chunk_writer_cluster_;
   1793 
   1794   // Default MkvWriter object created by this class used for writing Cues
   1795   // element out to a file.
   1796   MkvWriter* chunk_writer_cues_;
   1797 
   1798   // Default MkvWriter object created by this class used for writing the
   1799   // Matroska header out to a file.
   1800   MkvWriter* chunk_writer_header_;
   1801 
   1802   // Flag telling whether or not the muxer is chunking output to multiple
   1803   // files.
   1804   bool chunking_;
   1805 
   1806   // Base filename for the chunked files.
   1807   char* chunking_base_name_;
   1808 
   1809   // File position offset where the Clusters end.
   1810   int64_t cluster_end_offset_;
   1811 
   1812   // List of clusters.
   1813   Cluster** cluster_list_;
   1814 
   1815   // Number of cluster pointers allocated in the cluster list.
   1816   int32_t cluster_list_capacity_;
   1817 
   1818   // Number of clusters in the cluster list.
   1819   int32_t cluster_list_size_;
   1820 
   1821   // Indicates whether Cues should be written before or after Clusters
   1822   CuesPosition cues_position_;
   1823 
   1824   // Track number that is associated with the cues element for this segment.
   1825   uint64_t cues_track_;
   1826 
   1827   // Tells the muxer to force a new cluster on the next Block.
   1828   bool force_new_cluster_;
   1829 
   1830   // List of stored audio frames. These variables are used to store frames so
   1831   // the muxer can follow the guideline "Audio blocks that contain the video
   1832   // key frame's timecode should be in the same cluster as the video key frame
   1833   // block."
   1834   Frame** frames_;
   1835 
   1836   // Number of frame pointers allocated in the frame list.
   1837   int32_t frames_capacity_;
   1838 
   1839   // Number of frames in the frame list.
   1840   int32_t frames_size_;
   1841 
   1842   // Flag telling if a video track has been added to the segment.
   1843   bool has_video_;
   1844 
   1845   // Flag telling if the segment's header has been written.
   1846   bool header_written_;
   1847 
   1848   // Duration of the last block in nanoseconds.
   1849   uint64_t last_block_duration_;
   1850 
   1851   // Last timestamp in nanoseconds added to a cluster.
   1852   uint64_t last_timestamp_;
   1853 
   1854   // Last timestamp in nanoseconds by track number added to a cluster.
   1855   uint64_t last_track_timestamp_[kMaxTrackNumber];
   1856 
   1857   // Number of frames written per track.
   1858   uint64_t track_frames_written_[kMaxTrackNumber];
   1859 
   1860   // Maximum time in nanoseconds for a cluster duration. This variable is a
   1861   // guideline and some clusters may have a longer duration. Default is 30
   1862   // seconds.
   1863   uint64_t max_cluster_duration_;
   1864 
   1865   // Maximum size in bytes for a cluster. This variable is a guideline and
   1866   // some clusters may have a larger size. Default is 0 which signifies that
   1867   // the muxer will decide the size.
   1868   uint64_t max_cluster_size_;
   1869 
   1870   // The mode that segment is in. If set to |kLive| the writer must not
   1871   // seek backwards.
   1872   Mode mode_;
   1873 
   1874   // Flag telling the muxer that a new cue point should be added.
   1875   bool new_cuepoint_;
   1876 
   1877   // TODO(fgalligan): Should we add support for more than one Cues element?
   1878   // Flag whether or not the muxer should output a Cues element.
   1879   bool output_cues_;
   1880 
   1881   // Flag whether or not the last frame in each Cluster will have a Duration
   1882   // element in it.
   1883   bool accurate_cluster_duration_;
   1884 
   1885   // Flag whether or not to write the Cluster Timecode using exactly 8 bytes.
   1886   bool fixed_size_cluster_timecode_;
   1887 
   1888   // Flag whether or not to estimate the file duration.
   1889   bool estimate_file_duration_;
   1890 
   1891   // The size of the EBML header, used to validate the header if
   1892   // WriteEbmlHeader() is called more than once.
   1893   int32_t ebml_header_size_;
   1894 
   1895   // The file position of the segment's payload.
   1896   int64_t payload_pos_;
   1897 
   1898   // The file position of the element's size.
   1899   int64_t size_position_;
   1900 
   1901   // Current DocTypeVersion (|doc_type_version_|) and that written in
   1902   // WriteSegmentHeader().
   1903   // WriteEbmlHeader() will be called from Finalize() if |doc_type_version_|
   1904   // differs from |doc_type_version_written_|.
   1905   uint32_t doc_type_version_;
   1906   uint32_t doc_type_version_written_;
   1907 
   1908   // If |duration_| is > 0, then explicitly set the duration of the segment.
   1909   double duration_;
   1910 
   1911   // Pointer to the writer objects. Not owned by this class.
   1912   IMkvWriter* writer_cluster_;
   1913   IMkvWriter* writer_cues_;
   1914   IMkvWriter* writer_header_;
   1915 
   1916   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
   1917 };
   1918 
   1919 }  // namespace mkvmuxer
   1920 
   1921 #endif  // MKVMUXER_MKVMUXER_H_
   1922