|  | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 
|  | // | 
|  | // Use of this source code is governed by a BSD-style license | 
|  | // that can be found in the LICENSE file in the root of the source | 
|  | // tree. An additional intellectual property rights grant can be found | 
|  | // in the file PATENTS.  All contributing project authors may | 
|  | // be found in the AUTHORS file in the root of the source tree. | 
|  |  | 
|  | #ifndef MKVMUXER_MKVMUXER_H_ | 
|  | #define MKVMUXER_MKVMUXER_H_ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <list> | 
|  | #include <map> | 
|  |  | 
|  | #include "common/webmids.h" | 
|  | #include "mkvmuxer/mkvmuxertypes.h" | 
|  |  | 
|  | // For a description of the WebM elements see | 
|  | // http://www.webmproject.org/code/specs/container/. | 
|  |  | 
|  | namespace mkvparser { | 
|  | class IMkvReader; | 
|  | }  // namespace mkvparser | 
|  |  | 
|  | namespace mkvmuxer { | 
|  |  | 
|  | class MkvWriter; | 
|  | class Segment; | 
|  |  | 
|  | const uint64_t kMaxTrackNumber = 126; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Interface used by the mkvmuxer to write out the Mkv data. | 
|  | class IMkvWriter { | 
|  | public: | 
|  | // Writes out |len| bytes of |buf|. Returns 0 on success. | 
|  | virtual int32 Write(const void* buf, uint32 len) = 0; | 
|  |  | 
|  | // Returns the offset of the output position from the beginning of the | 
|  | // output. | 
|  | virtual int64 Position() const = 0; | 
|  |  | 
|  | // Set the current File position. Returns 0 on success. | 
|  | virtual int32 Position(int64 position) = 0; | 
|  |  | 
|  | // Returns true if the writer is seekable. | 
|  | virtual bool Seekable() const = 0; | 
|  |  | 
|  | // Element start notification. Called whenever an element identifier is about | 
|  | // to be written to the stream. |element_id| is the element identifier, and | 
|  | // |position| is the location in the WebM stream where the first octet of the | 
|  | // element identifier will be written. | 
|  | // Note: the |MkvId| enumeration in webmids.hpp defines element values. | 
|  | virtual void ElementStartNotify(uint64 element_id, int64 position) = 0; | 
|  |  | 
|  | protected: | 
|  | IMkvWriter(); | 
|  | virtual ~IMkvWriter(); | 
|  |  | 
|  | private: | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter); | 
|  | }; | 
|  |  | 
|  | // Writes out the EBML header for a WebM file, but allows caller to specify | 
|  | // DocType. This function must be called before any other libwebm writing | 
|  | // functions are called. | 
|  | bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version, | 
|  | const char* const doc_type); | 
|  |  | 
|  | // Writes out the EBML header for a WebM file. This function must be called | 
|  | // before any other libwebm writing functions are called. | 
|  | bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version); | 
|  |  | 
|  | // Deprecated. Writes out EBML header with doc_type_version as | 
|  | // kDefaultDocTypeVersion. Exists for backward compatibility. | 
|  | bool WriteEbmlHeader(IMkvWriter* writer); | 
|  |  | 
|  | // Copies in Chunk from source to destination between the given byte positions | 
|  | bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, int64_t start, | 
|  | int64_t size); | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Class to hold data the will be written to a block. | 
|  | class Frame { | 
|  | public: | 
|  | Frame(); | 
|  | ~Frame(); | 
|  |  | 
|  | // Sets this frame's contents based on |frame|. Returns true on success. On | 
|  | // failure, this frame's existing contents may be lost. | 
|  | bool CopyFrom(const Frame& frame); | 
|  |  | 
|  | // Copies |frame| data into |frame_|. Returns true on success. | 
|  | bool Init(const uint8_t* frame, uint64_t length); | 
|  |  | 
|  | // Copies |additional| data into |additional_|. Returns true on success. | 
|  | bool AddAdditionalData(const uint8_t* additional, uint64_t length, | 
|  | uint64_t add_id); | 
|  |  | 
|  | // Returns true if the frame has valid parameters. | 
|  | bool IsValid() const; | 
|  |  | 
|  | // Returns true if the frame can be written as a SimpleBlock based on current | 
|  | // parameters. | 
|  | bool CanBeSimpleBlock() const; | 
|  |  | 
|  | uint64_t add_id() const { return add_id_; } | 
|  | const uint8_t* additional() const { return additional_; } | 
|  | uint64_t additional_length() const { return additional_length_; } | 
|  | void set_duration(uint64_t duration); | 
|  | uint64_t duration() const { return duration_; } | 
|  | bool duration_set() const { return duration_set_; } | 
|  | const uint8_t* frame() const { return frame_; } | 
|  | void set_is_key(bool key) { is_key_ = key; } | 
|  | bool is_key() const { return is_key_; } | 
|  | uint64_t length() const { return length_; } | 
|  | void set_track_number(uint64_t track_number) { track_number_ = track_number; } | 
|  | uint64_t track_number() const { return track_number_; } | 
|  | void set_timestamp(uint64_t timestamp) { timestamp_ = timestamp; } | 
|  | uint64_t timestamp() const { return timestamp_; } | 
|  | void set_discard_padding(int64_t discard_padding) { | 
|  | discard_padding_ = discard_padding; | 
|  | } | 
|  | int64_t discard_padding() const { return discard_padding_; } | 
|  | void set_reference_block_timestamp(int64_t reference_block_timestamp); | 
|  | int64_t reference_block_timestamp() const { | 
|  | return reference_block_timestamp_; | 
|  | } | 
|  | bool reference_block_timestamp_set() const { | 
|  | return reference_block_timestamp_set_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Id of the Additional data. | 
|  | uint64_t add_id_; | 
|  |  | 
|  | // Pointer to additional data. Owned by this class. | 
|  | uint8_t* additional_; | 
|  |  | 
|  | // Length of the additional data. | 
|  | uint64_t additional_length_; | 
|  |  | 
|  | // Duration of the frame in nanoseconds. | 
|  | uint64_t duration_; | 
|  |  | 
|  | // Flag indicating that |duration_| has been set. Setting duration causes the | 
|  | // frame to be written out as a Block with BlockDuration instead of as a | 
|  | // SimpleBlock. | 
|  | bool duration_set_; | 
|  |  | 
|  | // Pointer to the data. Owned by this class. | 
|  | uint8_t* frame_; | 
|  |  | 
|  | // Flag telling if the data should set the key flag of a block. | 
|  | bool is_key_; | 
|  |  | 
|  | // Length of the data. | 
|  | uint64_t length_; | 
|  |  | 
|  | // Mkv track number the data is associated with. | 
|  | uint64_t track_number_; | 
|  |  | 
|  | // Timestamp of the data in nanoseconds. | 
|  | uint64_t timestamp_; | 
|  |  | 
|  | // Discard padding for the frame. | 
|  | int64_t discard_padding_; | 
|  |  | 
|  | // Reference block timestamp. | 
|  | int64_t reference_block_timestamp_; | 
|  |  | 
|  | // Flag indicating if |reference_block_timestamp_| has been set. | 
|  | bool reference_block_timestamp_set_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Frame); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Class to hold one cue point in a Cues element. | 
|  | class CuePoint { | 
|  | public: | 
|  | CuePoint(); | 
|  | ~CuePoint(); | 
|  |  | 
|  | // Returns the size in bytes for the entire CuePoint element. | 
|  | uint64_t Size() const; | 
|  |  | 
|  | // Output the CuePoint element to the writer. Returns true on success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | void set_time(uint64_t time) { time_ = time; } | 
|  | uint64_t time() const { return time_; } | 
|  | void set_track(uint64_t track) { track_ = track; } | 
|  | uint64_t track() const { return track_; } | 
|  | void set_cluster_pos(uint64_t cluster_pos) { cluster_pos_ = cluster_pos; } | 
|  | uint64_t cluster_pos() const { return cluster_pos_; } | 
|  | void set_block_number(uint64_t block_number) { block_number_ = block_number; } | 
|  | uint64_t block_number() const { return block_number_; } | 
|  | void set_output_block_number(bool output_block_number) { | 
|  | output_block_number_ = output_block_number; | 
|  | } | 
|  | bool output_block_number() const { return output_block_number_; } | 
|  |  | 
|  | private: | 
|  | // Returns the size in bytes for the payload of the CuePoint element. | 
|  | uint64_t PayloadSize() const; | 
|  |  | 
|  | // Absolute timecode according to the segment time base. | 
|  | uint64_t time_; | 
|  |  | 
|  | // The Track element associated with the CuePoint. | 
|  | uint64_t track_; | 
|  |  | 
|  | // The position of the Cluster containing the Block. | 
|  | uint64_t cluster_pos_; | 
|  |  | 
|  | // Number of the Block within the Cluster, starting from 1. | 
|  | uint64_t block_number_; | 
|  |  | 
|  | // If true the muxer will write out the block number for the cue if the | 
|  | // block number is different than the default of 1. Default is set to true. | 
|  | bool output_block_number_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(CuePoint); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Cues element. | 
|  | class Cues { | 
|  | public: | 
|  | Cues(); | 
|  | ~Cues(); | 
|  |  | 
|  | // Adds a cue point to the Cues element. Returns true on success. | 
|  | bool AddCue(CuePoint* cue); | 
|  |  | 
|  | // Returns the cue point by index. Returns NULL if there is no cue point | 
|  | // match. | 
|  | CuePoint* GetCueByIndex(int32_t index) const; | 
|  |  | 
|  | // Returns the total size of the Cues element | 
|  | uint64_t Size(); | 
|  |  | 
|  | // Output the Cues element to the writer. Returns true on success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | int32_t cue_entries_size() const { return cue_entries_size_; } | 
|  | void set_output_block_number(bool output_block_number) { | 
|  | output_block_number_ = output_block_number; | 
|  | } | 
|  | bool output_block_number() const { return output_block_number_; } | 
|  |  | 
|  | private: | 
|  | // Number of allocated elements in |cue_entries_|. | 
|  | int32_t cue_entries_capacity_; | 
|  |  | 
|  | // Number of CuePoints in |cue_entries_|. | 
|  | int32_t cue_entries_size_; | 
|  |  | 
|  | // CuePoint list. | 
|  | CuePoint** cue_entries_; | 
|  |  | 
|  | // If true the muxer will write out the block number for the cue if the | 
|  | // block number is different than the default of 1. Default is set to true. | 
|  | bool output_block_number_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cues); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // ContentEncAESSettings element | 
|  | class ContentEncAESSettings { | 
|  | public: | 
|  | enum { kCTR = 1 }; | 
|  |  | 
|  | ContentEncAESSettings(); | 
|  | ~ContentEncAESSettings() {} | 
|  |  | 
|  | // Returns the size in bytes for the ContentEncAESSettings element. | 
|  | uint64_t Size() const; | 
|  |  | 
|  | // Writes out the ContentEncAESSettings element to |writer|. Returns true on | 
|  | // success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | uint64_t cipher_mode() const { return cipher_mode_; } | 
|  |  | 
|  | private: | 
|  | // Returns the size in bytes for the payload of the ContentEncAESSettings | 
|  | // element. | 
|  | uint64_t PayloadSize() const; | 
|  |  | 
|  | // Sub elements | 
|  | uint64_t cipher_mode_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncAESSettings); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // ContentEncoding element | 
|  | // Elements used to describe if the track data has been encrypted or | 
|  | // compressed with zlib or header stripping. | 
|  | // Currently only whole frames can be encrypted with AES. This dictates that | 
|  | // ContentEncodingOrder will be 0, ContentEncodingScope will be 1, | 
|  | // ContentEncodingType will be 1, and ContentEncAlgo will be 5. | 
|  | class ContentEncoding { | 
|  | public: | 
|  | ContentEncoding(); | 
|  | ~ContentEncoding(); | 
|  |  | 
|  | // Sets the content encryption id. Copies |length| bytes from |id| to | 
|  | // |enc_key_id_|. Returns true on success. | 
|  | bool SetEncryptionID(const uint8_t* id, uint64_t length); | 
|  |  | 
|  | // Returns the size in bytes for the ContentEncoding element. | 
|  | uint64_t Size() const; | 
|  |  | 
|  | // Writes out the ContentEncoding element to |writer|. Returns true on | 
|  | // success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | uint64_t enc_algo() const { return enc_algo_; } | 
|  | uint64_t encoding_order() const { return encoding_order_; } | 
|  | uint64_t encoding_scope() const { return encoding_scope_; } | 
|  | uint64_t encoding_type() const { return encoding_type_; } | 
|  | ContentEncAESSettings* enc_aes_settings() { return &enc_aes_settings_; } | 
|  |  | 
|  | private: | 
|  | // Returns the size in bytes for the encoding elements. | 
|  | uint64_t EncodingSize(uint64_t compresion_size, | 
|  | uint64_t encryption_size) const; | 
|  |  | 
|  | // Returns the size in bytes for the encryption elements. | 
|  | uint64_t EncryptionSize() const; | 
|  |  | 
|  | // Track element names | 
|  | uint64_t enc_algo_; | 
|  | uint8_t* enc_key_id_; | 
|  | uint64_t encoding_order_; | 
|  | uint64_t encoding_scope_; | 
|  | uint64_t encoding_type_; | 
|  |  | 
|  | // ContentEncAESSettings element. | 
|  | ContentEncAESSettings enc_aes_settings_; | 
|  |  | 
|  | // Size of the ContentEncKeyID data in bytes. | 
|  | uint64_t enc_key_id_length_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Colour element. | 
|  | class PrimaryChromaticity { | 
|  | public: | 
|  | static const float kChromaticityMin; | 
|  | static const float kChromaticityMax; | 
|  |  | 
|  | PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {} | 
|  | PrimaryChromaticity() : x_(0), y_(0) {} | 
|  | ~PrimaryChromaticity() {} | 
|  |  | 
|  | // Returns sum of |x_id| and |y_id| element id sizes and payload sizes. | 
|  | uint64_t PrimaryChromaticitySize(libwebm::MkvId x_id, | 
|  | libwebm::MkvId y_id) const; | 
|  | bool Valid() const; | 
|  | bool Write(IMkvWriter* writer, libwebm::MkvId x_id, | 
|  | libwebm::MkvId y_id) const; | 
|  |  | 
|  | float x() const { return x_; } | 
|  | void set_x(float new_x) { x_ = new_x; } | 
|  | float y() const { return y_; } | 
|  | void set_y(float new_y) { y_ = new_y; } | 
|  |  | 
|  | private: | 
|  | float x_; | 
|  | float y_; | 
|  | }; | 
|  |  | 
|  | class MasteringMetadata { | 
|  | public: | 
|  | static const float kValueNotPresent; | 
|  | static const float kMinLuminance; | 
|  | static const float kMinLuminanceMax; | 
|  | static const float kMaxLuminanceMax; | 
|  |  | 
|  | MasteringMetadata() | 
|  | : luminance_max_(kValueNotPresent), | 
|  | luminance_min_(kValueNotPresent), | 
|  | r_(NULL), | 
|  | g_(NULL), | 
|  | b_(NULL), | 
|  | white_point_(NULL) {} | 
|  | ~MasteringMetadata() { | 
|  | delete r_; | 
|  | delete g_; | 
|  | delete b_; | 
|  | delete white_point_; | 
|  | } | 
|  |  | 
|  | // Returns total size of the MasteringMetadata element. | 
|  | uint64_t MasteringMetadataSize() const; | 
|  | bool Valid() const; | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | // Copies non-null chromaticity. | 
|  | bool SetChromaticity(const PrimaryChromaticity* r, | 
|  | const PrimaryChromaticity* g, | 
|  | const PrimaryChromaticity* b, | 
|  | const PrimaryChromaticity* white_point); | 
|  | const PrimaryChromaticity* r() const { return r_; } | 
|  | const PrimaryChromaticity* g() const { return g_; } | 
|  | const PrimaryChromaticity* b() const { return b_; } | 
|  | const PrimaryChromaticity* white_point() const { return white_point_; } | 
|  |  | 
|  | float luminance_max() const { return luminance_max_; } | 
|  | void set_luminance_max(float luminance_max) { | 
|  | luminance_max_ = luminance_max; | 
|  | } | 
|  | float luminance_min() const { return luminance_min_; } | 
|  | void set_luminance_min(float luminance_min) { | 
|  | luminance_min_ = luminance_min; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Returns size of MasteringMetadata child elements. | 
|  | uint64_t PayloadSize() const; | 
|  |  | 
|  | float luminance_max_; | 
|  | float luminance_min_; | 
|  | PrimaryChromaticity* r_; | 
|  | PrimaryChromaticity* g_; | 
|  | PrimaryChromaticity* b_; | 
|  | PrimaryChromaticity* white_point_; | 
|  | }; | 
|  |  | 
|  | class Colour { | 
|  | public: | 
|  | enum MatrixCoefficients { | 
|  | kGbr = 0, | 
|  | kBt709 = 1, | 
|  | kUnspecifiedMc = 2, | 
|  | kReserved = 3, | 
|  | kFcc = 4, | 
|  | kBt470bg = 5, | 
|  | kSmpte170MMc = 6, | 
|  | kSmpte240MMc = 7, | 
|  | kYcocg = 8, | 
|  | kBt2020NonConstantLuminance = 9, | 
|  | kBt2020ConstantLuminance = 10, | 
|  | }; | 
|  | enum ChromaSitingHorz { | 
|  | kUnspecifiedCsh = 0, | 
|  | kLeftCollocated = 1, | 
|  | kHalfCsh = 2, | 
|  | }; | 
|  | enum ChromaSitingVert { | 
|  | kUnspecifiedCsv = 0, | 
|  | kTopCollocated = 1, | 
|  | kHalfCsv = 2, | 
|  | }; | 
|  | enum Range { | 
|  | kUnspecifiedCr = 0, | 
|  | kBroadcastRange = 1, | 
|  | kFullRange = 2, | 
|  | kMcTcDefined = 3,  // Defined by MatrixCoefficients/TransferCharacteristics. | 
|  | }; | 
|  | enum TransferCharacteristics { | 
|  | kIturBt709Tc = 1, | 
|  | kUnspecifiedTc = 2, | 
|  | kReservedTc = 3, | 
|  | kGamma22Curve = 4, | 
|  | kGamma28Curve = 5, | 
|  | kSmpte170MTc = 6, | 
|  | kSmpte240MTc = 7, | 
|  | kLinear = 8, | 
|  | kLog = 9, | 
|  | kLogSqrt = 10, | 
|  | kIec6196624 = 11, | 
|  | kIturBt1361ExtendedColourGamut = 12, | 
|  | kIec6196621 = 13, | 
|  | kIturBt202010bit = 14, | 
|  | kIturBt202012bit = 15, | 
|  | kSmpteSt2084 = 16, | 
|  | kSmpteSt4281Tc = 17, | 
|  | kAribStdB67Hlg = 18, | 
|  | }; | 
|  | enum Primaries { | 
|  | kReservedP0 = 0, | 
|  | kIturBt709P = 1, | 
|  | kUnspecifiedP = 2, | 
|  | kReservedP3 = 3, | 
|  | kIturBt470M = 4, | 
|  | kIturBt470Bg = 5, | 
|  | kSmpte170MP = 6, | 
|  | kSmpte240MP = 7, | 
|  | kFilm = 8, | 
|  | kIturBt2020 = 9, | 
|  | kSmpteSt4281P = 10, | 
|  | kJedecP22Phosphors = 22, | 
|  | }; | 
|  | static const uint64_t kValueNotPresent; | 
|  | Colour() | 
|  | : matrix_coefficients_(kValueNotPresent), | 
|  | bits_per_channel_(kValueNotPresent), | 
|  | chroma_subsampling_horz_(kValueNotPresent), | 
|  | chroma_subsampling_vert_(kValueNotPresent), | 
|  | cb_subsampling_horz_(kValueNotPresent), | 
|  | cb_subsampling_vert_(kValueNotPresent), | 
|  | chroma_siting_horz_(kValueNotPresent), | 
|  | chroma_siting_vert_(kValueNotPresent), | 
|  | range_(kValueNotPresent), | 
|  | transfer_characteristics_(kValueNotPresent), | 
|  | primaries_(kValueNotPresent), | 
|  | max_cll_(kValueNotPresent), | 
|  | max_fall_(kValueNotPresent), | 
|  | mastering_metadata_(NULL) {} | 
|  | ~Colour() { delete mastering_metadata_; } | 
|  |  | 
|  | // Returns total size of the Colour element. | 
|  | uint64_t ColourSize() const; | 
|  | bool Valid() const; | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | // Deep copies |mastering_metadata|. | 
|  | bool SetMasteringMetadata(const MasteringMetadata& mastering_metadata); | 
|  |  | 
|  | const MasteringMetadata* mastering_metadata() const { | 
|  | return mastering_metadata_; | 
|  | } | 
|  |  | 
|  | uint64_t matrix_coefficients() const { return matrix_coefficients_; } | 
|  | void set_matrix_coefficients(uint64_t matrix_coefficients) { | 
|  | matrix_coefficients_ = matrix_coefficients; | 
|  | } | 
|  | uint64_t bits_per_channel() const { return bits_per_channel_; } | 
|  | void set_bits_per_channel(uint64_t bits_per_channel) { | 
|  | bits_per_channel_ = bits_per_channel; | 
|  | } | 
|  | uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; } | 
|  | void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) { | 
|  | chroma_subsampling_horz_ = chroma_subsampling_horz; | 
|  | } | 
|  | uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; } | 
|  | void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) { | 
|  | chroma_subsampling_vert_ = chroma_subsampling_vert; | 
|  | } | 
|  | uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; } | 
|  | void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) { | 
|  | cb_subsampling_horz_ = cb_subsampling_horz; | 
|  | } | 
|  | uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; } | 
|  | void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) { | 
|  | cb_subsampling_vert_ = cb_subsampling_vert; | 
|  | } | 
|  | uint64_t chroma_siting_horz() const { return chroma_siting_horz_; } | 
|  | void set_chroma_siting_horz(uint64_t chroma_siting_horz) { | 
|  | chroma_siting_horz_ = chroma_siting_horz; | 
|  | } | 
|  | uint64_t chroma_siting_vert() const { return chroma_siting_vert_; } | 
|  | void set_chroma_siting_vert(uint64_t chroma_siting_vert) { | 
|  | chroma_siting_vert_ = chroma_siting_vert; | 
|  | } | 
|  | uint64_t range() const { return range_; } | 
|  | void set_range(uint64_t range) { range_ = range; } | 
|  | uint64_t transfer_characteristics() const { | 
|  | return transfer_characteristics_; | 
|  | } | 
|  | void set_transfer_characteristics(uint64_t transfer_characteristics) { | 
|  | transfer_characteristics_ = transfer_characteristics; | 
|  | } | 
|  | uint64_t primaries() const { return primaries_; } | 
|  | void set_primaries(uint64_t primaries) { primaries_ = primaries; } | 
|  | uint64_t max_cll() const { return max_cll_; } | 
|  | void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; } | 
|  | uint64_t max_fall() const { return max_fall_; } | 
|  | void set_max_fall(uint64_t max_fall) { max_fall_ = max_fall; } | 
|  |  | 
|  | private: | 
|  | // Returns size of Colour child elements. | 
|  | uint64_t PayloadSize() const; | 
|  |  | 
|  | uint64_t matrix_coefficients_; | 
|  | uint64_t bits_per_channel_; | 
|  | uint64_t chroma_subsampling_horz_; | 
|  | uint64_t chroma_subsampling_vert_; | 
|  | uint64_t cb_subsampling_horz_; | 
|  | uint64_t cb_subsampling_vert_; | 
|  | uint64_t chroma_siting_horz_; | 
|  | uint64_t chroma_siting_vert_; | 
|  | uint64_t range_; | 
|  | uint64_t transfer_characteristics_; | 
|  | uint64_t primaries_; | 
|  | uint64_t max_cll_; | 
|  | uint64_t max_fall_; | 
|  |  | 
|  | MasteringMetadata* mastering_metadata_; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Projection element. | 
|  | class Projection { | 
|  | public: | 
|  | enum ProjectionType { | 
|  | kTypeNotPresent = -1, | 
|  | kRectangular = 0, | 
|  | kEquirectangular = 1, | 
|  | kCubeMap = 2, | 
|  | kMesh = 3, | 
|  | }; | 
|  | static const uint64_t kValueNotPresent; | 
|  | Projection() | 
|  | : type_(kRectangular), | 
|  | pose_yaw_(0.0), | 
|  | pose_pitch_(0.0), | 
|  | pose_roll_(0.0), | 
|  | private_data_(NULL), | 
|  | private_data_length_(0) {} | 
|  | ~Projection() { delete[] private_data_; } | 
|  |  | 
|  | uint64_t ProjectionSize() const; | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | bool SetProjectionPrivate(const uint8_t* private_data, | 
|  | uint64_t private_data_length); | 
|  |  | 
|  | ProjectionType type() const { return type_; } | 
|  | void set_type(ProjectionType type) { type_ = type; } | 
|  | float pose_yaw() const { return pose_yaw_; } | 
|  | void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; } | 
|  | float pose_pitch() const { return pose_pitch_; } | 
|  | void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; } | 
|  | float pose_roll() const { return pose_roll_; } | 
|  | void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; } | 
|  | uint8_t* private_data() const { return private_data_; } | 
|  | uint64_t private_data_length() const { return private_data_length_; } | 
|  |  | 
|  | private: | 
|  | // Returns size of VideoProjection child elements. | 
|  | uint64_t PayloadSize() const; | 
|  |  | 
|  | ProjectionType type_; | 
|  | float pose_yaw_; | 
|  | float pose_pitch_; | 
|  | float pose_roll_; | 
|  | uint8_t* private_data_; | 
|  | uint64_t private_data_length_; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Track element. | 
|  | class Track { | 
|  | public: | 
|  | // The |seed| parameter is used to synthesize a UID for the track. | 
|  | explicit Track(unsigned int* seed); | 
|  | virtual ~Track(); | 
|  |  | 
|  | // Adds a ContentEncoding element to the Track. Returns true on success. | 
|  | virtual bool AddContentEncoding(); | 
|  |  | 
|  | // Returns the ContentEncoding by index. Returns NULL if there is no | 
|  | // ContentEncoding match. | 
|  | ContentEncoding* GetContentEncodingByIndex(uint32_t index) const; | 
|  |  | 
|  | // Returns the size in bytes for the payload of the Track element. | 
|  | virtual uint64_t PayloadSize() const; | 
|  |  | 
|  | // Returns the size in bytes of the Track element. | 
|  | virtual uint64_t Size() const; | 
|  |  | 
|  | // Output the Track element to the writer. Returns true on success. | 
|  | virtual bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | // Sets the CodecPrivate element of the Track element. Copies |length| | 
|  | // bytes from |codec_private| to |codec_private_|. Returns true on success. | 
|  | bool SetCodecPrivate(const uint8_t* codec_private, uint64_t length); | 
|  |  | 
|  | void set_codec_id(const char* codec_id); | 
|  | const char* codec_id() const { return codec_id_; } | 
|  | const uint8_t* codec_private() const { return codec_private_; } | 
|  | void set_language(const char* language); | 
|  | const char* language() const { return language_; } | 
|  | void set_max_block_additional_id(uint64_t max_block_additional_id) { | 
|  | max_block_additional_id_ = max_block_additional_id; | 
|  | } | 
|  | uint64_t max_block_additional_id() const { return max_block_additional_id_; } | 
|  | void set_name(const char* name); | 
|  | const char* name() const { return name_; } | 
|  | void set_number(uint64_t number) { number_ = number; } | 
|  | uint64_t number() const { return number_; } | 
|  | void set_type(uint64_t type) { type_ = type; } | 
|  | uint64_t type() const { return type_; } | 
|  | void set_uid(uint64_t uid) { uid_ = uid; } | 
|  | uint64_t uid() const { return uid_; } | 
|  | void set_codec_delay(uint64_t codec_delay) { codec_delay_ = codec_delay; } | 
|  | uint64_t codec_delay() const { return codec_delay_; } | 
|  | void set_seek_pre_roll(uint64_t seek_pre_roll) { | 
|  | seek_pre_roll_ = seek_pre_roll; | 
|  | } | 
|  | uint64_t seek_pre_roll() const { return seek_pre_roll_; } | 
|  | void set_default_duration(uint64_t default_duration) { | 
|  | default_duration_ = default_duration; | 
|  | } | 
|  | uint64_t default_duration() const { return default_duration_; } | 
|  |  | 
|  | uint64_t codec_private_length() const { return codec_private_length_; } | 
|  | uint32_t content_encoding_entries_size() const { | 
|  | return content_encoding_entries_size_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Track element names. | 
|  | char* codec_id_; | 
|  | uint8_t* codec_private_; | 
|  | char* language_; | 
|  | uint64_t max_block_additional_id_; | 
|  | char* name_; | 
|  | uint64_t number_; | 
|  | uint64_t type_; | 
|  | uint64_t uid_; | 
|  | uint64_t codec_delay_; | 
|  | uint64_t seek_pre_roll_; | 
|  | uint64_t default_duration_; | 
|  |  | 
|  | // Size of the CodecPrivate data in bytes. | 
|  | uint64_t codec_private_length_; | 
|  |  | 
|  | // ContentEncoding element list. | 
|  | ContentEncoding** content_encoding_entries_; | 
|  |  | 
|  | // Number of ContentEncoding elements added. | 
|  | uint32_t content_encoding_entries_size_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Track); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Track that has video specific elements. | 
|  | class VideoTrack : public Track { | 
|  | public: | 
|  | // Supported modes for stereo 3D. | 
|  | enum StereoMode { | 
|  | kMono = 0, | 
|  | kSideBySideLeftIsFirst = 1, | 
|  | kTopBottomRightIsFirst = 2, | 
|  | kTopBottomLeftIsFirst = 3, | 
|  | kSideBySideRightIsFirst = 11 | 
|  | }; | 
|  |  | 
|  | enum AlphaMode { kNoAlpha = 0, kAlpha = 1 }; | 
|  |  | 
|  | // The |seed| parameter is used to synthesize a UID for the track. | 
|  | explicit VideoTrack(unsigned int* seed); | 
|  | virtual ~VideoTrack(); | 
|  |  | 
|  | // Returns the size in bytes for the payload of the Track element plus the | 
|  | // video specific elements. | 
|  | virtual uint64_t PayloadSize() const; | 
|  |  | 
|  | // Output the VideoTrack element to the writer. Returns true on success. | 
|  | virtual bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | // Sets the video's stereo mode. Returns true on success. | 
|  | bool SetStereoMode(uint64_t stereo_mode); | 
|  |  | 
|  | // Sets the video's alpha mode. Returns true on success. | 
|  | bool SetAlphaMode(uint64_t alpha_mode); | 
|  |  | 
|  | void set_display_height(uint64_t height) { display_height_ = height; } | 
|  | uint64_t display_height() const { return display_height_; } | 
|  | void set_display_width(uint64_t width) { display_width_ = width; } | 
|  | uint64_t display_width() const { return display_width_; } | 
|  | void set_pixel_height(uint64_t height) { pixel_height_ = height; } | 
|  | uint64_t pixel_height() const { return pixel_height_; } | 
|  | void set_pixel_width(uint64_t width) { pixel_width_ = width; } | 
|  | uint64_t pixel_width() const { return pixel_width_; } | 
|  |  | 
|  | void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; } | 
|  | uint64_t crop_left() const { return crop_left_; } | 
|  | void set_crop_right(uint64_t crop_right) { crop_right_ = crop_right; } | 
|  | uint64_t crop_right() const { return crop_right_; } | 
|  | void set_crop_top(uint64_t crop_top) { crop_top_ = crop_top; } | 
|  | uint64_t crop_top() const { return crop_top_; } | 
|  | void set_crop_bottom(uint64_t crop_bottom) { crop_bottom_ = crop_bottom; } | 
|  | uint64_t crop_bottom() const { return crop_bottom_; } | 
|  |  | 
|  | void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; } | 
|  | double frame_rate() const { return frame_rate_; } | 
|  | void set_height(uint64_t height) { height_ = height; } | 
|  | uint64_t height() const { return height_; } | 
|  | uint64_t stereo_mode() { return stereo_mode_; } | 
|  | uint64_t alpha_mode() { return alpha_mode_; } | 
|  | void set_width(uint64_t width) { width_ = width; } | 
|  | uint64_t width() const { return width_; } | 
|  |  | 
|  | Colour* colour() { return colour_; } | 
|  |  | 
|  | // Deep copies |colour|. | 
|  | bool SetColour(const Colour& colour); | 
|  |  | 
|  | Projection* projection() { return projection_; } | 
|  |  | 
|  | // Deep copies |projection|. | 
|  | bool SetProjection(const Projection& projection); | 
|  |  | 
|  | private: | 
|  | // Returns the size in bytes of the Video element. | 
|  | uint64_t VideoPayloadSize() const; | 
|  |  | 
|  | // Video track element names. | 
|  | uint64_t display_height_; | 
|  | uint64_t display_width_; | 
|  | uint64_t pixel_height_; | 
|  | uint64_t pixel_width_; | 
|  | uint64_t crop_left_; | 
|  | uint64_t crop_right_; | 
|  | uint64_t crop_top_; | 
|  | uint64_t crop_bottom_; | 
|  | double frame_rate_; | 
|  | uint64_t height_; | 
|  | uint64_t stereo_mode_; | 
|  | uint64_t alpha_mode_; | 
|  | uint64_t width_; | 
|  |  | 
|  | Colour* colour_; | 
|  | Projection* projection_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Track that has audio specific elements. | 
|  | class AudioTrack : public Track { | 
|  | public: | 
|  | // The |seed| parameter is used to synthesize a UID for the track. | 
|  | explicit AudioTrack(unsigned int* seed); | 
|  | virtual ~AudioTrack(); | 
|  |  | 
|  | // Returns the size in bytes for the payload of the Track element plus the | 
|  | // audio specific elements. | 
|  | virtual uint64_t PayloadSize() const; | 
|  |  | 
|  | // Output the AudioTrack element to the writer. Returns true on success. | 
|  | virtual bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | void set_bit_depth(uint64_t bit_depth) { bit_depth_ = bit_depth; } | 
|  | uint64_t bit_depth() const { return bit_depth_; } | 
|  | void set_channels(uint64_t channels) { channels_ = channels; } | 
|  | uint64_t channels() const { return channels_; } | 
|  | void set_sample_rate(double sample_rate) { sample_rate_ = sample_rate; } | 
|  | double sample_rate() const { return sample_rate_; } | 
|  |  | 
|  | private: | 
|  | // Audio track element names. | 
|  | uint64_t bit_depth_; | 
|  | uint64_t channels_; | 
|  | double sample_rate_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(AudioTrack); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Tracks element | 
|  | class Tracks { | 
|  | public: | 
|  | // Audio and video type defined by the Matroska specs. | 
|  | enum { kVideo = 0x1, kAudio = 0x2 }; | 
|  |  | 
|  | static const char kOpusCodecId[]; | 
|  | static const char kVorbisCodecId[]; | 
|  | static const char kVp8CodecId[]; | 
|  | static const char kVp9CodecId[]; | 
|  | static const char kVp10CodecId[]; | 
|  | static const char kAV1CodecId[]; | 
|  | static const char kWebVttCaptionsId[]; | 
|  | static const char kWebVttDescriptionsId[]; | 
|  | static const char kWebVttMetadataId[]; | 
|  | static const char kWebVttSubtitlesId[]; | 
|  |  | 
|  | Tracks(); | 
|  | ~Tracks(); | 
|  |  | 
|  | // Adds a Track element to the Tracks object. |track| will be owned and | 
|  | // deleted by the Tracks object. Returns true on success. |number| is the | 
|  | // number to use for the track. |number| must be >= 0. If |number| == 0 | 
|  | // then the muxer will decide on the track number. | 
|  | bool AddTrack(Track* track, int32_t number); | 
|  |  | 
|  | // Returns the track by index. Returns NULL if there is no track match. | 
|  | const Track* GetTrackByIndex(uint32_t idx) const; | 
|  |  | 
|  | // Search the Tracks and return the track that matches |tn|. Returns NULL | 
|  | // if there is no track match. | 
|  | Track* GetTrackByNumber(uint64_t track_number) const; | 
|  |  | 
|  | // Returns true if the track number is an audio track. | 
|  | bool TrackIsAudio(uint64_t track_number) const; | 
|  |  | 
|  | // Returns true if the track number is a video track. | 
|  | bool TrackIsVideo(uint64_t track_number) const; | 
|  |  | 
|  | // Output the Tracks element to the writer. Returns true on success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | uint32_t track_entries_size() const { return track_entries_size_; } | 
|  |  | 
|  | private: | 
|  | // Track element list. | 
|  | Track** track_entries_; | 
|  |  | 
|  | // Number of Track elements added. | 
|  | uint32_t track_entries_size_; | 
|  |  | 
|  | // Whether or not Tracks element has already been written via IMkvWriter. | 
|  | mutable bool wrote_tracks_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tracks); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Chapter element | 
|  | // | 
|  | class Chapter { | 
|  | public: | 
|  | // Set the identifier for this chapter.  (This corresponds to the | 
|  | // Cue Identifier line in WebVTT.) | 
|  | // TODO(matthewjheaney): the actual serialization of this item in | 
|  | // MKV is pending. | 
|  | bool set_id(const char* id); | 
|  |  | 
|  | // Converts the nanosecond start and stop times of this chapter to | 
|  | // their corresponding timecode values, and stores them that way. | 
|  | void set_time(const Segment& segment, uint64_t start_time_ns, | 
|  | uint64_t end_time_ns); | 
|  |  | 
|  | // Sets the uid for this chapter. Primarily used to enable | 
|  | // deterministic output from the muxer. | 
|  | void set_uid(const uint64_t uid) { uid_ = uid; } | 
|  |  | 
|  | // Add a title string to this chapter, per the semantics described | 
|  | // here: | 
|  | //  http://www.matroska.org/technical/specs/index.html | 
|  | // | 
|  | // The title ("chapter string") is a UTF-8 string. | 
|  | // | 
|  | // The language has ISO 639-2 representation, described here: | 
|  | //  http://www.loc.gov/standards/iso639-2/englangn.html | 
|  | //  http://www.loc.gov/standards/iso639-2/php/English_list.php | 
|  | // If you specify NULL as the language value, this implies | 
|  | // English ("eng"). | 
|  | // | 
|  | // The country value corresponds to the codes listed here: | 
|  | //  http://www.iana.org/domains/root/db/ | 
|  | // | 
|  | // The function returns false if the string could not be allocated. | 
|  | bool add_string(const char* title, const char* language, const char* country); | 
|  |  | 
|  | private: | 
|  | friend class Chapters; | 
|  |  | 
|  | // For storage of chapter titles that differ by language. | 
|  | class Display { | 
|  | public: | 
|  | // Establish representation invariant for new Display object. | 
|  | void Init(); | 
|  |  | 
|  | // Reclaim resources, in anticipation of destruction. | 
|  | void Clear(); | 
|  |  | 
|  | // Copies the title to the |title_| member.  Returns false on | 
|  | // error. | 
|  | bool set_title(const char* title); | 
|  |  | 
|  | // Copies the language to the |language_| member.  Returns false | 
|  | // on error. | 
|  | bool set_language(const char* language); | 
|  |  | 
|  | // Copies the country to the |country_| member.  Returns false on | 
|  | // error. | 
|  | bool set_country(const char* country); | 
|  |  | 
|  | // If |writer| is non-NULL, serialize the Display sub-element of | 
|  | // the Atom into the stream.  Returns the Display element size on | 
|  | // success, 0 if error. | 
|  | uint64_t WriteDisplay(IMkvWriter* writer) const; | 
|  |  | 
|  | private: | 
|  | char* title_; | 
|  | char* language_; | 
|  | char* country_; | 
|  | }; | 
|  |  | 
|  | Chapter(); | 
|  | ~Chapter(); | 
|  |  | 
|  | // Establish the representation invariant for a newly-created | 
|  | // Chapter object.  The |seed| parameter is used to create the UID | 
|  | // for this chapter atom. | 
|  | void Init(unsigned int* seed); | 
|  |  | 
|  | // Copies this Chapter object to a different one.  This is used when | 
|  | // expanding a plain array of Chapter objects (see Chapters). | 
|  | void ShallowCopy(Chapter* dst) const; | 
|  |  | 
|  | // Reclaim resources used by this Chapter object, pending its | 
|  | // destruction. | 
|  | void Clear(); | 
|  |  | 
|  | // If there is no storage remaining on the |displays_| array for a | 
|  | // new display object, creates a new, longer array and copies the | 
|  | // existing Display objects to the new array.  Returns false if the | 
|  | // array cannot be expanded. | 
|  | bool ExpandDisplaysArray(); | 
|  |  | 
|  | // If |writer| is non-NULL, serialize the Atom sub-element into the | 
|  | // stream.  Returns the total size of the element on success, 0 if | 
|  | // error. | 
|  | uint64_t WriteAtom(IMkvWriter* writer) const; | 
|  |  | 
|  | // The string identifier for this chapter (corresponds to WebVTT cue | 
|  | // identifier). | 
|  | char* id_; | 
|  |  | 
|  | // Start timecode of the chapter. | 
|  | uint64_t start_timecode_; | 
|  |  | 
|  | // Stop timecode of the chapter. | 
|  | uint64_t end_timecode_; | 
|  |  | 
|  | // The binary identifier for this chapter. | 
|  | uint64_t uid_; | 
|  |  | 
|  | // The Atom element can contain multiple Display sub-elements, as | 
|  | // the same logical title can be rendered in different languages. | 
|  | Display* displays_; | 
|  |  | 
|  | // The physical length (total size) of the |displays_| array. | 
|  | int displays_size_; | 
|  |  | 
|  | // The logical length (number of active elements) on the |displays_| | 
|  | // array. | 
|  | int displays_count_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapter); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Chapters element | 
|  | // | 
|  | class Chapters { | 
|  | public: | 
|  | Chapters(); | 
|  | ~Chapters(); | 
|  |  | 
|  | Chapter* AddChapter(unsigned int* seed); | 
|  |  | 
|  | // Returns the number of chapters that have been added. | 
|  | int Count() const; | 
|  |  | 
|  | // Output the Chapters element to the writer. Returns true on success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | private: | 
|  | // Expands the chapters_ array if there is not enough space to contain | 
|  | // another chapter object.  Returns true on success. | 
|  | bool ExpandChaptersArray(); | 
|  |  | 
|  | // If |writer| is non-NULL, serialize the Edition sub-element of the | 
|  | // Chapters element into the stream.  Returns the Edition element | 
|  | // size on success, 0 if error. | 
|  | uint64_t WriteEdition(IMkvWriter* writer) const; | 
|  |  | 
|  | // Total length of the chapters_ array. | 
|  | int chapters_size_; | 
|  |  | 
|  | // Number of active chapters on the chapters_ array. | 
|  | int chapters_count_; | 
|  |  | 
|  | // Array for storage of chapter objects. | 
|  | Chapter* chapters_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Chapters); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Tag element | 
|  | // | 
|  | class Tag { | 
|  | public: | 
|  | bool add_simple_tag(const char* tag_name, const char* tag_string); | 
|  |  | 
|  | private: | 
|  | // Tags calls Clear and the destructor of Tag | 
|  | friend class Tags; | 
|  |  | 
|  | // For storage of simple tags | 
|  | class SimpleTag { | 
|  | public: | 
|  | // Establish representation invariant for new SimpleTag object. | 
|  | void Init(); | 
|  |  | 
|  | // Reclaim resources, in anticipation of destruction. | 
|  | void Clear(); | 
|  |  | 
|  | // Copies the title to the |tag_name_| member.  Returns false on | 
|  | // error. | 
|  | bool set_tag_name(const char* tag_name); | 
|  |  | 
|  | // Copies the language to the |tag_string_| member.  Returns false | 
|  | // on error. | 
|  | bool set_tag_string(const char* tag_string); | 
|  |  | 
|  | // If |writer| is non-NULL, serialize the SimpleTag sub-element of | 
|  | // the Atom into the stream.  Returns the SimpleTag element size on | 
|  | // success, 0 if error. | 
|  | uint64_t Write(IMkvWriter* writer) const; | 
|  |  | 
|  | private: | 
|  | char* tag_name_; | 
|  | char* tag_string_; | 
|  | }; | 
|  |  | 
|  | Tag(); | 
|  | ~Tag(); | 
|  |  | 
|  | // Copies this Tag object to a different one.  This is used when | 
|  | // expanding a plain array of Tag objects (see Tags). | 
|  | void ShallowCopy(Tag* dst) const; | 
|  |  | 
|  | // Reclaim resources used by this Tag object, pending its | 
|  | // destruction. | 
|  | void Clear(); | 
|  |  | 
|  | // If there is no storage remaining on the |simple_tags_| array for a | 
|  | // new display object, creates a new, longer array and copies the | 
|  | // existing SimpleTag objects to the new array.  Returns false if the | 
|  | // array cannot be expanded. | 
|  | bool ExpandSimpleTagsArray(); | 
|  |  | 
|  | // If |writer| is non-NULL, serialize the Tag sub-element into the | 
|  | // stream.  Returns the total size of the element on success, 0 if | 
|  | // error. | 
|  | uint64_t Write(IMkvWriter* writer) const; | 
|  |  | 
|  | // The Atom element can contain multiple SimpleTag sub-elements | 
|  | SimpleTag* simple_tags_; | 
|  |  | 
|  | // The physical length (total size) of the |simple_tags_| array. | 
|  | int simple_tags_size_; | 
|  |  | 
|  | // The logical length (number of active elements) on the |simple_tags_| | 
|  | // array. | 
|  | int simple_tags_count_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tag); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Tags element | 
|  | // | 
|  | class Tags { | 
|  | public: | 
|  | Tags(); | 
|  | ~Tags(); | 
|  |  | 
|  | Tag* AddTag(); | 
|  |  | 
|  | // Returns the number of tags that have been added. | 
|  | int Count() const; | 
|  |  | 
|  | // Output the Tags element to the writer. Returns true on success. | 
|  | bool Write(IMkvWriter* writer) const; | 
|  |  | 
|  | private: | 
|  | // Expands the tags_ array if there is not enough space to contain | 
|  | // another tag object.  Returns true on success. | 
|  | bool ExpandTagsArray(); | 
|  |  | 
|  | // Total length of the tags_ array. | 
|  | int tags_size_; | 
|  |  | 
|  | // Number of active tags on the tags_ array. | 
|  | int tags_count_; | 
|  |  | 
|  | // Array for storage of tag objects. | 
|  | Tag* tags_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Tags); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Cluster element | 
|  | // | 
|  | // Notes: | 
|  | //  |Init| must be called before any other method in this class. | 
|  | class Cluster { | 
|  | public: | 
|  | // |timecode| is the absolute timecode of the cluster. |cues_pos| is the | 
|  | // position for the cluster within the segment that should be written in | 
|  | // the cues element. |timecode_scale| is the timecode scale of the segment. | 
|  | Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale, | 
|  | bool write_last_frame_with_duration = false, | 
|  | bool fixed_size_timecode = false); | 
|  | ~Cluster(); | 
|  |  | 
|  | bool Init(IMkvWriter* ptr_writer); | 
|  |  | 
|  | // Adds a frame to be output in the file. The frame is written out through | 
|  | // |writer_| if successful. Returns true on success. | 
|  | bool AddFrame(const Frame* frame); | 
|  |  | 
|  | // Adds a frame to be output in the file. The frame is written out through | 
|  | // |writer_| if successful. Returns true on success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data | 
|  | //   length: Length of the data | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions.  The range of allowed values is [1, 126]. | 
|  | //   timecode:     Absolute (not relative to cluster) timestamp of the | 
|  | //                 frame, expressed in timecode units. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, | 
|  | uint64_t timecode,  // timecode units (absolute) | 
|  | bool is_key); | 
|  |  | 
|  | // Adds a frame to be output in the file. The frame is written out through | 
|  | // |writer_| if successful. Returns true on success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data | 
|  | //   length: Length of the data | 
|  | //   additional: Pointer to the additional data | 
|  | //   additional_length: Length of the additional data | 
|  | //   add_id: Value of BlockAddID element | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions.  The range of allowed values is [1, 126]. | 
|  | //   abs_timecode: Absolute (not relative to cluster) timestamp of the | 
|  | //                 frame, expressed in timecode units. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, | 
|  | const uint8_t* additional, | 
|  | uint64_t additional_length, uint64_t add_id, | 
|  | uint64_t track_number, uint64_t abs_timecode, | 
|  | bool is_key); | 
|  |  | 
|  | // Adds a frame to be output in the file. The frame is written out through | 
|  | // |writer_| if successful. Returns true on success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data. | 
|  | //   length: Length of the data. | 
|  | //   discard_padding: DiscardPadding element value. | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions.  The range of allowed values is [1, 126]. | 
|  | //   abs_timecode: Absolute (not relative to cluster) timestamp of the | 
|  | //                 frame, expressed in timecode units. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, | 
|  | int64_t discard_padding, | 
|  | uint64_t track_number, uint64_t abs_timecode, | 
|  | bool is_key); | 
|  |  | 
|  | // Writes a frame of metadata to the output medium; returns true on | 
|  | // success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data | 
|  | //   length: Length of the data | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions.  The range of allowed values is [1, 126]. | 
|  | //   timecode:     Absolute (not relative to cluster) timestamp of the | 
|  | //                 metadata frame, expressed in timecode units. | 
|  | //   duration:     Duration of metadata frame, in timecode units. | 
|  | // | 
|  | // The metadata frame is written as a block group, with a duration | 
|  | // sub-element but no reference time sub-elements (indicating that | 
|  | // it is considered a keyframe, per Matroska semantics). | 
|  | bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, | 
|  | uint64_t timecode, uint64_t duration); | 
|  |  | 
|  | // Increments the size of the cluster's data in bytes. | 
|  | void AddPayloadSize(uint64_t size); | 
|  |  | 
|  | // Closes the cluster so no more data can be written to it. Will update the | 
|  | // cluster's size if |writer_| is seekable. Returns true on success. This | 
|  | // variant of Finalize() fails when |write_last_frame_with_duration_| is set | 
|  | // to true. | 
|  | bool Finalize(); | 
|  |  | 
|  | // Closes the cluster so no more data can be written to it. Will update the | 
|  | // cluster's size if |writer_| is seekable. Returns true on success. | 
|  | // Inputs: | 
|  | //   set_last_frame_duration: Boolean indicating whether or not the duration | 
|  | //                            of the last frame should be set. If set to | 
|  | //                            false, the |duration| value is ignored and | 
|  | //                            |write_last_frame_with_duration_| will not be | 
|  | //                            honored. | 
|  | //   duration: Duration of the Cluster in timecode scale. | 
|  | bool Finalize(bool set_last_frame_duration, uint64_t duration); | 
|  |  | 
|  | // Returns the size in bytes for the entire Cluster element. | 
|  | uint64_t Size() const; | 
|  |  | 
|  | // Given |abs_timecode|, calculates timecode relative to most recent timecode. | 
|  | // Returns -1 on failure, or a relative timecode. | 
|  | int64_t GetRelativeTimecode(int64_t abs_timecode) const; | 
|  |  | 
|  | int64_t size_position() const { return size_position_; } | 
|  | int32_t blocks_added() const { return blocks_added_; } | 
|  | uint64_t payload_size() const { return payload_size_; } | 
|  | int64_t position_for_cues() const { return position_for_cues_; } | 
|  | uint64_t timecode() const { return timecode_; } | 
|  | uint64_t timecode_scale() const { return timecode_scale_; } | 
|  | void set_write_last_frame_with_duration(bool write_last_frame_with_duration) { | 
|  | write_last_frame_with_duration_ = write_last_frame_with_duration; | 
|  | } | 
|  | bool write_last_frame_with_duration() const { | 
|  | return write_last_frame_with_duration_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Iterator type for the |stored_frames_| map. | 
|  | typedef std::map<uint64_t, std::list<Frame*> >::iterator FrameMapIterator; | 
|  |  | 
|  | // Utility method that confirms that blocks can still be added, and that the | 
|  | // cluster header has been written. Used by |DoWriteFrame*|. Returns true | 
|  | // when successful. | 
|  | bool PreWriteBlock(); | 
|  |  | 
|  | // Utility method used by the |DoWriteFrame*| methods that handles the book | 
|  | // keeping required after each block is written. | 
|  | void PostWriteBlock(uint64_t element_size); | 
|  |  | 
|  | // Does some verification and calls WriteFrame. | 
|  | bool DoWriteFrame(const Frame* const frame); | 
|  |  | 
|  | // Either holds back the given frame, or writes it out depending on whether or | 
|  | // not |write_last_frame_with_duration_| is set. | 
|  | bool QueueOrWriteFrame(const Frame* const frame); | 
|  |  | 
|  | // Outputs the Cluster header to |writer_|. Returns true on success. | 
|  | bool WriteClusterHeader(); | 
|  |  | 
|  | // Number of blocks added to the cluster. | 
|  | int32_t blocks_added_; | 
|  |  | 
|  | // Flag telling if the cluster has been closed. | 
|  | bool finalized_; | 
|  |  | 
|  | // Flag indicating whether the cluster's timecode will always be written out | 
|  | // using 8 bytes. | 
|  | bool fixed_size_timecode_; | 
|  |  | 
|  | // Flag telling if the cluster's header has been written. | 
|  | bool header_written_; | 
|  |  | 
|  | // The size of the cluster elements in bytes. | 
|  | uint64_t payload_size_; | 
|  |  | 
|  | // The file position used for cue points. | 
|  | const int64_t position_for_cues_; | 
|  |  | 
|  | // The file position of the cluster's size element. | 
|  | int64_t size_position_; | 
|  |  | 
|  | // The absolute timecode of the cluster. | 
|  | const uint64_t timecode_; | 
|  |  | 
|  | // The timecode scale of the Segment containing the cluster. | 
|  | const uint64_t timecode_scale_; | 
|  |  | 
|  | // Flag indicating whether the last frame of the cluster should be written as | 
|  | // a Block with Duration. If set to true, then it will result in holding back | 
|  | // of frames and the parameterized version of Finalize() must be called to | 
|  | // finish writing the Cluster. | 
|  | bool write_last_frame_with_duration_; | 
|  |  | 
|  | // Map used to hold back frames, if required. Track number is the key. | 
|  | std::map<uint64_t, std::list<Frame*> > stored_frames_; | 
|  |  | 
|  | // Map from track number to the timestamp of the last block written for that | 
|  | // track. | 
|  | std::map<uint64_t, uint64_t> last_block_timestamp_; | 
|  |  | 
|  | // Pointer to the writer object. Not owned by this class. | 
|  | IMkvWriter* writer_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Cluster); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // SeekHead element | 
|  | class SeekHead { | 
|  | public: | 
|  | SeekHead(); | 
|  | ~SeekHead(); | 
|  |  | 
|  | // TODO(fgalligan): Change this to reserve a certain size. Then check how | 
|  | // big the seek entry to be added is as not every seek entry will be the | 
|  | // maximum size it could be. | 
|  | // Adds a seek entry to be written out when the element is finalized. |id| | 
|  | // must be the coded mkv element id. |pos| is the file position of the | 
|  | // element. Returns true on success. | 
|  | bool AddSeekEntry(uint32_t id, uint64_t pos); | 
|  |  | 
|  | // Writes out SeekHead and SeekEntry elements. Returns true on success. | 
|  | bool Finalize(IMkvWriter* writer) const; | 
|  |  | 
|  | // Returns the id of the Seek Entry at the given index. Returns -1 if index is | 
|  | // out of range. | 
|  | uint32_t GetId(int index) const; | 
|  |  | 
|  | // Returns the position of the Seek Entry at the given index. Returns -1 if | 
|  | // index is out of range. | 
|  | uint64_t GetPosition(int index) const; | 
|  |  | 
|  | // Sets the Seek Entry id and position at given index. | 
|  | // Returns true on success. | 
|  | bool SetSeekEntry(int index, uint32_t id, uint64_t position); | 
|  |  | 
|  | // Reserves space by writing out a Void element which will be updated with | 
|  | // a SeekHead element later. Returns true on success. | 
|  | bool Write(IMkvWriter* writer); | 
|  |  | 
|  | // We are going to put a cap on the number of Seek Entries. | 
|  | const static int32_t kSeekEntryCount = 5; | 
|  |  | 
|  | private: | 
|  | // Returns the maximum size in bytes of one seek entry. | 
|  | uint64_t MaxEntrySize() const; | 
|  |  | 
|  | // Seek entry id element list. | 
|  | uint32_t seek_entry_id_[kSeekEntryCount]; | 
|  |  | 
|  | // Seek entry pos element list. | 
|  | uint64_t seek_entry_pos_[kSeekEntryCount]; | 
|  |  | 
|  | // The file position of SeekHead element. | 
|  | int64_t start_pos_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SeekHead); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // Segment Information element | 
|  | class SegmentInfo { | 
|  | public: | 
|  | SegmentInfo(); | 
|  | ~SegmentInfo(); | 
|  |  | 
|  | // Will update the duration if |duration_| is > 0.0. Returns true on success. | 
|  | bool Finalize(IMkvWriter* writer) const; | 
|  |  | 
|  | // Sets |muxing_app_| and |writing_app_|. | 
|  | bool Init(); | 
|  |  | 
|  | // Output the Segment Information element to the writer. Returns true on | 
|  | // success. | 
|  | bool Write(IMkvWriter* writer); | 
|  |  | 
|  | void set_duration(double duration) { duration_ = duration; } | 
|  | double duration() const { return duration_; } | 
|  | void set_muxing_app(const char* app); | 
|  | const char* muxing_app() const { return muxing_app_; } | 
|  | void set_timecode_scale(uint64_t scale) { timecode_scale_ = scale; } | 
|  | uint64_t timecode_scale() const { return timecode_scale_; } | 
|  | void set_writing_app(const char* app); | 
|  | const char* writing_app() const { return writing_app_; } | 
|  | void set_date_utc(int64_t date_utc) { date_utc_ = date_utc; } | 
|  | int64_t date_utc() const { return date_utc_; } | 
|  |  | 
|  | private: | 
|  | // Segment Information element names. | 
|  | // Initially set to -1 to signify that a duration has not been set and should | 
|  | // not be written out. | 
|  | double duration_; | 
|  | // Set to libwebm-%d.%d.%d.%d, major, minor, build, revision. | 
|  | char* muxing_app_; | 
|  | uint64_t timecode_scale_; | 
|  | // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision. | 
|  | char* writing_app_; | 
|  | // LLONG_MIN when DateUTC is not set. | 
|  | int64_t date_utc_; | 
|  |  | 
|  | // The file position of the duration element. | 
|  | int64_t duration_pos_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(SegmentInfo); | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////// | 
|  | // This class represents the main segment in a WebM file. Currently only | 
|  | // supports one Segment element. | 
|  | // | 
|  | // Notes: | 
|  | //  |Init| must be called before any other method in this class. | 
|  | class Segment { | 
|  | public: | 
|  | enum Mode { kLive = 0x1, kFile = 0x2 }; | 
|  |  | 
|  | enum CuesPosition { | 
|  | kAfterClusters = 0x0,  // Position Cues after Clusters - Default | 
|  | kBeforeClusters = 0x1  // Position Cues before Clusters | 
|  | }; | 
|  |  | 
|  | static const uint32_t kDefaultDocTypeVersion = 4; | 
|  | static const uint64_t kDefaultMaxClusterDuration = 30000000000ULL; | 
|  |  | 
|  | Segment(); | 
|  | ~Segment(); | 
|  |  | 
|  | // Initializes |SegmentInfo| and returns result. Always returns false when | 
|  | // |ptr_writer| is NULL. | 
|  | bool Init(IMkvWriter* ptr_writer); | 
|  |  | 
|  | // Adds a generic track to the segment.  Returns the newly-allocated | 
|  | // track object (which is owned by the segment) on success, NULL on | 
|  | // error. |number| is the number to use for the track.  |number| | 
|  | // must be >= 0. If |number| == 0 then the muxer will decide on the | 
|  | // track number. | 
|  | Track* AddTrack(int32_t number); | 
|  |  | 
|  | // Adds a Vorbis audio track to the segment. Returns the number of the track | 
|  | // on success, 0 on error. |number| is the number to use for the audio track. | 
|  | // |number| must be >= 0. If |number| == 0 then the muxer will decide on | 
|  | // the track number. | 
|  | uint64_t AddAudioTrack(int32_t sample_rate, int32_t channels, int32_t number); | 
|  |  | 
|  | // Adds an empty chapter to the chapters of this segment.  Returns | 
|  | // non-NULL on success.  After adding the chapter, the caller should | 
|  | // populate its fields via the Chapter member functions. | 
|  | Chapter* AddChapter(); | 
|  |  | 
|  | // Adds an empty tag to the tags of this segment.  Returns | 
|  | // non-NULL on success.  After adding the tag, the caller should | 
|  | // populate its fields via the Tag member functions. | 
|  | Tag* AddTag(); | 
|  |  | 
|  | // Adds a cue point to the Cues element. |timestamp| is the time in | 
|  | // nanoseconds of the cue's time. |track| is the Track of the Cue. This | 
|  | // function must be called after AddFrame to calculate the correct | 
|  | // BlockNumber for the CuePoint. Returns true on success. | 
|  | bool AddCuePoint(uint64_t timestamp, uint64_t track); | 
|  |  | 
|  | // Adds a frame to be output in the file. Returns true on success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data | 
|  | //   length: Length of the data | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions. | 
|  | //   timestamp:    Timestamp of the frame in nanoseconds from 0. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrame(const uint8_t* data, uint64_t length, uint64_t track_number, | 
|  | uint64_t timestamp_ns, bool is_key); | 
|  |  | 
|  | // Writes a frame of metadata to the output medium; returns true on | 
|  | // success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data | 
|  | //   length: Length of the data | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions. | 
|  | //   timecode:     Absolute timestamp of the metadata frame, expressed | 
|  | //                 in nanosecond units. | 
|  | //   duration:     Duration of metadata frame, in nanosecond units. | 
|  | // | 
|  | // The metadata frame is written as a block group, with a duration | 
|  | // sub-element but no reference time sub-elements (indicating that | 
|  | // it is considered a keyframe, per Matroska semantics). | 
|  | bool AddMetadata(const uint8_t* data, uint64_t length, uint64_t track_number, | 
|  | uint64_t timestamp_ns, uint64_t duration_ns); | 
|  |  | 
|  | // Writes a frame with additional data to the output medium; returns true on | 
|  | // success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data. | 
|  | //   length: Length of the data. | 
|  | //   additional: Pointer to additional data. | 
|  | //   additional_length: Length of additional data. | 
|  | //   add_id: Additional ID which identifies the type of additional data. | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions. | 
|  | //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond | 
|  | //                 units. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrameWithAdditional(const uint8_t* data, uint64_t length, | 
|  | const uint8_t* additional, | 
|  | uint64_t additional_length, uint64_t add_id, | 
|  | uint64_t track_number, uint64_t timestamp, | 
|  | bool is_key); | 
|  |  | 
|  | // Writes a frame with DiscardPadding to the output medium; returns true on | 
|  | // success. | 
|  | // Inputs: | 
|  | //   data: Pointer to the data. | 
|  | //   length: Length of the data. | 
|  | //   discard_padding: DiscardPadding element value. | 
|  | //   track_number: Track to add the data to. Value returned by Add track | 
|  | //                 functions. | 
|  | //   timestamp:    Absolute timestamp of the frame, expressed in nanosecond | 
|  | //                 units. | 
|  | //   is_key:       Flag telling whether or not this frame is a key frame. | 
|  | bool AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length, | 
|  | int64_t discard_padding, | 
|  | uint64_t track_number, uint64_t timestamp, | 
|  | bool is_key); | 
|  |  | 
|  | // Writes a Frame to the output medium. Chooses the correct way of writing | 
|  | // the frame (Block vs SimpleBlock) based on the parameters passed. | 
|  | // Inputs: | 
|  | //   frame: frame object | 
|  | bool AddGenericFrame(const Frame* frame); | 
|  |  | 
|  | // Adds a VP8 video track to the segment. Returns the number of the track on | 
|  | // success, 0 on error. |number| is the number to use for the video track. | 
|  | // |number| must be >= 0. If |number| == 0 then the muxer will decide on | 
|  | // the track number. | 
|  | uint64_t AddVideoTrack(int32_t width, int32_t height, int32_t number); | 
|  |  | 
|  | // This function must be called after Finalize() if you need a copy of the | 
|  | // output with Cues written before the Clusters. It will return false if the | 
|  | // writer is not seekable of if chunking is set to true. | 
|  | // Input parameters: | 
|  | // reader - an IMkvReader object created with the same underlying file of the | 
|  | //          current writer object. Make sure to close the existing writer | 
|  | //          object before creating this so that all the data is properly | 
|  | //          flushed and available for reading. | 
|  | // writer - an IMkvWriter object pointing to a *different* file than the one | 
|  | //          pointed by the current writer object. This file will contain the | 
|  | //          Cues element before the Clusters. | 
|  | bool CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader, | 
|  | IMkvWriter* writer); | 
|  |  | 
|  | // Sets which track to use for the Cues element. Must have added the track | 
|  | // before calling this function. Returns true on success. |track_number| is | 
|  | // returned by the Add track functions. | 
|  | bool CuesTrack(uint64_t track_number); | 
|  |  | 
|  | // This will force the muxer to create a new Cluster when the next frame is | 
|  | // added. | 
|  | void ForceNewClusterOnNextFrame(); | 
|  |  | 
|  | // Writes out any frames that have not been written out. Finalizes the last | 
|  | // cluster. May update the size and duration of the segment. May output the | 
|  | // Cues element. May finalize the SeekHead element. Returns true on success. | 
|  | bool Finalize(); | 
|  |  | 
|  | // Returns the Cues object. | 
|  | Cues* GetCues() { return &cues_; } | 
|  |  | 
|  | // Returns the Segment Information object. | 
|  | const SegmentInfo* GetSegmentInfo() const { return &segment_info_; } | 
|  | SegmentInfo* GetSegmentInfo() { return &segment_info_; } | 
|  |  | 
|  | // Search the Tracks and return the track that matches |track_number|. | 
|  | // Returns NULL if there is no track match. | 
|  | Track* GetTrackByNumber(uint64_t track_number) const; | 
|  |  | 
|  | // Toggles whether to output a cues element. | 
|  | void OutputCues(bool output_cues); | 
|  |  | 
|  | // Toggles whether to write the last frame in each Cluster with Duration. | 
|  | void AccurateClusterDuration(bool accurate_cluster_duration); | 
|  |  | 
|  | // Toggles whether to write the Cluster Timecode using exactly 8 bytes. | 
|  | void UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode); | 
|  |  | 
|  | // Sets if the muxer will output files in chunks or not. |chunking| is a | 
|  | // flag telling whether or not to turn on chunking. |filename| is the base | 
|  | // filename for the chunk files. The header chunk file will be named | 
|  | // |filename|.hdr and the data chunks will be named | 
|  | // |filename|_XXXXXX.chk. Chunking implies that the muxer will be writing | 
|  | // to files so the muxer will use the default MkvWriter class to control | 
|  | // what data is written to what files. Returns true on success. | 
|  | // TODO: Should we change the IMkvWriter Interface to add Open and Close? | 
|  | // That will force the interface to be dependent on files. | 
|  | bool SetChunking(bool chunking, const char* filename); | 
|  |  | 
|  | bool chunking() const { return chunking_; } | 
|  | uint64_t cues_track() const { return cues_track_; } | 
|  | void set_max_cluster_duration(uint64_t max_cluster_duration) { | 
|  | max_cluster_duration_ = max_cluster_duration; | 
|  | } | 
|  | uint64_t max_cluster_duration() const { return max_cluster_duration_; } | 
|  | void set_max_cluster_size(uint64_t max_cluster_size) { | 
|  | max_cluster_size_ = max_cluster_size; | 
|  | } | 
|  | uint64_t max_cluster_size() const { return max_cluster_size_; } | 
|  | void set_mode(Mode mode) { mode_ = mode; } | 
|  | Mode mode() const { return mode_; } | 
|  | CuesPosition cues_position() const { return cues_position_; } | 
|  | bool output_cues() const { return output_cues_; } | 
|  | void set_estimate_file_duration(bool estimate_duration) { | 
|  | estimate_file_duration_ = estimate_duration; | 
|  | } | 
|  | bool estimate_file_duration() const { return estimate_file_duration_; } | 
|  | const SegmentInfo* segment_info() const { return &segment_info_; } | 
|  | void set_duration(double duration) { duration_ = duration; } | 
|  | double duration() const { return duration_; } | 
|  |  | 
|  | // Returns true when codec IDs are valid for WebM. | 
|  | bool DocTypeIsWebm() const; | 
|  |  | 
|  | private: | 
|  | // Checks if header information has been output and initialized. If not it | 
|  | // will output the Segment element and initialize the SeekHead elment and | 
|  | // Cues elements. | 
|  | bool CheckHeaderInfo(); | 
|  |  | 
|  | // Sets |doc_type_version_| based on the current element requirements. | 
|  | void UpdateDocTypeVersion(); | 
|  |  | 
|  | // Sets |name| according to how many chunks have been written. |ext| is the | 
|  | // file extension. |name| must be deleted by the calling app. Returns true | 
|  | // on success. | 
|  | bool UpdateChunkName(const char* ext, char** name) const; | 
|  |  | 
|  | // Returns the maximum offset within the segment's payload. When chunking | 
|  | // this function is needed to determine offsets of elements within the | 
|  | // chunked files. Returns -1 on error. | 
|  | int64_t MaxOffset(); | 
|  |  | 
|  | // Adds the frame to our frame array. | 
|  | bool QueueFrame(Frame* frame); | 
|  |  | 
|  | // Output all frames that are queued. Returns -1 on error, otherwise | 
|  | // it returns the number of frames written. | 
|  | int WriteFramesAll(); | 
|  |  | 
|  | // Output all frames that are queued that have an end time that is less | 
|  | // then |timestamp|. Returns true on success and if there are no frames | 
|  | // queued. | 
|  | bool WriteFramesLessThan(uint64_t timestamp); | 
|  |  | 
|  | // Outputs the segment header, Segment Information element, SeekHead element, | 
|  | // and Tracks element to |writer_|. | 
|  | bool WriteSegmentHeader(); | 
|  |  | 
|  | // Given a frame with the specified timestamp (nanosecond units) and | 
|  | // keyframe status, determine whether a new cluster should be | 
|  | // created, before writing enqueued frames and the frame itself. The | 
|  | // function returns one of the following values: | 
|  | //  -1 = error: an out-of-order frame was detected | 
|  | //  0 = do not create a new cluster, and write frame to the existing cluster | 
|  | //  1 = create a new cluster, and write frame to that new cluster | 
|  | //  2 = create a new cluster, and re-run test | 
|  | int TestFrame(uint64_t track_num, uint64_t timestamp_ns, bool key) const; | 
|  |  | 
|  | // Create a new cluster, using the earlier of the first enqueued | 
|  | // frame, or the indicated time. Returns true on success. | 
|  | bool MakeNewCluster(uint64_t timestamp_ns); | 
|  |  | 
|  | // Checks whether a new cluster needs to be created, and if so | 
|  | // creates a new cluster. Returns false if creation of a new cluster | 
|  | // was necessary but creation was not successful. | 
|  | bool DoNewClusterProcessing(uint64_t track_num, uint64_t timestamp_ns, | 
|  | bool key); | 
|  |  | 
|  | // Adjusts Cue Point values (to place Cues before Clusters) so that they | 
|  | // reflect the correct offsets. | 
|  | void MoveCuesBeforeClusters(); | 
|  |  | 
|  | // This function recursively computes the correct cluster offsets (this is | 
|  | // done to move the Cues before Clusters). It recursively updates the change | 
|  | // in size (which indicates a change in cluster offset) until no sizes change. | 
|  | // Parameters: | 
|  | // diff - indicates the difference in size of the Cues element that needs to | 
|  | //        accounted for. | 
|  | // index - index in the list of Cues which is currently being adjusted. | 
|  | // cue_size - sum of size of all the CuePoint elements. | 
|  | void MoveCuesBeforeClustersHelper(uint64_t diff, int index, | 
|  | uint64_t* cue_size); | 
|  |  | 
|  | // Seeds the random number generator used to make UIDs. | 
|  | unsigned int seed_; | 
|  |  | 
|  | // WebM elements | 
|  | Cues cues_; | 
|  | SeekHead seek_head_; | 
|  | SegmentInfo segment_info_; | 
|  | Tracks tracks_; | 
|  | Chapters chapters_; | 
|  | Tags tags_; | 
|  |  | 
|  | // Number of chunks written. | 
|  | int chunk_count_; | 
|  |  | 
|  | // Current chunk filename. | 
|  | char* chunk_name_; | 
|  |  | 
|  | // Default MkvWriter object created by this class used for writing clusters | 
|  | // out in separate files. | 
|  | MkvWriter* chunk_writer_cluster_; | 
|  |  | 
|  | // Default MkvWriter object created by this class used for writing Cues | 
|  | // element out to a file. | 
|  | MkvWriter* chunk_writer_cues_; | 
|  |  | 
|  | // Default MkvWriter object created by this class used for writing the | 
|  | // Matroska header out to a file. | 
|  | MkvWriter* chunk_writer_header_; | 
|  |  | 
|  | // Flag telling whether or not the muxer is chunking output to multiple | 
|  | // files. | 
|  | bool chunking_; | 
|  |  | 
|  | // Base filename for the chunked files. | 
|  | char* chunking_base_name_; | 
|  |  | 
|  | // File position offset where the Clusters end. | 
|  | int64_t cluster_end_offset_; | 
|  |  | 
|  | // List of clusters. | 
|  | Cluster** cluster_list_; | 
|  |  | 
|  | // Number of cluster pointers allocated in the cluster list. | 
|  | int32_t cluster_list_capacity_; | 
|  |  | 
|  | // Number of clusters in the cluster list. | 
|  | int32_t cluster_list_size_; | 
|  |  | 
|  | // Indicates whether Cues should be written before or after Clusters | 
|  | CuesPosition cues_position_; | 
|  |  | 
|  | // Track number that is associated with the cues element for this segment. | 
|  | uint64_t cues_track_; | 
|  |  | 
|  | // Tells the muxer to force a new cluster on the next Block. | 
|  | bool force_new_cluster_; | 
|  |  | 
|  | // List of stored audio frames. These variables are used to store frames so | 
|  | // the muxer can follow the guideline "Audio blocks that contain the video | 
|  | // key frame's timecode should be in the same cluster as the video key frame | 
|  | // block." | 
|  | Frame** frames_; | 
|  |  | 
|  | // Number of frame pointers allocated in the frame list. | 
|  | int32_t frames_capacity_; | 
|  |  | 
|  | // Number of frames in the frame list. | 
|  | int32_t frames_size_; | 
|  |  | 
|  | // Flag telling if a video track has been added to the segment. | 
|  | bool has_video_; | 
|  |  | 
|  | // Flag telling if the segment's header has been written. | 
|  | bool header_written_; | 
|  |  | 
|  | // Duration of the last block in nanoseconds. | 
|  | uint64_t last_block_duration_; | 
|  |  | 
|  | // Last timestamp in nanoseconds added to a cluster. | 
|  | uint64_t last_timestamp_; | 
|  |  | 
|  | // Last timestamp in nanoseconds by track number added to a cluster. | 
|  | uint64_t last_track_timestamp_[kMaxTrackNumber]; | 
|  |  | 
|  | // Number of frames written per track. | 
|  | uint64_t track_frames_written_[kMaxTrackNumber]; | 
|  |  | 
|  | // Maximum time in nanoseconds for a cluster duration. This variable is a | 
|  | // guideline and some clusters may have a longer duration. Default is 30 | 
|  | // seconds. | 
|  | uint64_t max_cluster_duration_; | 
|  |  | 
|  | // Maximum size in bytes for a cluster. This variable is a guideline and | 
|  | // some clusters may have a larger size. Default is 0 which signifies that | 
|  | // the muxer will decide the size. | 
|  | uint64_t max_cluster_size_; | 
|  |  | 
|  | // The mode that segment is in. If set to |kLive| the writer must not | 
|  | // seek backwards. | 
|  | Mode mode_; | 
|  |  | 
|  | // Flag telling the muxer that a new cue point should be added. | 
|  | bool new_cuepoint_; | 
|  |  | 
|  | // TODO(fgalligan): Should we add support for more than one Cues element? | 
|  | // Flag whether or not the muxer should output a Cues element. | 
|  | bool output_cues_; | 
|  |  | 
|  | // Flag whether or not the last frame in each Cluster will have a Duration | 
|  | // element in it. | 
|  | bool accurate_cluster_duration_; | 
|  |  | 
|  | // Flag whether or not to write the Cluster Timecode using exactly 8 bytes. | 
|  | bool fixed_size_cluster_timecode_; | 
|  |  | 
|  | // Flag whether or not to estimate the file duration. | 
|  | bool estimate_file_duration_; | 
|  |  | 
|  | // The size of the EBML header, used to validate the header if | 
|  | // WriteEbmlHeader() is called more than once. | 
|  | int32_t ebml_header_size_; | 
|  |  | 
|  | // The file position of the segment's payload. | 
|  | int64_t payload_pos_; | 
|  |  | 
|  | // The file position of the element's size. | 
|  | int64_t size_position_; | 
|  |  | 
|  | // Current DocTypeVersion (|doc_type_version_|) and that written in | 
|  | // WriteSegmentHeader(). | 
|  | // WriteEbmlHeader() will be called from Finalize() if |doc_type_version_| | 
|  | // differs from |doc_type_version_written_|. | 
|  | uint32_t doc_type_version_; | 
|  | uint32_t doc_type_version_written_; | 
|  |  | 
|  | // If |duration_| is > 0, then explicitly set the duration of the segment. | 
|  | double duration_; | 
|  |  | 
|  | // Pointer to the writer objects. Not owned by this class. | 
|  | IMkvWriter* writer_cluster_; | 
|  | IMkvWriter* writer_cues_; | 
|  | IMkvWriter* writer_header_; | 
|  |  | 
|  | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(Segment); | 
|  | }; | 
|  |  | 
|  | }  // namespace mkvmuxer | 
|  |  | 
|  | #endif  // MKVMUXER_MKVMUXER_H_ |