Merge "mkvmuxer: Add DiscardPadding support."
This commit is contained in:
commit
84f2156ca1
290
mkvmuxer.cpp
290
mkvmuxer.cpp
@ -124,7 +124,8 @@ Frame::Frame()
|
||||
is_key_(false),
|
||||
length_(0),
|
||||
track_number_(0),
|
||||
timestamp_(0) {
|
||||
timestamp_(0),
|
||||
discard_padding_(0) {
|
||||
}
|
||||
|
||||
Frame::~Frame() {
|
||||
@ -1513,6 +1514,21 @@ bool Cluster::AddFrameWithAdditional(const uint8* frame,
|
||||
&WriteBlockWithAdditional);
|
||||
}
|
||||
|
||||
bool Cluster::AddFrameWithDiscardPadding(const uint8* frame,
|
||||
uint64 length,
|
||||
int64 discard_padding,
|
||||
uint64 track_number,
|
||||
uint64 abs_timecode,
|
||||
bool is_key) {
|
||||
return DoWriteBlockWithDiscardPadding(frame,
|
||||
length,
|
||||
discard_padding,
|
||||
track_number,
|
||||
abs_timecode,
|
||||
is_key ? 1 : 0,
|
||||
&WriteBlockWithDiscardPadding);
|
||||
}
|
||||
|
||||
bool Cluster::AddMetadata(const uint8* frame,
|
||||
uint64 length,
|
||||
uint64 track_number,
|
||||
@ -1559,6 +1575,42 @@ uint64 Cluster::Size() const {
|
||||
return element_size;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
bool Cluster::PreWriteBlock(Type* write_function) {
|
||||
if (write_function == NULL)
|
||||
return false;
|
||||
|
||||
if (finalized_)
|
||||
return false;
|
||||
|
||||
if (!header_written_) {
|
||||
if (!WriteClusterHeader())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cluster::PostWriteBlock(uint64 element_size) {
|
||||
AddPayloadSize(element_size);
|
||||
++blocks_added_;
|
||||
}
|
||||
|
||||
bool Cluster::IsValidTrackNumber(uint64 track_number) const {
|
||||
return (track_number > 0 && track_number <= 0x7E);
|
||||
}
|
||||
|
||||
int64 Cluster::GetRelativeTimecode(int64 abs_timecode) const {
|
||||
const int64 cluster_timecode = this->Cluster::timecode();
|
||||
const int64 rel_timecode =
|
||||
static_cast<int64>(abs_timecode) - cluster_timecode;
|
||||
|
||||
if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
|
||||
return -1;
|
||||
|
||||
return rel_timecode;
|
||||
}
|
||||
|
||||
bool Cluster::DoWriteBlock(
|
||||
const uint8* frame,
|
||||
uint64 length,
|
||||
@ -1569,46 +1621,26 @@ bool Cluster::DoWriteBlock(
|
||||
if (frame == NULL || length == 0)
|
||||
return false;
|
||||
|
||||
// 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.
|
||||
|
||||
if (track_number == 0 || track_number > 0x7E)
|
||||
if (!IsValidTrackNumber(track_number))
|
||||
return false;
|
||||
|
||||
const int64 cluster_timecode = this->Cluster::timecode();
|
||||
const int64 rel_timecode =
|
||||
static_cast<int64>(abs_timecode) - cluster_timecode;
|
||||
|
||||
const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
|
||||
if (rel_timecode < 0)
|
||||
return false;
|
||||
|
||||
if (rel_timecode > kMaxBlockTimecode)
|
||||
if (!PreWriteBlock(write_block))
|
||||
return false;
|
||||
|
||||
if (write_block == NULL)
|
||||
return false;
|
||||
|
||||
if (finalized_)
|
||||
return false;
|
||||
|
||||
if (!header_written_)
|
||||
if (!WriteClusterHeader())
|
||||
return false;
|
||||
|
||||
const uint64 element_size = (*write_block)(writer_,
|
||||
frame,
|
||||
length,
|
||||
track_number,
|
||||
rel_timecode,
|
||||
generic_arg);
|
||||
|
||||
if (element_size == 0)
|
||||
return false;
|
||||
|
||||
AddPayloadSize(element_size);
|
||||
blocks_added_++;
|
||||
|
||||
PostWriteBlock(element_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1626,33 +1658,16 @@ bool Cluster::DoWriteBlockWithAdditional(
|
||||
additional == NULL || additional_length == 0)
|
||||
return false;
|
||||
|
||||
// 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.
|
||||
|
||||
if (track_number == 0 || track_number > 0x7E)
|
||||
if (!IsValidTrackNumber(track_number))
|
||||
return false;
|
||||
|
||||
const int64 cluster_timecode = this->Cluster::timecode();
|
||||
const int64 rel_timecode =
|
||||
static_cast<int64>(abs_timecode) - cluster_timecode;
|
||||
|
||||
const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
|
||||
if (rel_timecode < 0)
|
||||
return false;
|
||||
|
||||
if (rel_timecode > kMaxBlockTimecode)
|
||||
if (!PreWriteBlock(write_block))
|
||||
return false;
|
||||
|
||||
if (write_block == NULL)
|
||||
return false;
|
||||
|
||||
if (finalized_)
|
||||
return false;
|
||||
|
||||
if (!header_written_)
|
||||
if (!WriteClusterHeader())
|
||||
return false;
|
||||
|
||||
const uint64 element_size = (*write_block)(writer_,
|
||||
frame,
|
||||
length,
|
||||
@ -1662,13 +1677,45 @@ bool Cluster::DoWriteBlockWithAdditional(
|
||||
track_number,
|
||||
rel_timecode,
|
||||
generic_arg);
|
||||
|
||||
if (element_size == 0)
|
||||
return false;
|
||||
|
||||
AddPayloadSize(element_size);
|
||||
blocks_added_++;
|
||||
PostWriteBlock(element_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cluster::DoWriteBlockWithDiscardPadding(
|
||||
const uint8* frame,
|
||||
uint64 length,
|
||||
int64 discard_padding,
|
||||
uint64 track_number,
|
||||
uint64 abs_timecode,
|
||||
uint64 generic_arg,
|
||||
WriteBlockDiscardPadding write_block) {
|
||||
if (frame == NULL || length == 0 || discard_padding <= 0)
|
||||
return false;
|
||||
|
||||
if (!IsValidTrackNumber(track_number))
|
||||
return false;
|
||||
|
||||
const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
|
||||
if (rel_timecode < 0)
|
||||
return false;
|
||||
|
||||
if (!PreWriteBlock(write_block))
|
||||
return false;
|
||||
|
||||
const uint64 element_size = (*write_block)(writer_,
|
||||
frame,
|
||||
length,
|
||||
discard_padding,
|
||||
track_number,
|
||||
rel_timecode,
|
||||
generic_arg);
|
||||
if (element_size == 0)
|
||||
return false;
|
||||
|
||||
PostWriteBlock(element_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2348,8 +2395,8 @@ bool Segment::AddFrame(const uint8* frame,
|
||||
// audio that is associated with the start time of a video key-frame is
|
||||
// muxed into the same cluster.
|
||||
if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
|
||||
Frame* const new_frame = new Frame();
|
||||
if (!new_frame->Init(frame, length))
|
||||
Frame* const new_frame = new (std::nothrow) Frame();
|
||||
if (new_frame == NULL || !new_frame->Init(frame, length))
|
||||
return false;
|
||||
new_frame->set_track_number(track_number);
|
||||
new_frame->set_timestamp(timestamp);
|
||||
@ -2400,7 +2447,7 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
|
||||
uint64 track_number,
|
||||
uint64 timestamp,
|
||||
bool is_key) {
|
||||
if (!frame || !additional)
|
||||
if (frame == NULL || additional == NULL)
|
||||
return false;
|
||||
|
||||
if (!CheckHeaderInfo())
|
||||
@ -2414,8 +2461,8 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
|
||||
// audio that is associated with the start time of a video key-frame is
|
||||
// muxed into the same cluster.
|
||||
if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
|
||||
Frame* const new_frame = new Frame();
|
||||
if (!new_frame->Init(frame, length))
|
||||
Frame* const new_frame = new (std::nothrow) Frame();
|
||||
if (new_frame == NULL || !new_frame->Init(frame, length))
|
||||
return false;
|
||||
new_frame->set_track_number(track_number);
|
||||
new_frame->set_timestamp(timestamp);
|
||||
@ -2427,6 +2474,74 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DoNewClusterProcessing(track_number, timestamp, is_key))
|
||||
return false;
|
||||
|
||||
if (cluster_list_size_ < 1)
|
||||
return false;
|
||||
|
||||
Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
|
||||
if (cluster == NULL)
|
||||
return false;
|
||||
|
||||
const uint64 timecode_scale = segment_info_.timecode_scale();
|
||||
const uint64 abs_timecode = timestamp / timecode_scale;
|
||||
|
||||
if (!cluster->AddFrameWithAdditional(frame,
|
||||
length,
|
||||
additional,
|
||||
additional_length,
|
||||
add_id,
|
||||
track_number,
|
||||
abs_timecode,
|
||||
is_key))
|
||||
return false;
|
||||
|
||||
if (new_cuepoint_ && cues_track_ == track_number) {
|
||||
if (!AddCuePoint(timestamp, cues_track_))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timestamp > last_timestamp_)
|
||||
last_timestamp_ = timestamp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Segment::AddFrameWithDiscardPadding(const uint8* frame,
|
||||
uint64 length,
|
||||
int64 discard_padding,
|
||||
uint64 track_number,
|
||||
uint64 timestamp,
|
||||
bool is_key) {
|
||||
if (frame == NULL || discard_padding <= 0)
|
||||
return false;
|
||||
|
||||
if (!CheckHeaderInfo())
|
||||
return false;
|
||||
|
||||
// Check for non-monotonically increasing timestamps.
|
||||
if (timestamp < last_timestamp_)
|
||||
return false;
|
||||
|
||||
// If the segment has a video track hold onto audio frames to make sure the
|
||||
// audio that is associated with the start time of a video key-frame is
|
||||
// muxed into the same cluster.
|
||||
if (has_video_ && tracks_.TrackIsAudio(track_number) && !force_new_cluster_) {
|
||||
Frame* const new_frame = new (std::nothrow) Frame();
|
||||
if (new_frame == NULL || !new_frame->Init(frame, length))
|
||||
return false;
|
||||
new_frame->set_track_number(track_number);
|
||||
new_frame->set_timestamp(timestamp);
|
||||
new_frame->set_is_key(is_key);
|
||||
new_frame->set_discard_padding(discard_padding);
|
||||
|
||||
if (!QueueFrame(new_frame))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DoNewClusterProcessing(track_number, timestamp, is_key))
|
||||
return false;
|
||||
|
||||
@ -2440,15 +2555,13 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
|
||||
const uint64 timecode_scale = segment_info_.timecode_scale();
|
||||
const uint64 abs_timecode = timestamp / timecode_scale;
|
||||
|
||||
if (!cluster->AddFrameWithAdditional(frame,
|
||||
length,
|
||||
additional,
|
||||
additional_length,
|
||||
add_id,
|
||||
track_number,
|
||||
abs_timecode,
|
||||
is_key))
|
||||
if (!cluster->AddFrameWithDiscardPadding(frame, length,
|
||||
discard_padding,
|
||||
track_number,
|
||||
abs_timecode,
|
||||
is_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (new_cuepoint_ && cues_track_ == track_number) {
|
||||
if (!AddCuePoint(timestamp, cues_track_))
|
||||
@ -2523,6 +2636,12 @@ bool Segment::AddGenericFrame(const Frame* frame) {
|
||||
frame->track_number(),
|
||||
frame->timestamp(),
|
||||
frame->is_key());
|
||||
} else if (frame->discard_padding() > 0) {
|
||||
return AddFrameWithDiscardPadding(frame->frame(), frame->length(),
|
||||
frame->discard_padding(),
|
||||
frame->track_number(),
|
||||
frame->timestamp(),
|
||||
frame->is_key());
|
||||
} else {
|
||||
return AddFrame(frame->frame(),
|
||||
frame->length(),
|
||||
@ -3006,12 +3125,24 @@ int Segment::WriteFramesAll() {
|
||||
const uint64 frame_timestamp = frame->timestamp(); // ns
|
||||
const uint64 frame_timecode = frame_timestamp / timecode_scale;
|
||||
|
||||
if (!cluster->AddFrame(frame->frame(),
|
||||
frame->length(),
|
||||
frame->track_number(),
|
||||
frame_timecode,
|
||||
frame->is_key()))
|
||||
return -1;
|
||||
if (frame->discard_padding() > 0) {
|
||||
if (!cluster->AddFrameWithDiscardPadding(frame->frame(),
|
||||
frame->length(),
|
||||
frame->discard_padding(),
|
||||
frame->track_number(),
|
||||
frame_timecode,
|
||||
frame->is_key())) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!cluster->AddFrame(frame->frame(),
|
||||
frame->length(),
|
||||
frame->track_number(),
|
||||
frame_timecode,
|
||||
frame->is_key())) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_cuepoint_ && cues_track_ == frame->track_number()) {
|
||||
if (!AddCuePoint(frame_timestamp, cues_track_))
|
||||
@ -3057,13 +3188,26 @@ bool Segment::WriteFramesLessThan(uint64 timestamp) {
|
||||
const Frame* const frame_prev = frames_[i-1];
|
||||
const uint64 frame_timestamp = frame_prev->timestamp();
|
||||
const uint64 frame_timecode = frame_timestamp / timecode_scale;
|
||||
const int64 discard_padding = frame_prev->discard_padding();
|
||||
|
||||
if (!cluster->AddFrame(frame_prev->frame(),
|
||||
frame_prev->length(),
|
||||
frame_prev->track_number(),
|
||||
frame_timecode,
|
||||
frame_prev->is_key()))
|
||||
return false;
|
||||
if (discard_padding > 0) {
|
||||
if (!cluster->AddFrameWithDiscardPadding(frame_prev->frame(),
|
||||
frame_prev->length(),
|
||||
discard_padding,
|
||||
frame_prev->track_number(),
|
||||
frame_timecode,
|
||||
frame_prev->is_key())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!cluster->AddFrame(frame_prev->frame(),
|
||||
frame_prev->length(),
|
||||
frame_prev->track_number(),
|
||||
frame_timecode,
|
||||
frame_prev->is_key())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) {
|
||||
if (!AddCuePoint(frame_timestamp, cues_track_))
|
||||
|
81
mkvmuxer.hpp
81
mkvmuxer.hpp
@ -90,6 +90,10 @@ class Frame {
|
||||
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.
|
||||
@ -118,6 +122,9 @@ class Frame {
|
||||
|
||||
// Timestamp of the data in nanoseconds.
|
||||
uint64 timestamp_;
|
||||
|
||||
// Discard padding for the frame.
|
||||
int64 discard_padding_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
@ -745,6 +752,24 @@ class Cluster {
|
||||
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:
|
||||
@ -803,6 +828,35 @@ class Cluster {
|
||||
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,
|
||||
@ -822,6 +876,15 @@ class Cluster {
|
||||
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();
|
||||
|
||||
@ -1055,6 +1118,24 @@ class Segment {
|
||||
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:
|
||||
|
@ -74,6 +74,10 @@ uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, int64 value) {
|
||||
return EbmlElementSize(type, static_cast<uint64>(value));
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
@ -464,7 +468,8 @@ uint64 WriteMetadataBlock(IMkvWriter* writer,
|
||||
return blockg_elem_size;
|
||||
}
|
||||
|
||||
// Writes a WebM Block with Additional. The structure is as follows
|
||||
// Writes a WebM BlockGroup with BlockAdditional data. The structure is as
|
||||
// follows:
|
||||
// Indentation shows sub-levels
|
||||
// BlockGroup
|
||||
// Block
|
||||
@ -553,6 +558,70 @@ uint64 WriteBlockWithAdditional(IMkvWriter* writer,
|
||||
return block_group_elem_size;
|
||||
}
|
||||
|
||||
// Writes a WebM BlockGroup with DiscardPadding. The structure is as follows:
|
||||
// Indentation shows sub-levels
|
||||
// BlockGroup
|
||||
// Block
|
||||
// Data
|
||||
// DiscardPadding
|
||||
uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
int64 discard_padding,
|
||||
uint64 track_number,
|
||||
int64 timecode,
|
||||
uint64 is_key) {
|
||||
if (!data || length < 1 || discard_padding <= 0)
|
||||
return 0;
|
||||
|
||||
const uint64 block_payload_size = 4 + length;
|
||||
const uint64 block_elem_size = EbmlMasterElementSize(kMkvBlock,
|
||||
block_payload_size) +
|
||||
block_payload_size;
|
||||
const uint64 discard_padding_elem_size = EbmlElementSize(kMkvDiscardPadding,
|
||||
discard_padding);
|
||||
const uint64 block_group_payload_size = block_elem_size +
|
||||
discard_padding_elem_size;
|
||||
const uint64 block_group_elem_size = EbmlMasterElementSize(
|
||||
kMkvBlockGroup,
|
||||
block_group_payload_size) +
|
||||
block_group_payload_size;
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, kMkvBlockGroup,
|
||||
block_group_payload_size))
|
||||
return 0;
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, kMkvBlock, block_payload_size))
|
||||
return 0;
|
||||
|
||||
if (WriteUInt(writer, track_number))
|
||||
return 0;
|
||||
|
||||
if (SerializeInt(writer, timecode, 2))
|
||||
return 0;
|
||||
|
||||
uint64 flags = 0;
|
||||
if (is_key)
|
||||
flags |= 0x80;
|
||||
if (SerializeInt(writer, flags, 1))
|
||||
return 0;
|
||||
|
||||
if (writer->Write(data, static_cast<uint32>(length)))
|
||||
return 0;
|
||||
|
||||
if (WriteID(writer, kMkvDiscardPadding))
|
||||
return 0;
|
||||
|
||||
const uint64 size = GetUIntSize(discard_padding);
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
if (SerializeInt(writer, discard_padding, static_cast<int32>(size)))
|
||||
return false;
|
||||
|
||||
return block_group_elem_size;
|
||||
}
|
||||
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
@ -25,6 +25,7 @@ int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
||||
int32 GetUIntSize(uint64 value);
|
||||
int32 GetCodedUIntSize(uint64 value);
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, int64 value);
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, float value);
|
||||
uint64 EbmlElementSize(uint64 type, const char* value);
|
||||
@ -113,6 +114,25 @@ uint64 WriteBlockWithAdditional(IMkvWriter* writer,
|
||||
int64 timecode,
|
||||
uint64 is_key);
|
||||
|
||||
// Output an Mkv Block with a DiscardPadding element.
|
||||
// Inputs:
|
||||
// data: Pointer to the data.
|
||||
// length: Length of the data.
|
||||
// discard_padding: DiscardPadding value.
|
||||
// track_number: Track to add the data to. Value returned by Add track
|
||||
// functions. Only values in the range [1, 126] are
|
||||
// permitted.
|
||||
// timecode: Relative timecode of the Block. Only values in the
|
||||
// range [0, 2^15) are permitted.
|
||||
// is_key: Non-zero value specifies that frame is a key frame.
|
||||
uint64 WriteBlockWithDiscardPadding(IMkvWriter* writer,
|
||||
const uint8* data,
|
||||
uint64 length,
|
||||
int64 discard_padding,
|
||||
uint64 track_number,
|
||||
int64 timecode,
|
||||
uint64 is_key);
|
||||
|
||||
// Output a void element. |size| must be the entire size in bytes that will be
|
||||
// void. The function will calculate the size of the void header and subtract
|
||||
// it from |size|.
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "sample_muxer_metadata.h"
|
||||
|
||||
using mkvmuxer::int64;
|
||||
using mkvmuxer::uint64;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -475,6 +476,7 @@ int main(int argc, char* argv[]) {
|
||||
(track_type == Track::kVideo && output_video)) {
|
||||
const int frame_count = block->GetFrameCount();
|
||||
const bool is_key = block->IsKey();
|
||||
const int64 discard_padding = block->GetDiscardPadding();
|
||||
|
||||
for (int i = 0; i < frame_count; ++i) {
|
||||
const mkvparser::Block::Frame& frame = block->GetFrame(i);
|
||||
@ -494,11 +496,21 @@ int main(int argc, char* argv[]) {
|
||||
if (track_type == Track::kAudio)
|
||||
track_num = aud_track;
|
||||
|
||||
if (!muxer_segment.AddFrame(data,
|
||||
frame.len,
|
||||
track_num,
|
||||
time_ns,
|
||||
is_key)) {
|
||||
bool frame_added = false;
|
||||
if (discard_padding) {
|
||||
frame_added =
|
||||
muxer_segment.AddFrameWithDiscardPadding(data, frame.len,
|
||||
discard_padding,
|
||||
track_num,
|
||||
time_ns,
|
||||
is_key);
|
||||
} else {
|
||||
frame_added = muxer_segment.AddFrame(data, frame.len,
|
||||
track_num,
|
||||
time_ns,
|
||||
is_key);
|
||||
}
|
||||
if (!frame_added) {
|
||||
printf("\n Could not add frame.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ enum MkvId {
|
||||
kMkvBlockMore = 0xA6,
|
||||
kMkvBlockAddID = 0xEE,
|
||||
kMkvBlockAdditional = 0xA5,
|
||||
kMkvDiscardPadding = 0x75A2,
|
||||
//Track
|
||||
kMkvTracks = 0x1654AE6B,
|
||||
kMkvTrackEntry = 0xAE,
|
||||
|
Loading…
x
Reference in New Issue
Block a user