diff --git a/mkvmuxer.cpp b/mkvmuxer.cpp index b471936..20d9302 100644 --- a/mkvmuxer.cpp +++ b/mkvmuxer.cpp @@ -1045,6 +1045,19 @@ bool Cluster::AddFrame(const uint8* frame, &WriteSimpleBlock); } +bool Cluster::AddMetadata(const uint8* frame, + uint64 length, + uint64 track_number, + uint64 abs_timecode, + uint64 duration_timecode) { + return DoWriteBlock(frame, + length, + track_number, + abs_timecode, + duration_timecode, + &WriteMetadataBlock); +} + void Cluster::AddPayloadSize(uint64 size) { payload_size_ += size; } @@ -1727,6 +1740,49 @@ bool Segment::AddFrame(const uint8* frame, return true; } +bool Segment::AddMetadata(const uint8* frame, + uint64 length, + uint64 track_number, + uint64 timestamp_ns, + uint64 duration_ns) { + if (!frame) + return false; + + if (!CheckHeaderInfo()) + return false; + + // Check for non-monotonically increasing timestamps. + if (timestamp_ns < last_timestamp_) + return false; + + if (!DoNewClusterProcessing(track_number, timestamp_ns, true)) + return false; + + if (cluster_list_size_ < 1) + return false; + + Cluster* const cluster = cluster_list_[cluster_list_size_-1]; + + if (!cluster) + return false; + + const uint64 timecode_scale = segment_info_.timecode_scale(); + const uint64 abs_timecode = timestamp_ns / timecode_scale; + const uint64 duration_timecode = duration_ns / timecode_scale; + + if (!cluster->AddMetadata(frame, + length, + track_number, + abs_timecode, + duration_timecode)) + return false; + + if (timestamp_ns > last_timestamp_) + last_timestamp_ = timestamp_ns; + + return true; +} + void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; } diff --git a/mkvmuxer.hpp b/mkvmuxer.hpp index 9a25b27..3e9b592 100644 --- a/mkvmuxer.hpp +++ b/mkvmuxer.hpp @@ -499,6 +499,26 @@ class Cluster { uint64 timecode, // timecode units (absolute) 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); @@ -524,7 +544,7 @@ class Cluster { int64 timecode, uint64 generic_arg); - // Used to implement AddFrame. + // Used to implement AddFrame and AddMetadata. bool DoWriteBlock(const uint8* frame, uint64 length, uint64 track_number, @@ -700,6 +720,26 @@ class Segment { 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); + // Adds a 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