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 
add_id()110   uint64_t add_id() const { return add_id_; }
additional()111   const uint8_t* additional() const { return additional_; }
additional_length()112   uint64_t additional_length() const { return additional_length_; }
113   void set_duration(uint64_t duration);
duration()114   uint64_t duration() const { return duration_; }
duration_set()115   bool duration_set() const { return duration_set_; }
frame()116   const uint8_t* frame() const { return frame_; }
set_is_key(bool key)117   void set_is_key(bool key) { is_key_ = key; }
is_key()118   bool is_key() const { return is_key_; }
length()119   uint64_t length() const { return length_; }
set_track_number(uint64_t track_number)120   void set_track_number(uint64_t track_number) { track_number_ = track_number; }
track_number()121   uint64_t track_number() const { return track_number_; }
set_timestamp(uint64_t timestamp)122   void set_timestamp(uint64_t timestamp) { timestamp_ = timestamp; }
timestamp()123   uint64_t timestamp() const { return timestamp_; }
set_discard_padding(int64_t discard_padding)124   void set_discard_padding(int64_t discard_padding) {
125     discard_padding_ = discard_padding;
126   }
discard_padding()127   int64_t discard_padding() const { return discard_padding_; }
128   void set_reference_block_timestamp(int64_t reference_block_timestamp);
reference_block_timestamp()129   int64_t reference_block_timestamp() const {
130     return reference_block_timestamp_;
131   }
reference_block_timestamp_set()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 
set_time(uint64_t time)194   void set_time(uint64_t time) { time_ = time; }
time()195   uint64_t time() const { return time_; }
set_track(uint64_t track)196   void set_track(uint64_t track) { track_ = track; }
track()197   uint64_t track() const { return track_; }
set_cluster_pos(uint64_t cluster_pos)198   void set_cluster_pos(uint64_t cluster_pos) { cluster_pos_ = cluster_pos; }
cluster_pos()199   uint64_t cluster_pos() const { return cluster_pos_; }
set_block_number(uint64_t block_number)200   void set_block_number(uint64_t block_number) { block_number_ = block_number; }
block_number()201   uint64_t block_number() const { return block_number_; }
set_output_block_number(bool output_block_number)202   void set_output_block_number(bool output_block_number) {
203     output_block_number_ = output_block_number;
204   }
output_block_number()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 
cue_entries_size()250   int32_t cue_entries_size() const { return cue_entries_size_; }
set_output_block_number(bool output_block_number)251   void set_output_block_number(bool output_block_number) {
252     output_block_number_ = output_block_number;
253   }
output_block_number()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();
~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 
cipher_mode()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 
enc_algo()325   uint64_t enc_algo() const { return enc_algo_; }
encoding_order()326   uint64_t encoding_order() const { return encoding_order_; }
encoding_scope()327   uint64_t encoding_scope() const { return encoding_scope_; }
encoding_type()328   uint64_t encoding_type() const { return encoding_type_; }
enc_aes_settings()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 
PrimaryChromaticity(float x_val,float y_val)362   PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {}
PrimaryChromaticity()363   PrimaryChromaticity() : x_(0), y_(0) {}
~PrimaryChromaticity()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 
x()373   float x() const { return x_; }
set_x(float new_x)374   void set_x(float new_x) { x_ = new_x; }
y()375   float y() const { return y_; }
set_y(float new_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 
MasteringMetadata()390   MasteringMetadata()
391       : luminance_max_(kValueNotPresent),
392         luminance_min_(kValueNotPresent),
393         r_(NULL),
394         g_(NULL),
395         b_(NULL),
396         white_point_(NULL) {}
~MasteringMetadata()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);
r()414   const PrimaryChromaticity* r() const { return r_; }
g()415   const PrimaryChromaticity* g() const { return g_; }
b()416   const PrimaryChromaticity* b() const { return b_; }
white_point()417   const PrimaryChromaticity* white_point() const { return white_point_; }
418 
luminance_max()419   float luminance_max() const { return luminance_max_; }
set_luminance_max(float luminance_max)420   void set_luminance_max(float luminance_max) {
421     luminance_max_ = luminance_max;
422   }
luminance_min()423   float luminance_min() const { return luminance_min_; }
set_luminance_min(float 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;
Colour()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) {}
~Colour()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 
mastering_metadata()531   const MasteringMetadata* mastering_metadata() const {
532     return mastering_metadata_;
533   }
534 
matrix_coefficients()535   uint64_t matrix_coefficients() const { return matrix_coefficients_; }
set_matrix_coefficients(uint64_t matrix_coefficients)536   void set_matrix_coefficients(uint64_t matrix_coefficients) {
537     matrix_coefficients_ = matrix_coefficients;
538   }
bits_per_channel()539   uint64_t bits_per_channel() const { return bits_per_channel_; }
set_bits_per_channel(uint64_t bits_per_channel)540   void set_bits_per_channel(uint64_t bits_per_channel) {
541     bits_per_channel_ = bits_per_channel;
542   }
chroma_subsampling_horz()543   uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; }
set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz)544   void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) {
545     chroma_subsampling_horz_ = chroma_subsampling_horz;
546   }
chroma_subsampling_vert()547   uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; }
set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert)548   void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) {
549     chroma_subsampling_vert_ = chroma_subsampling_vert;
550   }
cb_subsampling_horz()551   uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; }
set_cb_subsampling_horz(uint64_t cb_subsampling_horz)552   void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) {
553     cb_subsampling_horz_ = cb_subsampling_horz;
554   }
cb_subsampling_vert()555   uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; }
set_cb_subsampling_vert(uint64_t cb_subsampling_vert)556   void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) {
557     cb_subsampling_vert_ = cb_subsampling_vert;
558   }
chroma_siting_horz()559   uint64_t chroma_siting_horz() const { return chroma_siting_horz_; }
set_chroma_siting_horz(uint64_t chroma_siting_horz)560   void set_chroma_siting_horz(uint64_t chroma_siting_horz) {
561     chroma_siting_horz_ = chroma_siting_horz;
562   }
chroma_siting_vert()563   uint64_t chroma_siting_vert() const { return chroma_siting_vert_; }
set_chroma_siting_vert(uint64_t chroma_siting_vert)564   void set_chroma_siting_vert(uint64_t chroma_siting_vert) {
565     chroma_siting_vert_ = chroma_siting_vert;
566   }
range()567   uint64_t range() const { return range_; }
set_range(uint64_t range)568   void set_range(uint64_t range) { range_ = range; }
transfer_characteristics()569   uint64_t transfer_characteristics() const {
570     return transfer_characteristics_;
571   }
set_transfer_characteristics(uint64_t transfer_characteristics)572   void set_transfer_characteristics(uint64_t transfer_characteristics) {
573     transfer_characteristics_ = transfer_characteristics;
574   }
primaries()575   uint64_t primaries() const { return primaries_; }
set_primaries(uint64_t primaries)576   void set_primaries(uint64_t primaries) { primaries_ = primaries; }
max_cll()577   uint64_t max_cll() const { return max_cll_; }
set_max_cll(uint64_t max_cll)578   void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; }
max_fall()579   uint64_t max_fall() const { return max_fall_; }
set_max_fall(uint64_t 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;
Projection()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) {}
~Projection()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 
type()630   ProjectionType type() const { return type_; }
set_type(ProjectionType type)631   void set_type(ProjectionType type) { type_ = type; }
pose_yaw()632   float pose_yaw() const { return pose_yaw_; }
set_pose_yaw(float pose_yaw)633   void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; }
pose_pitch()634   float pose_pitch() const { return pose_pitch_; }
set_pose_pitch(float pose_pitch)635   void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; }
pose_roll()636   float pose_roll() const { return pose_roll_; }
set_pose_roll(float pose_roll)637   void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; }
private_data()638   uint8_t* private_data() const { return private_data_; }
private_data_length()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);
codec_id()682   const char* codec_id() const { return codec_id_; }
codec_private()683   const uint8_t* codec_private() const { return codec_private_; }
684   void set_language(const char* language);
language()685   const char* language() const { return language_; }
set_max_block_additional_id(uint64_t max_block_additional_id)686   void set_max_block_additional_id(uint64_t max_block_additional_id) {
687     max_block_additional_id_ = max_block_additional_id;
688   }
max_block_additional_id()689   uint64_t max_block_additional_id() const { return max_block_additional_id_; }
690   void set_name(const char* name);
name()691   const char* name() const { return name_; }
set_number(uint64_t number)692   void set_number(uint64_t number) { number_ = number; }
number()693   uint64_t number() const { return number_; }
set_type(uint64_t type)694   void set_type(uint64_t type) { type_ = type; }
type()695   uint64_t type() const { return type_; }
set_uid(uint64_t uid)696   void set_uid(uint64_t uid) { uid_ = uid; }
uid()697   uint64_t uid() const { return uid_; }
set_codec_delay(uint64_t codec_delay)698   void set_codec_delay(uint64_t codec_delay) { codec_delay_ = codec_delay; }
codec_delay()699   uint64_t codec_delay() const { return codec_delay_; }
set_seek_pre_roll(uint64_t seek_pre_roll)700   void set_seek_pre_roll(uint64_t seek_pre_roll) {
701     seek_pre_roll_ = seek_pre_roll;
702   }
seek_pre_roll()703   uint64_t seek_pre_roll() const { return seek_pre_roll_; }
set_default_duration(uint64_t default_duration)704   void set_default_duration(uint64_t default_duration) {
705     default_duration_ = default_duration;
706   }
default_duration()707   uint64_t default_duration() const { return default_duration_; }
708 
codec_private_length()709   uint64_t codec_private_length() const { return codec_private_length_; }
content_encoding_entries_size()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 
set_display_height(uint64_t height)772   void set_display_height(uint64_t height) { display_height_ = height; }
display_height()773   uint64_t display_height() const { return display_height_; }
set_display_width(uint64_t width)774   void set_display_width(uint64_t width) { display_width_ = width; }
display_width()775   uint64_t display_width() const { return display_width_; }
set_pixel_height(uint64_t height)776   void set_pixel_height(uint64_t height) { pixel_height_ = height; }
pixel_height()777   uint64_t pixel_height() const { return pixel_height_; }
set_pixel_width(uint64_t width)778   void set_pixel_width(uint64_t width) { pixel_width_ = width; }
pixel_width()779   uint64_t pixel_width() const { return pixel_width_; }
780 
set_crop_left(uint64_t crop_left)781   void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; }
crop_left()782   uint64_t crop_left() const { return crop_left_; }
set_crop_right(uint64_t crop_right)783   void set_crop_right(uint64_t crop_right) { crop_right_ = crop_right; }
crop_right()784   uint64_t crop_right() const { return crop_right_; }
set_crop_top(uint64_t crop_top)785   void set_crop_top(uint64_t crop_top) { crop_top_ = crop_top; }
crop_top()786   uint64_t crop_top() const { return crop_top_; }
set_crop_bottom(uint64_t crop_bottom)787   void set_crop_bottom(uint64_t crop_bottom) { crop_bottom_ = crop_bottom; }
crop_bottom()788   uint64_t crop_bottom() const { return crop_bottom_; }
789 
set_frame_rate(double frame_rate)790   void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; }
frame_rate()791   double frame_rate() const { return frame_rate_; }
set_height(uint64_t height)792   void set_height(uint64_t height) { height_ = height; }
height()793   uint64_t height() const { return height_; }
stereo_mode()794   uint64_t stereo_mode() { return stereo_mode_; }
alpha_mode()795   uint64_t alpha_mode() { return alpha_mode_; }
set_width(uint64_t width)796   void set_width(uint64_t width) { width_ = width; }
width()797   uint64_t width() const { return width_; }
798   void set_colour_space(const char* colour_space);
colour_space()799   const char* colour_space() const { return colour_space_; }
800 
colour()801   Colour* colour() { return colour_; }
802 
803   // Deep copies |colour|.
804   bool SetColour(const Colour& colour);
805 
projection()806   Projection* projection() { return projection_; }
807 
808   // Deep copies |projection|.
809   bool SetProjection(const Projection& projection);
810 
811  private:
812   // Returns the size in bytes of the Video element.
813   uint64_t VideoPayloadSize() const;
814 
815   // Video track element names.
816   uint64_t display_height_;
817   uint64_t display_width_;
818   uint64_t pixel_height_;
819   uint64_t pixel_width_;
820   uint64_t crop_left_;
821   uint64_t crop_right_;
822   uint64_t crop_top_;
823   uint64_t crop_bottom_;
824   double frame_rate_;
825   uint64_t height_;
826   uint64_t stereo_mode_;
827   uint64_t alpha_mode_;
828   uint64_t width_;
829   char* colour_space_;
830 
831   Colour* colour_;
832   Projection* projection_;
833 
834   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
835 };
836 
837 ///////////////////////////////////////////////////////////////
838 // Track that has audio specific elements.
839 class AudioTrack : public Track {
840  public:
841   // The |seed| parameter is used to synthesize a UID for the track.
842   explicit AudioTrack(unsigned int* seed);
843   virtual ~AudioTrack();
844 
845   // Returns the size in bytes for the payload of the Track element plus the
846   // audio specific elements.
847   virtual uint64_t PayloadSize() const;
848 
849   // Output the AudioTrack element to the writer. Returns true on success.
850   virtual bool Write(IMkvWriter* writer) const;
851 
set_bit_depth(uint64_t bit_depth)852   void set_bit_depth(uint64_t bit_depth) { bit_depth_ = bit_depth; }
bit_depth()853   uint64_t bit_depth() const { return bit_depth_; }
set_channels(uint64_t channels)854   void set_channels(uint64_t channels) { channels_ = channels; }
channels()855   uint64_t channels() const { return channels_; }
set_sample_rate(double sample_rate)856   void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; }
sample_rate()857   double sample_rate() const { return sample_rate_; }
858 
859  private:
860   // Audio track element names.
861   uint64_t bit_depth_;
862   uint64_t channels_;
863   double sample_rate_;
864 
865   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack);
866 };
867 
868 ///////////////////////////////////////////////////////////////
869 // Tracks element
870 class Tracks {
871  public:
872   // Audio and video type defined by the Matroska specs.
873   enum { kVideo = 0x1, kAudio = 0x2 };
874 
875   static const char kOpusCodecId[];
876   static const char kVorbisCodecId[];
877   static const char kAv1CodecId[];
878   static const char kVp8CodecId[];
879   static const char kVp9CodecId[];
880   static const char kWebVttCaptionsId[];
881   static const char kWebVttDescriptionsId[];
882   static const char kWebVttMetadataId[];
883   static const char kWebVttSubtitlesId[];
884 
885   Tracks();
886   ~Tracks();
887 
888   // Adds a Track element to the Tracks object. |track| will be owned and
889   // deleted by the Tracks object. Returns true on success. |number| is the
890   // number to use for the track. |number| must be >= 0. If |number| == 0
891   // then the muxer will decide on the track number.
892   bool AddTrack(Track* track, int32_t number);
893 
894   // Returns the track by index. Returns NULL if there is no track match.
895   const Track* GetTrackByIndex(uint32_t idx) const;
896 
897   // Search the Tracks and return the track that matches |tn|. Returns NULL
898   // if there is no track match.
899   Track* GetTrackByNumber(uint64_t track_number) const;
900 
901   // Returns true if the track number is an audio track.
902   bool TrackIsAudio(uint64_t track_number) const;
903 
904   // Returns true if the track number is a video track.
905   bool TrackIsVideo(uint64_t track_number) const;
906 
907   // Output the Tracks element to the writer. Returns true on success.
908   bool Write(IMkvWriter* writer) const;
909 
track_entries_size()910   uint32_t track_entries_size() const { return track_entries_size_; }
911 
912  private:
913   // Track element list.
914   Track** track_entries_;
915 
916   // Number of Track elements added.
917   uint32_t track_entries_size_;
918 
919   // Whether or not Tracks element has already been written via IMkvWriter.
920   mutable bool wrote_tracks_;
921 
922   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks);
923 };
924 
925 ///////////////////////////////////////////////////////////////
926 // Chapter element
927 //
928 class Chapter {
929  public:
930   // Set the identifier for this chapter.  (This corresponds to the
931   // Cue Identifier line in WebVTT.)
932   // TODO(matthewjheaney): the actual serialization of this item in
933   // MKV is pending.
934   bool set_id(const char* id);
935 
936   // Converts the nanosecond start and stop times of this chapter to
937   // their corresponding timecode values, and stores them that way.
938   void set_time(const Segment& segment, uint64_t start_time_ns,
939                 uint64_t end_time_ns);
940 
941   // Sets the uid for this chapter. Primarily used to enable
942   // deterministic output from the muxer.
set_uid(const uint64_t uid)943   void set_uid(const uint64_t uid) { uid_ = uid; }
944 
945   // Add a title string to this chapter, per the semantics described
946   // here:
947   //  http://www.matroska.org/technical/specs/index.html
948   //
949   // The title ("chapter string") is a UTF-8 string.
950   //
951   // The language has ISO 639-2 representation, described here:
952   //  http://www.loc.gov/standards/iso639-2/englangn.html
953   //  http://www.loc.gov/standards/iso639-2/php/English_list.php
954   // If you specify NULL as the language value, this implies
955   // English ("eng").
956   //
957   // The country value corresponds to the codes listed here:
958   //  http://www.iana.org/domains/root/db/
959   //
960   // The function returns false if the string could not be allocated.
961   bool add_string(const char* title, const char* language, const char* country);
962 
963  private:
964   friend class Chapters;
965 
966   // For storage of chapter titles that differ by language.
967   class Display {
968    public:
969     // Establish representation invariant for new Display object.
970     void Init();
971 
972     // Reclaim resources, in anticipation of destruction.
973     void Clear();
974 
975     // Copies the title to the |title_| member.  Returns false on
976     // error.
977     bool set_title(const char* title);
978 
979     // Copies the language to the |language_| member.  Returns false
980     // on error.
981     bool set_language(const char* language);
982 
983     // Copies the country to the |country_| member.  Returns false on
984     // error.
985     bool set_country(const char* country);
986 
987     // If |writer| is non-NULL, serialize the Display sub-element of
988     // the Atom into the stream.  Returns the Display element size on
989     // success, 0 if error.
990     uint64_t WriteDisplay(IMkvWriter* writer) const;
991 
992    private:
993     char* title_;
994     char* language_;
995     char* country_;
996   };
997 
998   Chapter();
999   ~Chapter();
1000 
1001   // Establish the representation invariant for a newly-created
1002   // Chapter object.  The |seed| parameter is used to create the UID
1003   // for this chapter atom.
1004   void Init(unsigned int* seed);
1005 
1006   // Copies this Chapter object to a different one.  This is used when
1007   // expanding a plain array of Chapter objects (see Chapters).
1008   void ShallowCopy(Chapter* dst) const;
1009 
1010   // Reclaim resources used by this Chapter object, pending its
1011   // destruction.
1012   void Clear();
1013 
1014   // If there is no storage remaining on the |displays_| array for a
1015   // new display object, creates a new, longer array and copies the
1016   // existing Display objects to the new array.  Returns false if the
1017   // array cannot be expanded.
1018   bool ExpandDisplaysArray();
1019 
1020   // If |writer| is non-NULL, serialize the Atom sub-element into the
1021   // stream.  Returns the total size of the element on success, 0 if
1022   // error.
1023   uint64_t WriteAtom(IMkvWriter* writer) const;
1024 
1025   // The string identifier for this chapter (corresponds to WebVTT cue
1026   // identifier).
1027   char* id_;
1028 
1029   // Start timecode of the chapter.
1030   uint64_t start_timecode_;
1031 
1032   // Stop timecode of the chapter.
1033   uint64_t end_timecode_;
1034 
1035   // The binary identifier for this chapter.
1036   uint64_t uid_;
1037 
1038   // The Atom element can contain multiple Display sub-elements, as
1039   // the same logical title can be rendered in different languages.
1040   Display* displays_;
1041 
1042   // The physical length (total size) of the |displays_| array.
1043   int displays_size_;
1044 
1045   // The logical length (number of active elements) on the |displays_|
1046   // array.
1047   int displays_count_;
1048 
1049   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter);
1050 };
1051 
1052 ///////////////////////////////////////////////////////////////
1053 // Chapters element
1054 //
1055 class Chapters {
1056  public:
1057   Chapters();
1058   ~Chapters();
1059 
1060   Chapter* AddChapter(unsigned int* seed);
1061 
1062   // Returns the number of chapters that have been added.
1063   int Count() const;
1064 
1065   // Output the Chapters element to the writer. Returns true on success.
1066   bool Write(IMkvWriter* writer) const;
1067 
1068  private:
1069   // Expands the chapters_ array if there is not enough space to contain
1070   // another chapter object.  Returns true on success.
1071   bool ExpandChaptersArray();
1072 
1073   // If |writer| is non-NULL, serialize the Edition sub-element of the
1074   // Chapters element into the stream.  Returns the Edition element
1075   // size on success, 0 if error.
1076   uint64_t WriteEdition(IMkvWriter* writer) const;
1077 
1078   // Total length of the chapters_ array.
1079   int chapters_size_;
1080 
1081   // Number of active chapters on the chapters_ array.
1082   int chapters_count_;
1083 
1084   // Array for storage of chapter objects.
1085   Chapter* chapters_;
1086 
1087   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters);
1088 };
1089 
1090 ///////////////////////////////////////////////////////////////
1091 // Tag element
1092 //
1093 class Tag {
1094  public:
1095   bool add_simple_tag(const char* tag_name, const char* tag_string);
1096 
1097  private:
1098   // Tags calls Clear and the destructor of Tag
1099   friend class Tags;
1100 
1101   // For storage of simple tags
1102   class SimpleTag {
1103    public:
1104     // Establish representation invariant for new SimpleTag object.
1105     void Init();
1106 
1107     // Reclaim resources, in anticipation of destruction.
1108     void Clear();
1109 
1110     // Copies the title to the |tag_name_| member.  Returns false on
1111     // error.
1112     bool set_tag_name(const char* tag_name);
1113 
1114     // Copies the language to the |tag_string_| member.  Returns false
1115     // on error.
1116     bool set_tag_string(const char* tag_string);
1117 
1118     // If |writer| is non-NULL, serialize the SimpleTag sub-element of
1119     // the Atom into the stream.  Returns the SimpleTag element size on
1120     // success, 0 if error.
1121     uint64_t Write(IMkvWriter* writer) const;
1122 
1123    private:
1124     char* tag_name_;
1125     char* tag_string_;
1126   };
1127 
1128   Tag();
1129   ~Tag();
1130 
1131   // Copies this Tag object to a different one.  This is used when
1132   // expanding a plain array of Tag objects (see Tags).
1133   void ShallowCopy(Tag* dst) const;
1134 
1135   // Reclaim resources used by this Tag object, pending its
1136   // destruction.
1137   void Clear();
1138 
1139   // If there is no storage remaining on the |simple_tags_| array for a
1140   // new display object, creates a new, longer array and copies the
1141   // existing SimpleTag objects to the new array.  Returns false if the
1142   // array cannot be expanded.
1143   bool ExpandSimpleTagsArray();
1144 
1145   // If |writer| is non-NULL, serialize the Tag sub-element into the
1146   // stream.  Returns the total size of the element on success, 0 if
1147   // error.
1148   uint64_t Write(IMkvWriter* writer) const;
1149 
1150   // The Atom element can contain multiple SimpleTag sub-elements
1151   SimpleTag* simple_tags_;
1152 
1153   // The physical length (total size) of the |simple_tags_| array.
1154   int simple_tags_size_;
1155 
1156   // The logical length (number of active elements) on the |simple_tags_|
1157   // array.
1158   int simple_tags_count_;
1159 
1160   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag);
1161 };
1162 
1163 ///////////////////////////////////////////////////////////////
1164 // Tags element
1165 //
1166 class Tags {
1167  public:
1168   Tags();
1169   ~Tags();
1170 
1171   Tag* AddTag();
1172 
1173   // Returns the number of tags that have been added.
1174   int Count() const;
1175 
1176   // Output the Tags element to the writer. Returns true on success.
1177   bool Write(IMkvWriter* writer) const;
1178 
1179  private:
1180   // Expands the tags_ array if there is not enough space to contain
1181   // another tag object.  Returns true on success.
1182   bool ExpandTagsArray();
1183 
1184   // Total length of the tags_ array.
1185   int tags_size_;
1186 
1187   // Number of active tags on the tags_ array.
1188   int tags_count_;
1189 
1190   // Array for storage of tag objects.
1191   Tag* tags_;
1192 
1193   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags);
1194 };
1195 
1196 ///////////////////////////////////////////////////////////////
1197 // Cluster element
1198 //
1199 // Notes:
1200 //  |Init| must be called before any other method in this class.
1201 class Cluster {
1202  public:
1203   // |timecode| is the absolute timecode of the cluster. |cues_pos| is the
1204   // position for the cluster within the segment that should be written in
1205   // the cues element. |timecode_scale| is the timecode scale of the segment.
1206   Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
1207           bool write_last_frame_with_duration = false,
1208           bool fixed_size_timecode = false);
1209   ~Cluster();
1210 
1211   bool Init(IMkvWriter* ptr_writer);
1212 
1213   // Adds a frame to be output in the file. The frame is written out through
1214   // |writer_| if successful. Returns true on success.
1215   bool AddFrame(const Frame* frame);
1216 
1217   // Adds a frame to be output in the file. The frame is written out through
1218   // |writer_| if successful. Returns true on success.
1219   // Inputs:
1220   //   data: Pointer to the data
1221   //   length: Length of the data
1222   //   track_number: Track to add the data to. Value returned by Add track
1223   //                 functions.  The range of allowed values is [1, 126].
1224   //   timecode:     Absolute (not relative to cluster) timestamp of the
1225   //                 frame, expressed in timecode units.
1226   //   is_key:       Flag telling whether or not this frame is a key frame.
1227   bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number,
1228                 uint64_t timecode,  // timecode units (absolute)
1229                 bool is_key);
1230 
1231   // Adds a frame to be output in the file. The frame is written out through
1232   // |writer_| if successful. Returns true on success.
1233   // Inputs:
1234   //   data: Pointer to the data
1235   //   length: Length of the data
1236   //   additional: Pointer to the additional data
1237   //   additional_length: Length of the additional data
1238   //   add_id: Value of BlockAddID element
1239   //   track_number: Track to add the data to. Value returned by Add track
1240   //                 functions.  The range of allowed values is [1, 126].
1241   //   abs_timecode: Absolute (not relative to cluster) timestamp of the
1242   //                 frame, expressed in timecode units.
1243   //   is_key:       Flag telling whether or not this frame is a key frame.
1244   bool AddFrameWithAdditional(const uint8_t* data, uint64_t length,
1245                               const uint8_t* additional,
1246                               uint64_t additional_length, uint64_t add_id,
1247                               uint64_t track_number, uint64_t abs_timecode,
1248                               bool is_key);
1249 
1250   // Adds a frame to be output in the file. The frame is written out through
1251   // |writer_| if successful. Returns true on success.
1252   // Inputs:
1253   //   data: Pointer to the data.
1254   //   length: Length of the data.
1255   //   discard_padding: DiscardPadding element value.
1256   //   track_number: Track to add the data to. Value returned by Add track
1257   //                 functions.  The range of allowed values is [1, 126].
1258   //   abs_timecode: Absolute (not relative to cluster) timestamp of the
1259   //                 frame, expressed in timecode units.
1260   //   is_key:       Flag telling whether or not this frame is a key frame.
1261   bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
1262                                   int64_t discard_padding,
1263                                   uint64_t track_number, uint64_t abs_timecode,
1264                                   bool is_key);
1265 
1266   // Writes a frame of metadata to the output medium; returns true on
1267   // success.
1268   // Inputs:
1269   //   data: Pointer to the data
1270   //   length: Length of the data
1271   //   track_number: Track to add the data to. Value returned by Add track
1272   //                 functions.  The range of allowed values is [1, 126].
1273   //   timecode:     Absolute (not relative to cluster) timestamp of the
1274   //                 metadata frame, expressed in timecode units.
1275   //   duration:     Duration of metadata frame, in timecode units.
1276   //
1277   // The metadata frame is written as a block group, with a duration
1278   // sub-element but no reference time sub-elements (indicating that
1279   // it is considered a keyframe, per Matroska semantics).
1280   bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number,
1281                    uint64_t timecode, uint64_t duration);
1282 
1283   // Increments the size of the cluster's data in bytes.
1284   void AddPayloadSize(uint64_t size);
1285 
1286   // Closes the cluster so no more data can be written to it. Will update the
1287   // cluster's size if |writer_| is seekable. Returns true on success. This
1288   // variant of Finalize() fails when |write_last_frame_with_duration_| is set
1289   // to true.
1290   bool Finalize();
1291 
1292   // Closes the cluster so no more data can be written to it. Will update the
1293   // cluster's size if |writer_| is seekable. Returns true on success.
1294   // Inputs:
1295   //   set_last_frame_duration: Boolean indicating whether or not the duration
1296   //                            of the last frame should be set. If set to
1297   //                            false, the |duration| value is ignored and
1298   //                            |write_last_frame_with_duration_| will not be
1299   //                            honored.
1300   //   duration: Duration of the Cluster in timecode scale.
1301   bool Finalize(bool set_last_frame_duration, uint64_t duration);
1302 
1303   // Returns the size in bytes for the entire Cluster element.
1304   uint64_t Size() const;
1305 
1306   // Given |abs_timecode|, calculates timecode relative to most recent timecode.
1307   // Returns -1 on failure, or a relative timecode.
1308   int64_t GetRelativeTimecode(int64_t abs_timecode) const;
1309 
size_position()1310   int64_t size_position() const { return size_position_; }
blocks_added()1311   int32_t blocks_added() const { return blocks_added_; }
payload_size()1312   uint64_t payload_size() const { return payload_size_; }
position_for_cues()1313   int64_t position_for_cues() const { return position_for_cues_; }
timecode()1314   uint64_t timecode() const { return timecode_; }
timecode_scale()1315   uint64_t timecode_scale() const { return timecode_scale_; }
set_write_last_frame_with_duration(bool write_last_frame_with_duration)1316   void set_write_last_frame_with_duration(bool write_last_frame_with_duration) {
1317     write_last_frame_with_duration_ = write_last_frame_with_duration;
1318   }
write_last_frame_with_duration()1319   bool write_last_frame_with_duration() const {
1320     return write_last_frame_with_duration_;
1321   }
1322 
1323  private:
1324   // Iterator type for the |stored_frames_| map.
1325   typedef std::map<uint64_t, std::list<Frame*> >::iterator FrameMapIterator;
1326 
1327   // Utility method that confirms that blocks can still be added, and that the
1328   // cluster header has been written. Used by |DoWriteFrame*|. Returns true
1329   // when successful.
1330   bool PreWriteBlock();
1331 
1332   // Utility method used by the |DoWriteFrame*| methods that handles the book
1333   // keeping required after each block is written.
1334   void PostWriteBlock(uint64_t element_size);
1335 
1336   // Does some verification and calls WriteFrame.
1337   bool DoWriteFrame(const Frame* const frame);
1338 
1339   // Either holds back the given frame, or writes it out depending on whether or
1340   // not |write_last_frame_with_duration_| is set.
1341   bool QueueOrWriteFrame(const Frame* const frame);
1342 
1343   // Outputs the Cluster header to |writer_|. Returns true on success.
1344   bool WriteClusterHeader();
1345 
1346   // Number of blocks added to the cluster.
1347   int32_t blocks_added_;
1348 
1349   // Flag telling if the cluster has been closed.
1350   bool finalized_;
1351 
1352   // Flag indicating whether the cluster's timecode will always be written out
1353   // using 8 bytes.
1354   bool fixed_size_timecode_;
1355 
1356   // Flag telling if the cluster's header has been written.
1357   bool header_written_;
1358 
1359   // The size of the cluster elements in bytes.
1360   uint64_t payload_size_;
1361 
1362   // The file position used for cue points.
1363   const int64_t position_for_cues_;
1364 
1365   // The file position of the cluster's size element.
1366   int64_t size_position_;
1367 
1368   // The absolute timecode of the cluster.
1369   const uint64_t timecode_;
1370 
1371   // The timecode scale of the Segment containing the cluster.
1372   const uint64_t timecode_scale_;
1373 
1374   // Flag indicating whether the last frame of the cluster should be written as
1375   // a Block with Duration. If set to true, then it will result in holding back
1376   // of frames and the parameterized version of Finalize() must be called to
1377   // finish writing the Cluster.
1378   bool write_last_frame_with_duration_;
1379 
1380   // Map used to hold back frames, if required. Track number is the key.
1381   std::map<uint64_t, std::list<Frame*> > stored_frames_;
1382 
1383   // Map from track number to the timestamp of the last block written for that
1384   // track.
1385   std::map<uint64_t, uint64_t> last_block_timestamp_;
1386 
1387   // Pointer to the writer object. Not owned by this class.
1388   IMkvWriter* writer_;
1389 
1390   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster);
1391 };
1392 
1393 ///////////////////////////////////////////////////////////////
1394 // SeekHead element
1395 class SeekHead {
1396  public:
1397   SeekHead();
1398   ~SeekHead();
1399 
1400   // TODO(fgalligan): Change this to reserve a certain size. Then check how
1401   // big the seek entry to be added is as not every seek entry will be the
1402   // maximum size it could be.
1403   // Adds a seek entry to be written out when the element is finalized. |id|
1404   // must be the coded mkv element id. |pos| is the file position of the
1405   // element. Returns true on success.
1406   bool AddSeekEntry(uint32_t id, uint64_t pos);
1407 
1408   // Writes out SeekHead and SeekEntry elements. Returns true on success.
1409   bool Finalize(IMkvWriter* writer) const;
1410 
1411   // Returns the id of the Seek Entry at the given index. Returns -1 if index is
1412   // out of range.
1413   uint32_t GetId(int index) const;
1414 
1415   // Returns the position of the Seek Entry at the given index. Returns -1 if
1416   // index is out of range.
1417   uint64_t GetPosition(int index) const;
1418 
1419   // Sets the Seek Entry id and position at given index.
1420   // Returns true on success.
1421   bool SetSeekEntry(int index, uint32_t id, uint64_t position);
1422 
1423   // Reserves space by writing out a Void element which will be updated with
1424   // a SeekHead element later. Returns true on success.
1425   bool Write(IMkvWriter* writer);
1426 
1427   // We are going to put a cap on the number of Seek Entries.
1428   const static int32_t kSeekEntryCount = 5;
1429 
1430  private:
1431   // Returns the maximum size in bytes of one seek entry.
1432   uint64_t MaxEntrySize() const;
1433 
1434   // Seek entry id element list.
1435   uint32_t seek_entry_id_[kSeekEntryCount];
1436 
1437   // Seek entry pos element list.
1438   uint64_t seek_entry_pos_[kSeekEntryCount];
1439 
1440   // The file position of SeekHead element.
1441   int64_t start_pos_;
1442 
1443   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead);
1444 };
1445 
1446 ///////////////////////////////////////////////////////////////
1447 // Segment Information element
1448 class SegmentInfo {
1449  public:
1450   SegmentInfo();
1451   ~SegmentInfo();
1452 
1453   // Will update the duration if |duration_| is > 0.0. Returns true on success.
1454   bool Finalize(IMkvWriter* writer) const;
1455 
1456   // Sets |muxing_app_| and |writing_app_|.
1457   bool Init();
1458 
1459   // Output the Segment Information element to the writer. Returns true on
1460   // success.
1461   bool Write(IMkvWriter* writer);
1462 
set_duration(double duration)1463   void set_duration(double duration) { duration_ = duration; }
duration()1464   double duration() const { return duration_; }
1465   void set_muxing_app(const char* app);
muxing_app()1466   const char* muxing_app() const { return muxing_app_; }
set_timecode_scale(uint64_t scale)1467   void set_timecode_scale(uint64_t scale) { timecode_scale_ = scale; }
timecode_scale()1468   uint64_t timecode_scale() const { return timecode_scale_; }
1469   void set_writing_app(const char* app);
writing_app()1470   const char* writing_app() const { return writing_app_; }
set_date_utc(int64_t date_utc)1471   void set_date_utc(int64_t date_utc) { date_utc_ = date_utc; }
date_utc()1472   int64_t date_utc() const { return date_utc_; }
1473 
1474  private:
1475   // Segment Information element names.
1476   // Initially set to -1 to signify that a duration has not been set and should
1477   // not be written out.
1478   double duration_;
1479   // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
1480   char* muxing_app_;
1481   uint64_t timecode_scale_;
1482   // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision.
1483   char* writing_app_;
1484   // LLONG_MIN when DateUTC is not set.
1485   int64_t date_utc_;
1486 
1487   // The file position of the duration element.
1488   int64_t duration_pos_;
1489 
1490   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo);
1491 };
1492 
1493 ///////////////////////////////////////////////////////////////
1494 // This class represents the main segment in a WebM file. Currently only
1495 // supports one Segment element.
1496 //
1497 // Notes:
1498 //  |Init| must be called before any other method in this class.
1499 class Segment {
1500  public:
1501   enum Mode { kLive = 0x1, kFile = 0x2 };
1502 
1503   enum CuesPosition {
1504     kAfterClusters = 0x0,  // Position Cues after Clusters - Default
1505     kBeforeClusters = 0x1  // Position Cues before Clusters
1506   };
1507 
1508   static const uint32_t kDefaultDocTypeVersion = 4;
1509   static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL;
1510 
1511   Segment();
1512   ~Segment();
1513 
1514   // Initializes |SegmentInfo| and returns result. Always returns false when
1515   // |ptr_writer| is NULL.
1516   bool Init(IMkvWriter* ptr_writer);
1517 
1518   // Adds a generic track to the segment.  Returns the newly-allocated
1519   // track object (which is owned by the segment) on success, NULL on
1520   // error. |number| is the number to use for the track.  |number|
1521   // must be >= 0. If |number| == 0 then the muxer will decide on the
1522   // track number.
1523   Track* AddTrack(int32_t number);
1524 
1525   // Adds a Vorbis audio track to the segment. Returns the number of the track
1526   // on success, 0 on error. |number| is the number to use for the audio track.
1527   // |number| must be >= 0. If |number| == 0 then the muxer will decide on
1528   // the track number.
1529   uint64_t AddAudioTrack(int32_t sample_rate, int32_t channels, int32_t number);
1530 
1531   // Adds an empty chapter to the chapters of this segment.  Returns
1532   // non-NULL on success.  After adding the chapter, the caller should
1533   // populate its fields via the Chapter member functions.
1534   Chapter* AddChapter();
1535 
1536   // Adds an empty tag to the tags of this segment.  Returns
1537   // non-NULL on success.  After adding the tag, the caller should
1538   // populate its fields via the Tag member functions.
1539   Tag* AddTag();
1540 
1541   // Adds a cue point to the Cues element. |timestamp| is the time in
1542   // nanoseconds of the cue's time. |track| is the Track of the Cue. This
1543   // function must be called after AddFrame to calculate the correct
1544   // BlockNumber for the CuePoint. Returns true on success.
1545   bool AddCuePoint(uint64_t timestamp, uint64_t track);
1546 
1547   // Adds a frame to be output in the file. Returns true on success.
1548   // Inputs:
1549   //   data: Pointer to the data
1550   //   length: Length of the data
1551   //   track_number: Track to add the data to. Value returned by Add track
1552   //                 functions.
1553   //   timestamp:    Timestamp of the frame in nanoseconds from 0.
1554   //   is_key:       Flag telling whether or not this frame is a key frame.
1555   bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number,
1556                 uint64_t timestamp_ns, bool is_key);
1557 
1558   // Writes a frame of metadata to the output medium; returns true on
1559   // success.
1560   // Inputs:
1561   //   data: Pointer to the data
1562   //   length: Length of the data
1563   //   track_number: Track to add the data to. Value returned by Add track
1564   //                 functions.
1565   //   timecode:     Absolute timestamp of the metadata frame, expressed
1566   //                 in nanosecond units.
1567   //   duration:     Duration of metadata frame, in nanosecond units.
1568   //
1569   // The metadata frame is written as a block group, with a duration
1570   // sub-element but no reference time sub-elements (indicating that
1571   // it is considered a keyframe, per Matroska semantics).
1572   bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number,
1573                    uint64_t timestamp_ns, uint64_t duration_ns);
1574 
1575   // Writes a frame with additional data to the output medium; returns true on
1576   // success.
1577   // Inputs:
1578   //   data: Pointer to the data.
1579   //   length: Length of the data.
1580   //   additional: Pointer to additional data.
1581   //   additional_length: Length of additional data.
1582   //   add_id: Additional ID which identifies the type of additional data.
1583   //   track_number: Track to add the data to. Value returned by Add track
1584   //                 functions.
1585   //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond
1586   //                 units.
1587   //   is_key:       Flag telling whether or not this frame is a key frame.
1588   bool AddFrameWithAdditional(const uint8_t* data, uint64_t length,
1589                               const uint8_t* additional,
1590                               uint64_t additional_length, uint64_t add_id,
1591                               uint64_t track_number, uint64_t timestamp,
1592                               bool is_key);
1593 
1594   // Writes a frame with DiscardPadding to the output medium; returns true on
1595   // success.
1596   // Inputs:
1597   //   data: Pointer to the data.
1598   //   length: Length of the data.
1599   //   discard_padding: DiscardPadding element value.
1600   //   track_number: Track to add the data to. Value returned by Add track
1601   //                 functions.
1602   //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond
1603   //                 units.
1604   //   is_key:       Flag telling whether or not this frame is a key frame.
1605   bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
1606                                   int64_t discard_padding,
1607                                   uint64_t track_number, uint64_t timestamp,
1608                                   bool is_key);
1609 
1610   // Writes a Frame to the output medium. Chooses the correct way of writing
1611   // the frame (Block vs SimpleBlock) based on the parameters passed.
1612   // Inputs:
1613   //   frame: frame object
1614   bool AddGenericFrame(const Frame* frame);
1615 
1616   // Adds a VP8 video track to the segment. Returns the number of the track on
1617   // success, 0 on error. |number| is the number to use for the video track.
1618   // |number| must be >= 0. If |number| == 0 then the muxer will decide on
1619   // the track number.
1620   uint64_t AddVideoTrack(int32_t width, int32_t height, int32_t number);
1621 
1622   // This function must be called after Finalize() if you need a copy of the
1623   // output with Cues written before the Clusters. It will return false if the
1624   // writer is not seekable of if chunking is set to true.
1625   // Input parameters:
1626   // reader - an IMkvReader object created with the same underlying file of the
1627   //          current writer object. Make sure to close the existing writer
1628   //          object before creating this so that all the data is properly
1629   //          flushed and available for reading.
1630   // writer - an IMkvWriter object pointing to a *different* file than the one
1631   //          pointed by the current writer object. This file will contain the
1632   //          Cues element before the Clusters.
1633   bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
1634                                      IMkvWriter* writer);
1635 
1636   // Sets which track to use for the Cues element. Must have added the track
1637   // before calling this function. Returns true on success. |track_number| is
1638   // returned by the Add track functions.
1639   bool CuesTrack(uint64_t track_number);
1640 
1641   // This will force the muxer to create a new Cluster when the next frame is
1642   // added.
1643   void ForceNewClusterOnNextFrame();
1644 
1645   // Writes out any frames that have not been written out. Finalizes the last
1646   // cluster. May update the size and duration of the segment. May output the
1647   // Cues element. May finalize the SeekHead element. Returns true on success.
1648   bool Finalize();
1649 
1650   // Returns the Cues object.
GetCues()1651   Cues* GetCues() { return &cues_; }
1652 
1653   // Returns the Segment Information object.
GetSegmentInfo()1654   const SegmentInfo* GetSegmentInfo() const { return &segment_info_; }
GetSegmentInfo()1655   SegmentInfo* GetSegmentInfo() { return &segment_info_; }
1656 
1657   // Search the Tracks and return the track that matches |track_number|.
1658   // Returns NULL if there is no track match.
1659   Track* GetTrackByNumber(uint64_t track_number) const;
1660 
1661   // Toggles whether to output a cues element.
1662   void OutputCues(bool output_cues);
1663 
1664   // Toggles whether to write the last frame in each Cluster with Duration.
1665   void AccurateClusterDuration(bool accurate_cluster_duration);
1666 
1667   // Toggles whether to write the Cluster Timecode using exactly 8 bytes.
1668   void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode);
1669 
1670   // Sets if the muxer will output files in chunks or not. |chunking| is a
1671   // flag telling whether or not to turn on chunking. |filename| is the base
1672   // filename for the chunk files. The header chunk file will be named
1673   // |filename|.hdr and the data chunks will be named
1674   // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing
1675   // to files so the muxer will use the default MkvWriter class to control
1676   // what data is written to what files. Returns true on success.
1677   // TODO: Should we change the IMkvWriter Interface to add Open and Close?
1678   // That will force the interface to be dependent on files.
1679   bool SetChunking(bool chunking, const char* filename);
1680 
chunking()1681   bool chunking() const { return chunking_; }
cues_track()1682   uint64_t cues_track() const { return cues_track_; }
set_max_cluster_duration(uint64_t max_cluster_duration)1683   void set_max_cluster_duration(uint64_t max_cluster_duration) {
1684     max_cluster_duration_ = max_cluster_duration;
1685   }
max_cluster_duration()1686   uint64_t max_cluster_duration() const { return max_cluster_duration_; }
set_max_cluster_size(uint64_t max_cluster_size)1687   void set_max_cluster_size(uint64_t max_cluster_size) {
1688     max_cluster_size_ = max_cluster_size;
1689   }
max_cluster_size()1690   uint64_t max_cluster_size() const { return max_cluster_size_; }
set_mode(Mode mode)1691   void set_mode(Mode mode) { mode_ = mode; }
mode()1692   Mode mode() const { return mode_; }
cues_position()1693   CuesPosition cues_position() const { return cues_position_; }
output_cues()1694   bool output_cues() const { return output_cues_; }
set_estimate_file_duration(bool estimate_duration)1695   void set_estimate_file_duration(bool estimate_duration) {
1696     estimate_file_duration_ = estimate_duration;
1697   }
estimate_file_duration()1698   bool estimate_file_duration() const { return estimate_file_duration_; }
segment_info()1699   const SegmentInfo* segment_info() const { return &segment_info_; }
set_duration(double duration)1700   void set_duration(double duration) { duration_ = duration; }
duration()1701   double duration() const { return duration_; }
1702 
1703   // Returns true when codec IDs are valid for WebM.
1704   bool DocTypeIsWebm() const;
1705 
1706  private:
1707   // Checks if header information has been output and initialized. If not it
1708   // will output the Segment element and initialize the SeekHead elment and
1709   // Cues elements.
1710   bool CheckHeaderInfo();
1711 
1712   // Sets |doc_type_version_| based on the current element requirements.
1713   void UpdateDocTypeVersion();
1714 
1715   // Sets |name| according to how many chunks have been written. |ext| is the
1716   // file extension. |name| must be deleted by the calling app. Returns true
1717   // on success.
1718   bool UpdateChunkName(const char* ext, char** name) const;
1719 
1720   // Returns the maximum offset within the segment's payload. When chunking
1721   // this function is needed to determine offsets of elements within the
1722   // chunked files. Returns -1 on error.
1723   int64_t MaxOffset();
1724 
1725   // Adds the frame to our frame array.
1726   bool QueueFrame(Frame* frame);
1727 
1728   // Output all frames that are queued. Returns -1 on error, otherwise
1729   // it returns the number of frames written.
1730   int WriteFramesAll();
1731 
1732   // Output all frames that are queued that have an end time that is less
1733   // then |timestamp|. Returns true on success and if there are no frames
1734   // queued.
1735   bool WriteFramesLessThan(uint64_t timestamp);
1736 
1737   // Outputs the segment header, Segment Information element, SeekHead element,
1738   // and Tracks element to |writer_|.
1739   bool WriteSegmentHeader();
1740 
1741   // Given a frame with the specified timestamp (nanosecond units) and
1742   // keyframe status, determine whether a new cluster should be
1743   // created, before writing enqueued frames and the frame itself. The
1744   // function returns one of the following values:
1745   //  -1 = error: an out-of-order frame was detected
1746   //  0 = do not create a new cluster, and write frame to the existing cluster
1747   //  1 = create a new cluster, and write frame to that new cluster
1748   //  2 = create a new cluster, and re-run test
1749   int TestFrame(uint64_t track_num, uint64_t timestamp_ns, bool key) const;
1750 
1751   // Create a new cluster, using the earlier of the first enqueued
1752   // frame, or the indicated time. Returns true on success.
1753   bool MakeNewCluster(uint64_t timestamp_ns);
1754 
1755   // Checks whether a new cluster needs to be created, and if so
1756   // creates a new cluster. Returns false if creation of a new cluster
1757   // was necessary but creation was not successful.
1758   bool DoNewClusterProcessing(uint64_t track_num, uint64_t timestamp_ns,
1759                               bool key);
1760 
1761   // Adjusts Cue Point values (to place Cues before Clusters) so that they
1762   // reflect the correct offsets.
1763   void MoveCuesBeforeClusters();
1764 
1765   // This function recursively computes the correct cluster offsets (this is
1766   // done to move the Cues before Clusters). It recursively updates the change
1767   // in size (which indicates a change in cluster offset) until no sizes change.
1768   // Parameters:
1769   // diff - indicates the difference in size of the Cues element that needs to
1770   //        accounted for.
1771   // index - index in the list of Cues which is currently being adjusted.
1772   // cue_size - sum of size of all the CuePoint elements.
1773   void MoveCuesBeforeClustersHelper(uint64_t diff, int index,
1774                                     uint64_t* cue_size);
1775 
1776   // Seeds the random number generator used to make UIDs.
1777   unsigned int seed_;
1778 
1779   // WebM elements
1780   Cues cues_;
1781   SeekHead seek_head_;
1782   SegmentInfo segment_info_;
1783   Tracks tracks_;
1784   Chapters chapters_;
1785   Tags tags_;
1786 
1787   // Number of chunks written.
1788   int chunk_count_;
1789 
1790   // Current chunk filename.
1791   char* chunk_name_;
1792 
1793   // Default MkvWriter object created by this class used for writing clusters
1794   // out in separate files.
1795   MkvWriter* chunk_writer_cluster_;
1796 
1797   // Default MkvWriter object created by this class used for writing Cues
1798   // element out to a file.
1799   MkvWriter* chunk_writer_cues_;
1800 
1801   // Default MkvWriter object created by this class used for writing the
1802   // Matroska header out to a file.
1803   MkvWriter* chunk_writer_header_;
1804 
1805   // Flag telling whether or not the muxer is chunking output to multiple
1806   // files.
1807   bool chunking_;
1808 
1809   // Base filename for the chunked files.
1810   char* chunking_base_name_;
1811 
1812   // File position offset where the Clusters end.
1813   int64_t cluster_end_offset_;
1814 
1815   // List of clusters.
1816   Cluster** cluster_list_;
1817 
1818   // Number of cluster pointers allocated in the cluster list.
1819   int32_t cluster_list_capacity_;
1820 
1821   // Number of clusters in the cluster list.
1822   int32_t cluster_list_size_;
1823 
1824   // Indicates whether Cues should be written before or after Clusters
1825   CuesPosition cues_position_;
1826 
1827   // Track number that is associated with the cues element for this segment.
1828   uint64_t cues_track_;
1829 
1830   // Tells the muxer to force a new cluster on the next Block.
1831   bool force_new_cluster_;
1832 
1833   // List of stored audio frames. These variables are used to store frames so
1834   // the muxer can follow the guideline "Audio blocks that contain the video
1835   // key frame's timecode should be in the same cluster as the video key frame
1836   // block."
1837   Frame** frames_;
1838 
1839   // Number of frame pointers allocated in the frame list.
1840   int32_t frames_capacity_;
1841 
1842   // Number of frames in the frame list.
1843   int32_t frames_size_;
1844 
1845   // Flag telling if a video track has been added to the segment.
1846   bool has_video_;
1847 
1848   // Flag telling if the segment's header has been written.
1849   bool header_written_;
1850 
1851   // Duration of the last block in nanoseconds.
1852   uint64_t last_block_duration_;
1853 
1854   // Last timestamp in nanoseconds added to a cluster.
1855   uint64_t last_timestamp_;
1856 
1857   // Last timestamp in nanoseconds by track number added to a cluster.
1858   uint64_t last_track_timestamp_[kMaxTrackNumber];
1859 
1860   // Number of frames written per track.
1861   uint64_t track_frames_written_[kMaxTrackNumber];
1862 
1863   // Maximum time in nanoseconds for a cluster duration. This variable is a
1864   // guideline and some clusters may have a longer duration. Default is 30
1865   // seconds.
1866   uint64_t max_cluster_duration_;
1867 
1868   // Maximum size in bytes for a cluster. This variable is a guideline and
1869   // some clusters may have a larger size. Default is 0 which signifies that
1870   // the muxer will decide the size.
1871   uint64_t max_cluster_size_;
1872 
1873   // The mode that segment is in. If set to |kLive| the writer must not
1874   // seek backwards.
1875   Mode mode_;
1876 
1877   // Flag telling the muxer that a new cue point should be added.
1878   bool new_cuepoint_;
1879 
1880   // TODO(fgalligan): Should we add support for more than one Cues element?
1881   // Flag whether or not the muxer should output a Cues element.
1882   bool output_cues_;
1883 
1884   // Flag whether or not the last frame in each Cluster will have a Duration
1885   // element in it.
1886   bool accurate_cluster_duration_;
1887 
1888   // Flag whether or not to write the Cluster Timecode using exactly 8 bytes.
1889   bool fixed_size_cluster_timecode_;
1890 
1891   // Flag whether or not to estimate the file duration.
1892   bool estimate_file_duration_;
1893 
1894   // The size of the EBML header, used to validate the header if
1895   // WriteEbmlHeader() is called more than once.
1896   int32_t ebml_header_size_;
1897 
1898   // The file position of the segment's payload.
1899   int64_t payload_pos_;
1900 
1901   // The file position of the element's size.
1902   int64_t size_position_;
1903 
1904   // Current DocTypeVersion (|doc_type_version_|) and that written in
1905   // WriteSegmentHeader().
1906   // WriteEbmlHeader() will be called from Finalize() if |doc_type_version_|
1907   // differs from |doc_type_version_written_|.
1908   uint32_t doc_type_version_;
1909   uint32_t doc_type_version_written_;
1910 
1911   // If |duration_| is > 0, then explicitly set the duration of the segment.
1912   double duration_;
1913 
1914   // Pointer to the writer objects. Not owned by this class.
1915   IMkvWriter* writer_cluster_;
1916   IMkvWriter* writer_cues_;
1917   IMkvWriter* writer_header_;
1918 
1919   LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment);
1920 };
1921 
1922 }  // namespace mkvmuxer
1923 
1924 #endif  // MKVMUXER_MKVMUXER_H_
1925