Index: source/libvpx/third_party/libwebm/mkvmuxer.hpp |
=================================================================== |
--- source/libvpx/third_party/libwebm/mkvmuxer.hpp (revision 0) |
+++ source/libvpx/third_party/libwebm/mkvmuxer.hpp (revision 0) |
@@ -0,0 +1,1403 @@ |
+// 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_HPP |
+#define MKVMUXER_HPP |
+ |
+#include "mkvmuxertypes.hpp" |
+ |
+// For a description of the WebM elements see |
+// http://www.webmproject.org/code/specs/container/. |
+ |
+namespace mkvparser { |
+ class IMkvReader; |
+} // end namespace |
+ |
+namespace mkvmuxer { |
+ |
+class MkvWriter; |
+class Segment; |
+ |
+/////////////////////////////////////////////////////////////// |
+// 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. This function must be called |
+// before any other libwebm writing functions are called. |
+bool WriteEbmlHeader(IMkvWriter* writer); |
+ |
+// Copies in Chunk from source to destination between the given byte positions |
+bool ChunkedCopy(mkvparser::IMkvReader* source, IMkvWriter* dst, |
+ int64 start, int64 size); |
+ |
+/////////////////////////////////////////////////////////////// |
+// Class to hold data the will be written to a block. |
+class Frame { |
+ public: |
+ Frame(); |
+ ~Frame(); |
+ |
+ // Copies |frame| data into |frame_|. Returns true on success. |
+ bool Init(const uint8* frame, uint64 length); |
+ |
+ // Copies |additional| data into |additional_|. Returns true on success. |
+ bool AddAdditionalData(const uint8* additional, uint64 length, |
+ uint64 add_id); |
+ |
+ uint64 add_id() const { return add_id_; } |
+ const uint8* additional() const { return additional_; } |
+ uint64 additional_length() const { return additional_length_; } |
+ void set_duration(uint64 duration) { duration_ = duration; } |
+ uint64 duration() const { return duration_; } |
+ const uint8* frame() const { return frame_; } |
+ void set_is_key(bool key) { is_key_ = key; } |
+ bool is_key() const { return is_key_; } |
+ uint64 length() const { return length_; } |
+ void set_track_number(uint64 track_number) { track_number_ = track_number; } |
+ uint64 track_number() const { return track_number_; } |
+ void set_timestamp(uint64 timestamp) { timestamp_ = timestamp; } |
+ uint64 timestamp() const { return timestamp_; } |
+ void set_discard_padding(uint64 discard_padding) { |
+ discard_padding_ = discard_padding; |
+ } |
+ uint64 discard_padding() const { return discard_padding_; } |
+ |
+ private: |
+ // Id of the Additional data. |
+ uint64 add_id_; |
+ |
+ // Pointer to additional data. Owned by this class. |
+ uint8* additional_; |
+ |
+ // Length of the additional data. |
+ uint64 additional_length_; |
+ |
+ // Duration of the frame in nanoseconds. |
+ uint64 duration_; |
+ |
+ // Pointer to the data. Owned by this class. |
+ uint8* frame_; |
+ |
+ // Flag telling if the data should set the key flag of a block. |
+ bool is_key_; |
+ |
+ // Length of the data. |
+ uint64 length_; |
+ |
+ // Mkv track number the data is associated with. |
+ uint64 track_number_; |
+ |
+ // Timestamp of the data in nanoseconds. |
+ uint64 timestamp_; |
+ |
+ // Discard padding for the frame. |
+ int64 discard_padding_; |
+}; |
+ |
+/////////////////////////////////////////////////////////////// |
+// 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 Size() const; |
+ |
+ // Output the CuePoint element to the writer. Returns true on success. |
+ bool Write(IMkvWriter* writer) const; |
+ |
+ void set_time(uint64 time) { time_ = time; } |
+ uint64 time() const { return time_; } |
+ void set_track(uint64 track) { track_ = track; } |
+ uint64 track() const { return track_; } |
+ void set_cluster_pos(uint64 cluster_pos) { cluster_pos_ = cluster_pos; } |
+ uint64 cluster_pos() const { return cluster_pos_; } |
+ void set_block_number(uint64 block_number) { block_number_ = block_number; } |
+ uint64 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 PayloadSize() const; |
+ |
+ // Absolute timecode according to the segment time base. |
+ uint64 time_; |
+ |
+ // The Track element associated with the CuePoint. |
+ uint64 track_; |
+ |
+ // The position of the Cluster containing the Block. |
+ uint64 cluster_pos_; |
+ |
+ // Number of the Block within the Cluster, starting from 1. |
+ uint64 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 index) const; |
+ |
+ // Returns the total size of the Cues element |
+ uint64 Size(); |
+ |
+ // Output the Cues element to the writer. Returns true on success. |
+ bool Write(IMkvWriter* writer) const; |
+ |
+ int32 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 cue_entries_capacity_; |
+ |
+ // Number of CuePoints in |cue_entries_|. |
+ int32 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 Size() const; |
+ |
+ // Writes out the ContentEncAESSettings element to |writer|. Returns true on |
+ // success. |
+ bool Write(IMkvWriter* writer) const; |
+ |
+ uint64 cipher_mode() const { return cipher_mode_; } |
+ |
+ private: |
+ // Returns the size in bytes for the payload of the ContentEncAESSettings |
+ // element. |
+ uint64 PayloadSize() const; |
+ |
+ // Sub elements |
+ uint64 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* id, uint64 length); |
+ |
+ // Returns the size in bytes for the ContentEncoding element. |
+ uint64 Size() const; |
+ |
+ // Writes out the ContentEncoding element to |writer|. Returns true on |
+ // success. |
+ bool Write(IMkvWriter* writer) const; |
+ |
+ uint64 enc_algo() const { return enc_algo_; } |
+ uint64 encoding_order() const { return encoding_order_; } |
+ uint64 encoding_scope() const { return encoding_scope_; } |
+ uint64 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 EncodingSize(uint64 compresion_size, uint64 encryption_size) const; |
+ |
+ // Returns the size in bytes for the encryption elements. |
+ uint64 EncryptionSize() const; |
+ |
+ // Track element names |
+ uint64 enc_algo_; |
+ uint8* enc_key_id_; |
+ uint64 encoding_order_; |
+ uint64 encoding_scope_; |
+ uint64 encoding_type_; |
+ |
+ // ContentEncAESSettings element. |
+ ContentEncAESSettings enc_aes_settings_; |
+ |
+ // Size of the ContentEncKeyID data in bytes. |
+ uint64 enc_key_id_length_; |
+ |
+ LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding); |
+}; |
+ |
+/////////////////////////////////////////////////////////////// |
+// 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 index) const; |
+ |
+ // Returns the size in bytes for the payload of the Track element. |
+ virtual uint64 PayloadSize() const; |
+ |
+ // Returns the size in bytes of the Track element. |
+ virtual uint64 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* codec_private, uint64 length); |
+ |
+ void set_codec_id(const char* codec_id); |
+ const char* codec_id() const { return codec_id_; } |
+ const uint8* 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 max_block_additional_id) { |
+ max_block_additional_id_ = max_block_additional_id; |
+ } |
+ uint64 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 number) { number_ = number; } |
+ uint64 number() const { return number_; } |
+ void set_type(uint64 type) { type_ = type; } |
+ uint64 type() const { return type_; } |
+ void set_uid(uint64 uid) { uid_ = uid; } |
+ uint64 uid() const { return uid_; } |
+ void set_codec_delay(uint64 codec_delay) { codec_delay_ = codec_delay; } |
+ uint64 codec_delay() const { return codec_delay_; } |
+ void set_seek_pre_roll(uint64 seek_pre_roll) { |
+ seek_pre_roll_ = seek_pre_roll; |
+ } |
+ uint64 seek_pre_roll() const { return seek_pre_roll_; } |
+ |
+ uint64 codec_private_length() const { return codec_private_length_; } |
+ uint32 content_encoding_entries_size() const { |
+ return content_encoding_entries_size_; |
+ } |
+ |
+ private: |
+ // Track element names |
+ char* codec_id_; |
+ uint8* codec_private_; |
+ char* language_; |
+ uint64 max_block_additional_id_; |
+ char* name_; |
+ uint64 number_; |
+ uint64 type_; |
+ uint64 uid_; |
+ uint64 codec_delay_; |
+ uint64 seek_pre_roll_; |
+ |
+ // Size of the CodecPrivate data in bytes. |
+ uint64 codec_private_length_; |
+ |
+ // ContentEncoding element list. |
+ ContentEncoding** content_encoding_entries_; |
+ |
+ // Number of ContentEncoding elements added. |
+ uint32 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 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 stereo_mode); |
+ |
+ // Sets the video's alpha mode. Returns true on success. |
+ bool SetAlphaMode(uint64 alpha_mode); |
+ |
+ void set_display_height(uint64 height) { display_height_ = height; } |
+ uint64 display_height() const { return display_height_; } |
+ void set_display_width(uint64 width) { display_width_ = width; } |
+ uint64 display_width() const { return display_width_; } |
+ void set_frame_rate(double frame_rate) { frame_rate_ = frame_rate; } |
+ double frame_rate() const { return frame_rate_; } |
+ void set_height(uint64 height) { height_ = height; } |
+ uint64 height() const { return height_; } |
+ uint64 stereo_mode() { return stereo_mode_; } |
+ uint64 alpha_mode() { return alpha_mode_; } |
+ void set_width(uint64 width) { width_ = width; } |
+ uint64 width() const { return width_; } |
+ |
+ private: |
+ // Returns the size in bytes of the Video element. |
+ uint64 VideoPayloadSize() const; |
+ |
+ // Video track element names. |
+ uint64 display_height_; |
+ uint64 display_width_; |
+ double frame_rate_; |
+ uint64 height_; |
+ uint64 stereo_mode_; |
+ uint64 alpha_mode_; |
+ uint64 width_; |
+ |
+ 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 PayloadSize() const; |
+ |
+ // Output the AudioTrack element to the writer. Returns true on success. |
+ virtual bool Write(IMkvWriter* writer) const; |
+ |
+ void set_bit_depth(uint64 bit_depth) { bit_depth_ = bit_depth; } |
+ uint64 bit_depth() const { return bit_depth_; } |
+ void set_channels(uint64 channels) { channels_ = channels; } |
+ uint64 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 bit_depth_; |
+ uint64 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 |
+ }; |
+ // Opus, Vorbis, VP8, and VP9 codec ids defined by the Matroska specs. |
+ static const char kOpusCodecId[]; |
+ static const char kVorbisCodecId[]; |
+ static const char kVp8CodecId[]; |
+ static const char kVp9CodecId[]; |
+ |
+ 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 number); |
+ |
+ // Returns the track by index. Returns NULL if there is no track match. |
+ const Track* GetTrackByIndex(uint32 idx) const; |
+ |
+ // Search the Tracks and return the track that matches |tn|. Returns NULL |
+ // if there is no track match. |
+ Track* GetTrackByNumber(uint64 track_number) const; |
+ |
+ // Returns true if the track number is an audio track. |
+ bool TrackIsAudio(uint64 track_number) const; |
+ |
+ // Returns true if the track number is a video track. |
+ bool TrackIsVideo(uint64 track_number) const; |
+ |
+ // Output the Tracks element to the writer. Returns true on success. |
+ bool Write(IMkvWriter* writer) const; |
+ |
+ uint32 track_entries_size() const { return track_entries_size_; } |
+ |
+ private: |
+ // Track element list. |
+ Track** track_entries_; |
+ |
+ // Number of Track elements added. |
+ uint32 track_entries_size_; |
+ |
+ 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 start_time_ns, |
+ uint64 end_time_ns); |
+ |
+ // Sets the uid for this chapter. Primarily used to enable |
+ // deterministic output from the muxer. |
+ void set_uid(const uint64 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 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 WriteAtom(IMkvWriter* writer) const; |
+ |
+ // The string identifier for this chapter (corresponds to WebVTT cue |
+ // identifier). |
+ char* id_; |
+ |
+ // Start timecode of the chapter. |
+ uint64 start_timecode_; |
+ |
+ // Stop timecode of the chapter. |
+ uint64 end_timecode_; |
+ |
+ // The binary identifier for this chapter. |
+ uint64 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 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); |
+}; |
+ |
+/////////////////////////////////////////////////////////////// |
+// Cluster element |
+// |
+// Notes: |
+// |Init| must be called before any other method in this class. |
+class Cluster { |
+ public: |
+ Cluster(uint64 timecode, int64 cues_pos); |
+ ~Cluster(); |
+ |
+ // |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. |
+ 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. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ uint64 track_number, |
+ uint64 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: |
+ // frame: 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* frame, |
+ uint64 length, |
+ const uint8* additional, |
+ uint64 additional_length, |
+ uint64 add_id, |
+ uint64 track_number, |
+ uint64 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: |
+ // frame: 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* frame, |
+ uint64 length, |
+ int64 discard_padding, |
+ uint64 track_number, |
+ uint64 abs_timecode, |
+ bool is_key); |
+ |
+ // Writes a frame of metadata to the output medium; returns true on |
+ // success. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ uint64 track_number, |
+ uint64 timecode, // timecode units (absolute) |
+ uint64 duration); // timecode units |
+ |
+ // Increments the size of the cluster's data in bytes. |
+ void AddPayloadSize(uint64 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. |
+ bool Finalize(); |
+ |
+ // Returns the size in bytes for the entire Cluster element. |
+ uint64 Size() const; |
+ |
+ int64 size_position() const { return size_position_; } |
+ int32 blocks_added() const { return blocks_added_; } |
+ uint64 payload_size() const { return payload_size_; } |
+ int64 position_for_cues() const { return position_for_cues_; } |
+ uint64 timecode() const { return timecode_; } |
+ |
+ private: |
+ // Signature that matches either of WriteSimpleBlock or WriteMetadataBlock |
+ // in the muxer utilities package. |
+ typedef uint64 (*WriteBlock)(IMkvWriter* writer, |
+ const uint8* data, |
+ uint64 length, |
+ uint64 track_number, |
+ int64 timecode, |
+ uint64 generic_arg); |
+ |
+ // Signature that matches WriteBlockWithAdditional |
+ // in the muxer utilities package. |
+ typedef uint64 (*WriteBlockAdditional)(IMkvWriter* writer, |
+ const uint8* data, |
+ uint64 length, |
+ const uint8* additional, |
+ uint64 add_id, |
+ uint64 additional_length, |
+ uint64 track_number, |
+ int64 timecode, |
+ uint64 is_key); |
+ |
+ // Signature that matches WriteBlockWithDiscardPadding |
+ // in the muxer utilities package. |
+ typedef uint64 (*WriteBlockDiscardPadding)(IMkvWriter* writer, |
+ const uint8* data, |
+ uint64 length, |
+ int64 discard_padding, |
+ uint64 track_number, |
+ int64 timecode, |
+ uint64 is_key); |
+ |
+ // Utility method that confirms that blocks can still be added, and that the |
+ // cluster header has been written. Used by |DoWriteBlock*|. Returns true |
+ // when successful. |
+ template <typename Type> |
+ bool PreWriteBlock(Type* write_function); |
+ |
+ // Utility method used by the |DoWriteBlock*| methods that handles the book |
+ // keeping required after each block is written. |
+ void PostWriteBlock(uint64 element_size); |
+ |
+ // To simplify things, we require that there be fewer than 127 |
+ // tracks -- this allows us to serialize the track number value for |
+ // a stream using a single byte, per the Matroska encoding. |
+ bool IsValidTrackNumber(uint64 track_number) const; |
+ |
+ // Given |abs_timecode|, calculates timecode relative to most recent timecode. |
+ // Returns -1 on failure, or a relative timecode. |
+ int64 GetRelativeTimecode(int64 abs_timecode) const; |
+ |
+ // Used to implement AddFrame and AddMetadata. |
+ bool DoWriteBlock(const uint8* frame, |
+ uint64 length, |
+ uint64 track_number, |
+ uint64 absolute_timecode, |
+ uint64 generic_arg, |
+ WriteBlock write_block); |
+ |
+ // Used to implement AddFrameWithAdditional |
+ bool DoWriteBlockWithAdditional(const uint8* frame, |
+ uint64 length, |
+ const uint8* additional, |
+ uint64 additional_length, |
+ uint64 add_id, |
+ uint64 track_number, |
+ uint64 absolute_timecode, |
+ uint64 generic_arg, |
+ WriteBlockAdditional write_block); |
+ |
+ // Used to implement AddFrameWithDiscardPadding |
+ bool DoWriteBlockWithDiscardPadding(const uint8* frame, |
+ uint64 length, |
+ int64 discard_padding, |
+ uint64 track_number, |
+ uint64 absolute_timecode, |
+ uint64 generic_arg, |
+ WriteBlockDiscardPadding write_block); |
+ |
+ // Outputs the Cluster header to |writer_|. Returns true on success. |
+ bool WriteClusterHeader(); |
+ |
+ // Number of blocks added to the cluster. |
+ int32 blocks_added_; |
+ |
+ // Flag telling if the cluster has been closed. |
+ bool finalized_; |
+ |
+ // Flag telling if the cluster's header has been written. |
+ bool header_written_; |
+ |
+ // The size of the cluster elements in bytes. |
+ uint64 payload_size_; |
+ |
+ // The file position used for cue points. |
+ const int64 position_for_cues_; |
+ |
+ // The file position of the cluster's size element. |
+ int64 size_position_; |
+ |
+ // The absolute timecode of the cluster. |
+ const uint64 timecode_; |
+ |
+ // 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 id, uint64 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 GetId(int index) const; |
+ |
+ // Returns the position of the Seek Entry at the given index. Returns -1 if |
+ // index is out of range. |
+ uint64 GetPosition(int index) const; |
+ |
+ // Sets the Seek Entry id and position at given index. |
+ // Returns true on success. |
+ bool SetSeekEntry(int index, uint32 id, uint64 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 kSeekEntryCount = 5; |
+ |
+ private: |
+ // Returns the maximum size in bytes of one seek entry. |
+ uint64 MaxEntrySize() const; |
+ |
+ // Seek entry id element list. |
+ uint32 seek_entry_id_[kSeekEntryCount]; |
+ |
+ // Seek entry pos element list. |
+ uint64 seek_entry_pos_[kSeekEntryCount]; |
+ |
+ // The file position of SeekHead element. |
+ int64 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 scale) { timecode_scale_ = scale; } |
+ uint64 timecode_scale() const { return timecode_scale_; } |
+ void set_writing_app(const char* app); |
+ const char* writing_app() const { return writing_app_; } |
+ |
+ 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 timecode_scale_; |
+ // Initially set to libwebm-%d.%d.%d.%d, major, minor, build, revision. |
+ char* writing_app_; |
+ |
+ // The file position of the duration element. |
+ int64 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 |
+ }; |
+ |
+ const static uint64 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 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 AddAudioTrack(int32 sample_rate, int32 channels, int32 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 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 timestamp, uint64 track); |
+ |
+ // Adds a frame to be output in the file. Returns true on success. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ uint64 track_number, |
+ uint64 timestamp_ns, |
+ bool is_key); |
+ |
+ // Writes a frame of metadata to the output medium; returns true on |
+ // success. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ uint64 track_number, |
+ uint64 timestamp_ns, |
+ uint64 duration_ns); |
+ |
+ // Writes a frame with additional data to the output medium; returns true on |
+ // success. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ const uint8* additional, |
+ uint64 additional_length, |
+ uint64 add_id, |
+ uint64 track_number, |
+ uint64 timestamp, |
+ bool is_key); |
+ |
+ // Writes a frame with DiscardPadding to the output medium; returns true on |
+ // success. |
+ // Inputs: |
+ // frame: 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* frame, |
+ uint64 length, |
+ int64 discard_padding, |
+ uint64 track_number, |
+ uint64 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 AddVideoTrack(int32 width, int32 height, int32 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 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 track_number) const; |
+ |
+ // Toggles whether to output a cues element. |
+ void OutputCues(bool output_cues); |
+ |
+ // 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 cues_track() const { return cues_track_; } |
+ void set_max_cluster_duration(uint64 max_cluster_duration) { |
+ max_cluster_duration_ = max_cluster_duration; |
+ } |
+ uint64 max_cluster_duration() const { return max_cluster_duration_; } |
+ void set_max_cluster_size(uint64 max_cluster_size) { |
+ max_cluster_size_ = max_cluster_size; |
+ } |
+ uint64 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_; } |
+ const SegmentInfo* segment_info() const { return &segment_info_; } |
+ |
+ 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 |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 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 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 track_num, uint64 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 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 track_num, uint64 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 - size of the Cues element. |
+ void MoveCuesBeforeClustersHelper(uint64 diff, int index, uint64* 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_; |
+ |
+ // 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 cluster_end_offset_; |
+ |
+ // List of clusters. |
+ Cluster** cluster_list_; |
+ |
+ // Number of cluster pointers allocated in the cluster list. |
+ int32 cluster_list_capacity_; |
+ |
+ // Number of clusters in the cluster list. |
+ int32 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 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 frames_capacity_; |
+ |
+ // Number of frames in the frame list. |
+ int32 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 last_block_duration_; |
+ |
+ // Last timestamp in nanoseconds added to a cluster. |
+ uint64 last_timestamp_; |
+ |
+ // 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 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 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_; |
+ |
+ // The file position of the segment's payload. |
+ int64 payload_pos_; |
+ |
+ // The file position of the element's size. |
+ int64 size_position_; |
+ |
+ // 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); |
+}; |
+ |
+} //end namespace mkvmuxer |
+ |
+#endif //MKVMUXER_HPP |