#include "mkvwriter.hpp"
#include "webmids.hpp"
+#ifdef _MSC_VER
+// Disable MSVC warnings that suggest making code non-portable.
+#pragma warning(disable : 4996)
+#endif
+
namespace mkvmuxer {
namespace {
char*& dst = *dst_ptr;
- delete [] dst;
+ delete[] dst;
dst = NULL;
if (src == NULL)
//
// IMkvWriter Class
-IMkvWriter::IMkvWriter() {
-}
+IMkvWriter::IMkvWriter() {}
-IMkvWriter::~IMkvWriter() {
-}
+IMkvWriter::~IMkvWriter() {}
bool WriteEbmlHeader(IMkvWriter* writer) {
// Level 0
return true;
}
-bool ChunkedCopy(mkvparser::IMkvReader* source,
- mkvmuxer::IMkvWriter* dst,
+bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst,
mkvmuxer::int64 start, int64 size) {
// TODO(vigneshv): Check if this is a reasonable value.
const uint32 kBufSize = 2048;
is_key_(false),
length_(0),
track_number_(0),
- timestamp_(0) {
-}
+ timestamp_(0),
+ discard_padding_(0) {}
Frame::~Frame() {
- delete [] frame_;
- delete [] additional_;
+ delete[] frame_;
+ delete[] additional_;
}
bool Frame::Init(const uint8* frame, uint64 length) {
if (!data)
return false;
- delete [] frame_;
+ delete[] frame_;
frame_ = data;
length_ = length;
if (!data)
return false;
- delete [] additional_;
+ delete[] additional_;
additional_ = data;
additional_length_ = length;
add_id_ = add_id;
track_(0),
cluster_pos_(0),
block_number_(1),
- output_block_number_(true) {
-}
+ output_block_number_(true) {}
-CuePoint::~CuePoint() {
-}
+CuePoint::~CuePoint() {}
bool CuePoint::Write(IMkvWriter* writer) const {
if (!writer || track_ < 1 || cluster_pos_ < 1)
size += EbmlElementSize(kMkvCueTrack, track_);
if (output_block_number_ && block_number_ > 1)
size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
- const uint64 track_pos_size = EbmlMasterElementSize(kMkvCueTrackPositions,
- size) + size;
- const uint64 payload_size = EbmlElementSize(kMkvCueTime, time_) +
- track_pos_size;
+ const uint64 track_pos_size =
+ EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;
+ const uint64 payload_size =
+ EbmlElementSize(kMkvCueTime, time_) + track_pos_size;
if (!WriteEbmlMasterElement(writer, kMkvCuePoint, payload_size))
return false;
size += EbmlElementSize(kMkvCueTrack, track_);
if (output_block_number_ && block_number_ > 1)
size += EbmlElementSize(kMkvCueBlockNumber, block_number_);
- const uint64 track_pos_size = EbmlMasterElementSize(kMkvCueTrackPositions,
- size) + size;
- const uint64 payload_size = EbmlElementSize(kMkvCueTime, time_) +
- track_pos_size;
+ const uint64 track_pos_size =
+ EbmlMasterElementSize(kMkvCueTrackPositions, size) + size;
+ const uint64 payload_size =
+ EbmlElementSize(kMkvCueTime, time_) + track_pos_size;
return payload_size;
}
: cue_entries_capacity_(0),
cue_entries_size_(0),
cue_entries_(NULL),
- output_block_number_(true) {
-}
+ output_block_number_(true) {}
Cues::~Cues() {
if (cue_entries_) {
CuePoint* const cue = cue_entries_[i];
delete cue;
}
- delete [] cue_entries_;
+ delete[] cue_entries_;
}
}
return false;
CuePoint** const cues =
- new (std::nothrow) CuePoint*[new_capacity]; // NOLINT
+ new (std::nothrow) CuePoint* [new_capacity]; // NOLINT
if (!cues)
return false;
cues[i] = cue_entries_[i];
}
- delete [] cue_entries_;
+ delete[] cue_entries_;
cue_entries_ = cues;
cue_entries_capacity_ = new_capacity;
encoding_order_(0),
encoding_scope_(1),
encoding_type_(1),
- enc_key_id_length_(0) {
-}
+ enc_key_id_length_(0) {}
-ContentEncoding::~ContentEncoding() {
- delete [] enc_key_id_;
-}
+ContentEncoding::~ContentEncoding() { delete[] enc_key_id_; }
bool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {
if (!id || length < 1)
return false;
- delete [] enc_key_id_;
+ delete[] enc_key_id_;
enc_key_id_ =
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
uint64 ContentEncoding::Size() const {
const uint64 encryption_size = EncryptionSize();
const uint64 encoding_size = EncodingSize(0, encryption_size);
- const uint64 encodings_size = EbmlMasterElementSize(kMkvContentEncoding,
- encoding_size) +
- encoding_size;
+ const uint64 encodings_size =
+ EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;
return encodings_size;
}
bool ContentEncoding::Write(IMkvWriter* writer) const {
const uint64 encryption_size = EncryptionSize();
const uint64 encoding_size = EncodingSize(0, encryption_size);
- const uint64 size = EbmlMasterElementSize(kMkvContentEncoding,
- encoding_size) +
- encoding_size;
+ const uint64 size =
+ EbmlMasterElementSize(kMkvContentEncoding, encoding_size) + encoding_size;
const int64 payload_position = writer->Position();
if (payload_position < 0)
return false;
if (!WriteEbmlElement(writer, kMkvContentEncAlgo, enc_algo_))
return false;
- if (!WriteEbmlElement(writer,
- kMkvContentEncKeyID,
- enc_key_id_,
+ if (!WriteEbmlElement(writer, kMkvContentEncKeyID, enc_key_id_,
enc_key_id_length_))
return false;
uint64 encoding_size = 0;
if (encryption_size > 0) {
- encoding_size += EbmlMasterElementSize(kMkvContentEncryption,
- encryption_size) +
- encryption_size;
+ encoding_size +=
+ EbmlMasterElementSize(kMkvContentEncryption, encryption_size) +
+ encryption_size;
}
encoding_size += EbmlElementSize(kMkvContentEncodingType, encoding_type_);
encoding_size += EbmlElementSize(kMkvContentEncodingScope, encoding_scope_);
uint64 ContentEncoding::EncryptionSize() const {
const uint64 aes_size = enc_aes_settings_.Size();
- uint64 encryption_size = EbmlElementSize(kMkvContentEncKeyID,
- enc_key_id_,
- enc_key_id_length_);
+ uint64 encryption_size =
+ EbmlElementSize(kMkvContentEncKeyID, enc_key_id_, enc_key_id_length_);
encryption_size += EbmlElementSize(kMkvContentEncAlgo, enc_algo_);
return encryption_size + aes_size;
uid_(MakeUID(seed)),
codec_delay_(0),
seek_pre_roll_(0),
+ default_duration_(0),
codec_private_length_(0),
content_encoding_entries_(NULL),
- content_encoding_entries_size_(0) {
-}
+ content_encoding_entries_size_(0) {}
Track::~Track() {
- delete [] codec_id_;
- delete [] codec_private_;
- delete [] language_;
- delete [] name_;
+ delete[] codec_id_;
+ delete[] codec_private_;
+ delete[] language_;
+ delete[] name_;
if (content_encoding_entries_) {
for (uint32 i = 0; i < content_encoding_entries_size_; ++i) {
ContentEncoding* const encoding = content_encoding_entries_[i];
delete encoding;
}
- delete [] content_encoding_entries_;
+ delete[] content_encoding_entries_;
}
}
const uint32 count = content_encoding_entries_size_ + 1;
ContentEncoding** const content_encoding_entries =
- new (std::nothrow) ContentEncoding*[count]; // NOLINT
+ new (std::nothrow) ContentEncoding* [count]; // NOLINT
if (!content_encoding_entries)
return false;
ContentEncoding* const content_encoding =
new (std::nothrow) ContentEncoding(); // NOLINT
if (!content_encoding) {
- delete [] content_encoding_entries;
+ delete[] content_encoding_entries;
return false;
}
content_encoding_entries[i] = content_encoding_entries_[i];
}
- delete [] content_encoding_entries_;
+ delete[] content_encoding_entries_;
content_encoding_entries_ = content_encoding_entries;
content_encoding_entries_[content_encoding_entries_size_] = content_encoding;
if (codec_id_)
size += EbmlElementSize(kMkvCodecID, codec_id_);
if (codec_private_)
- size += EbmlElementSize(kMkvCodecPrivate,
- codec_private_,
+ size += EbmlElementSize(kMkvCodecPrivate, codec_private_,
codec_private_length_);
if (language_)
size += EbmlElementSize(kMkvLanguage, language_);
size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
if (seek_pre_roll_)
size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
+ if (default_duration_)
+ size += EbmlElementSize(kMkvDefaultDuration, default_duration_);
if (content_encoding_entries_size_ > 0) {
uint64 content_encodings_size = 0;
content_encodings_size += encoding->Size();
}
- size += EbmlMasterElementSize(kMkvContentEncodings,
- content_encodings_size) +
- content_encodings_size;
+ size +=
+ EbmlMasterElementSize(kMkvContentEncodings, content_encodings_size) +
+ content_encodings_size;
}
return size;
if (codec_id_)
size += EbmlElementSize(kMkvCodecID, codec_id_);
if (codec_private_)
- size += EbmlElementSize(kMkvCodecPrivate,
- codec_private_,
+ size += EbmlElementSize(kMkvCodecPrivate, codec_private_,
codec_private_length_);
if (language_)
size += EbmlElementSize(kMkvLanguage, language_);
size += EbmlElementSize(kMkvCodecDelay, codec_delay_);
if (seek_pre_roll_)
size += EbmlElementSize(kMkvSeekPreRoll, seek_pre_roll_);
-
+ if (default_duration_)
+ size += EbmlElementSize(kMkvDefaultDuration, default_duration_);
const int64 payload_position = writer->Position();
if (payload_position < 0)
if (!WriteEbmlElement(writer, kMkvTrackType, type_))
return false;
if (max_block_additional_id_) {
- if (!WriteEbmlElement(writer,
- kMkvMaxBlockAdditionID,
+ if (!WriteEbmlElement(writer, kMkvMaxBlockAdditionID,
max_block_additional_id_)) {
return false;
}
if (!WriteEbmlElement(writer, kMkvSeekPreRoll, seek_pre_roll_))
return false;
}
+ if (default_duration_) {
+ if (!WriteEbmlElement(writer, kMkvDefaultDuration, default_duration_))
+ return false;
+ }
if (codec_id_) {
if (!WriteEbmlElement(writer, kMkvCodecID, codec_id_))
return false;
}
if (codec_private_) {
- if (!WriteEbmlElement(writer,
- kMkvCodecPrivate,
- codec_private_,
+ if (!WriteEbmlElement(writer, kMkvCodecPrivate, codec_private_,
codec_private_length_))
return false;
}
content_encodings_size += encoding->Size();
}
- if (!WriteEbmlMasterElement(writer,
- kMkvContentEncodings,
+ if (!WriteEbmlMasterElement(writer, kMkvContentEncodings,
content_encodings_size))
return false;
if (!codec_private || length < 1)
return false;
- delete [] codec_private_;
+ delete[] codec_private_;
codec_private_ =
new (std::nothrow) uint8[static_cast<size_t>(length)]; // NOLINT
void Track::set_codec_id(const char* codec_id) {
if (codec_id) {
- delete [] codec_id_;
+ delete[] codec_id_;
const size_t length = strlen(codec_id) + 1;
codec_id_ = new (std::nothrow) char[length]; // NOLINT
// TODO(fgalligan): Vet the language parameter.
void Track::set_language(const char* language) {
if (language) {
- delete [] language_;
+ delete[] language_;
const size_t length = strlen(language) + 1;
language_ = new (std::nothrow) char[length]; // NOLINT
void Track::set_name(const char* name) {
if (name) {
- delete [] name_;
+ delete[] name_;
const size_t length = strlen(name) + 1;
name_ = new (std::nothrow) char[length]; // NOLINT
height_(0),
stereo_mode_(0),
alpha_mode_(0),
- width_(0) {
-}
+ width_(0) {}
-VideoTrack::~VideoTrack() {
-}
+VideoTrack::~VideoTrack() {}
bool VideoTrack::SetStereoMode(uint64 stereo_mode) {
- if (stereo_mode != kMono &&
- stereo_mode != kSideBySideLeftIsFirst &&
+ if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
stereo_mode != kTopBottomRightIsFirst &&
stereo_mode != kTopBottomLeftIsFirst &&
stereo_mode != kSideBySideRightIsFirst)
}
bool VideoTrack::SetAlphaMode(uint64 alpha_mode) {
- if (alpha_mode != kNoAlpha &&
- alpha_mode != kAlpha)
+ if (alpha_mode != kNoAlpha && alpha_mode != kAlpha)
return false;
alpha_mode_ = alpha_mode;
if (!WriteEbmlElement(writer, kMkvAlphaMode, alpha_mode_))
return false;
if (frame_rate_ > 0.0)
- if (!WriteEbmlElement(writer,
- kMkvFrameRate,
+ if (!WriteEbmlElement(writer, kMkvFrameRate,
static_cast<float>(frame_rate_)))
return false;
// AudioTrack Class
AudioTrack::AudioTrack(unsigned int* seed)
- : Track(seed),
- bit_depth_(0),
- channels_(1),
- sample_rate_(0.0) {
-}
+ : Track(seed), bit_depth_(0), channels_(1), sample_rate_(0.0) {}
-AudioTrack::~AudioTrack() {
-}
+AudioTrack::~AudioTrack() {}
uint64 AudioTrack::PayloadSize() const {
const uint64 parent_size = Track::PayloadSize();
- uint64 size = EbmlElementSize(kMkvSamplingFrequency,
- static_cast<float>(sample_rate_));
+ uint64 size =
+ EbmlElementSize(kMkvSamplingFrequency, static_cast<float>(sample_rate_));
size += EbmlElementSize(kMkvChannels, channels_);
if (bit_depth_ > 0)
size += EbmlElementSize(kMkvBitDepth, bit_depth_);
return false;
// Calculate AudioSettings size.
- uint64 size = EbmlElementSize(kMkvSamplingFrequency,
- static_cast<float>(sample_rate_));
+ uint64 size =
+ EbmlElementSize(kMkvSamplingFrequency, static_cast<float>(sample_rate_));
size += EbmlElementSize(kMkvChannels, channels_);
if (bit_depth_ > 0)
size += EbmlElementSize(kMkvBitDepth, bit_depth_);
if (payload_position < 0)
return false;
- if (!WriteEbmlElement(writer,
- kMkvSamplingFrequency,
+ if (!WriteEbmlElement(writer, kMkvSamplingFrequency,
static_cast<float>(sample_rate_)))
return false;
if (!WriteEbmlElement(writer, kMkvChannels, channels_))
const char Tracks::kVp8CodecId[] = "V_VP8";
const char Tracks::kVp9CodecId[] = "V_VP9";
-
-Tracks::Tracks()
- : track_entries_(NULL),
- track_entries_size_(0) {
-}
+Tracks::Tracks() : track_entries_(NULL), track_entries_size_(0) {}
Tracks::~Tracks() {
if (track_entries_) {
Track* const track = track_entries_[i];
delete track;
}
- delete [] track_entries_;
+ delete[] track_entries_;
}
}
const uint32 count = track_entries_size_ + 1;
- Track** const track_entries = new (std::nothrow) Track*[count]; // NOLINT
+ Track** const track_entries = new (std::nothrow) Track* [count]; // NOLINT
if (!track_entries)
return false;
track_entries[i] = track_entries_[i];
}
- delete [] track_entries_;
+ delete[] track_entries_;
// Find the lowest availible track number > 0.
if (track_num == 0) {
//
// Chapter Class
-bool Chapter::set_id(const char* id) {
- return StrCpy(id, &id_);
-}
+bool Chapter::set_id(const char* id) { return StrCpy(id, &id_); }
-void Chapter::set_time(const Segment& segment,
- uint64 start_ns,
- uint64 end_ns) {
+void Chapter::set_time(const Segment& segment, uint64 start_ns, uint64 end_ns) {
const SegmentInfo* const info = segment.GetSegmentInfo();
const uint64 timecode_scale = info->timecode_scale();
start_timecode_ = start_ns / timecode_scale;
end_timecode_ = end_ns / timecode_scale;
}
-bool Chapter::add_string(const char* title,
- const char* language,
+bool Chapter::add_string(const char* title, const char* language,
const char* country) {
if (!ExpandDisplaysArray())
return false;
// active on the array.
}
-Chapter::~Chapter() {
-}
+Chapter::~Chapter() {}
void Chapter::Init(unsigned int* seed) {
id_ = NULL;
d.Clear();
}
- delete [] displays_;
+ delete[] displays_;
displays_ = NULL;
displays_size_ = 0;
displays[idx] = displays_[idx]; // shallow copy
}
- delete [] displays_;
+ delete[] displays_;
displays_ = displays;
displays_size_ = size;
}
uint64 Chapter::WriteAtom(IMkvWriter* writer) const {
- uint64 payload_size =
- EbmlElementSize(kMkvChapterStringUID, id_) +
- EbmlElementSize(kMkvChapterUID, uid_) +
- EbmlElementSize(kMkvChapterTimeStart, start_timecode_) +
- EbmlElementSize(kMkvChapterTimeEnd, end_timecode_);
+ uint64 payload_size = EbmlElementSize(kMkvChapterStringUID, id_) +
+ EbmlElementSize(kMkvChapterUID, uid_) +
+ EbmlElementSize(kMkvChapterTimeStart, start_timecode_) +
+ EbmlElementSize(kMkvChapterTimeEnd, end_timecode_);
for (int idx = 0; idx < displays_count_; ++idx) {
const Display& d = displays_[idx];
}
const uint64 atom_size =
- EbmlMasterElementSize(kMkvChapterAtom, payload_size) +
- payload_size;
+ EbmlMasterElementSize(kMkvChapterAtom, payload_size) + payload_size;
if (writer == NULL)
return atom_size;
payload_size += EbmlElementSize(kMkvChapCountry, country_);
const uint64 display_size =
- EbmlMasterElementSize(kMkvChapterDisplay, payload_size) +
- payload_size;
+ EbmlMasterElementSize(kMkvChapterDisplay, payload_size) + payload_size;
if (writer == NULL)
return display_size;
//
// Chapters Class
-Chapters::Chapters()
- : chapters_size_(0),
- chapters_count_(0),
- chapters_(NULL) {
-}
+Chapters::Chapters() : chapters_size_(0), chapters_count_(0), chapters_(NULL) {}
Chapters::~Chapters() {
while (chapters_count_ > 0) {
chapter.Clear();
}
- delete [] chapters_;
+ delete[] chapters_;
chapters_ = NULL;
}
-int Chapters::Count() const {
- return chapters_count_;
-}
+int Chapters::Count() const { return chapters_count_; }
Chapter* Chapters::AddChapter(unsigned int* seed) {
if (!ExpandChaptersArray())
src.ShallowCopy(dst);
}
- delete [] chapters_;
+ delete[] chapters_;
chapters_ = chapters;
chapters_size_ = size;
}
const uint64 edition_size =
- EbmlMasterElementSize(kMkvEditionEntry, payload_size) +
- payload_size;
+ EbmlMasterElementSize(kMkvEditionEntry, payload_size) + payload_size;
if (writer == NULL) // return size only
return edition_size;
position_for_cues_(cues_pos),
size_position_(-1),
timecode_(timecode),
- writer_(NULL) {
-}
+ writer_(NULL) {}
-Cluster::~Cluster() {
-}
+Cluster::~Cluster() {}
bool Cluster::Init(IMkvWriter* ptr_writer) {
if (!ptr_writer) {
return true;
}
-bool Cluster::AddFrame(const uint8* frame,
- uint64 length,
- uint64 track_number,
- uint64 abs_timecode,
- bool is_key) {
- return DoWriteBlock(frame,
- length,
- track_number,
- abs_timecode,
- is_key ? 1 : 0,
+bool Cluster::AddFrame(const uint8* frame, uint64 length, uint64 track_number,
+ uint64 abs_timecode, bool is_key) {
+ return DoWriteBlock(frame, length, track_number, abs_timecode, is_key ? 1 : 0,
&WriteSimpleBlock);
}
-bool Cluster::AddFrameWithAdditional(const uint8* frame,
- uint64 length,
+bool Cluster::AddFrameWithAdditional(const uint8* frame, uint64 length,
const uint8* additional,
- uint64 additional_length,
- uint64 add_id,
- uint64 track_number,
- uint64 abs_timecode,
+ uint64 additional_length, uint64 add_id,
+ uint64 track_number, uint64 abs_timecode,
bool is_key) {
- return DoWriteBlockWithAdditional(frame,
- length,
- additional,
- additional_length,
- add_id,
- track_number,
- abs_timecode,
- is_key ? 1 : 0,
- &WriteBlockWithAdditional);
-}
-
-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);
+ return DoWriteBlockWithAdditional(
+ frame, length, additional, additional_length, add_id, track_number,
+ abs_timecode, is_key ? 1 : 0, &WriteBlockWithAdditional);
}
-void Cluster::AddPayloadSize(uint64 size) {
- payload_size_ += size;
+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, 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; }
+
bool Cluster::Finalize() {
if (!writer_ || finalized_ || size_position_ == -1)
return false;
uint64 Cluster::Size() const {
const uint64 element_size =
- EbmlMasterElementSize(kMkvCluster,
- 0xFFFFFFFFFFFFFFFFULL) + payload_size_;
+ EbmlMasterElementSize(kMkvCluster, 0xFFFFFFFFFFFFFFFFULL) + payload_size_;
return element_size;
}
-bool Cluster::DoWriteBlock(
- const uint8* frame,
- uint64 length,
- uint64 track_number,
- uint64 abs_timecode,
- uint64 generic_arg,
- WriteBlock write_block) {
- if (frame == NULL || length == 0)
+template <typename Type>
+bool Cluster::PreWriteBlock(Type* write_function) {
+ if (write_function == NULL)
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 (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)
- return false;
+ if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
+ return -1;
- if (rel_timecode > kMaxBlockTimecode)
- return false;
+ return rel_timecode;
+}
- if (write_block == NULL)
+bool Cluster::DoWriteBlock(const uint8* frame, uint64 length,
+ uint64 track_number, uint64 abs_timecode,
+ uint64 generic_arg, WriteBlock write_block) {
+ if (frame == NULL || length == 0)
return false;
- if (finalized_)
+ if (!IsValidTrackNumber(track_number))
return false;
- if (!header_written_)
- if (!WriteClusterHeader())
- return false;
+ const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
+ if (rel_timecode < 0)
+ return false;
- const uint64 element_size = (*write_block)(writer_,
- frame,
- length,
- track_number,
- rel_timecode,
- generic_arg);
+ if (!PreWriteBlock(write_block))
+ 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;
}
bool Cluster::DoWriteBlockWithAdditional(
- const uint8* frame,
- uint64 length,
- const uint8* additional,
- uint64 additional_length,
- uint64 add_id,
- uint64 track_number,
- uint64 abs_timecode,
- uint64 generic_arg,
- WriteBlockAdditional write_block) {
- if (frame == NULL || length == 0 ||
- additional == NULL || additional_length == 0)
+ const uint8* frame, uint64 length, const uint8* additional,
+ uint64 additional_length, uint64 add_id, uint64 track_number,
+ uint64 abs_timecode, uint64 generic_arg, WriteBlockAdditional write_block) {
+ if (frame == NULL || length == 0 || 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)
+ const uint64 element_size =
+ (*write_block)(writer_, frame, length, additional, additional_length,
+ add_id, track_number, rel_timecode, generic_arg);
+ if (element_size == 0)
return false;
- if (finalized_)
+ 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 (!header_written_)
- if (!WriteClusterHeader())
- return false;
+ if (!IsValidTrackNumber(track_number))
+ return false;
- const uint64 element_size = (*write_block)(writer_,
- frame,
- length,
- additional,
- additional_length,
- add_id,
- track_number,
- rel_timecode,
- generic_arg);
+ const int64 rel_timecode = GetRelativeTimecode(abs_timecode);
+ if (rel_timecode < 0)
+ return false;
- if (element_size == 0)
+ if (!PreWriteBlock(write_block))
return false;
- AddPayloadSize(element_size);
- blocks_added_++;
+ 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;
}
}
}
-SeekHead::~SeekHead() {
-}
+SeekHead::~SeekHead() {}
bool SeekHead::Finalize(IMkvWriter* writer) const {
if (writer->Seekable()) {
for (int32 i = 0; i < kSeekEntryCount; ++i) {
if (seek_entry_id_[i] != 0) {
- entry_size[i] = EbmlElementSize(
- kMkvSeekID,
- static_cast<uint64>(seek_entry_id_[i]));
+ entry_size[i] =
+ EbmlElementSize(kMkvSeekID, static_cast<uint64>(seek_entry_id_[i]));
entry_size[i] += EbmlElementSize(kMkvSeekPosition, seek_entry_pos_[i]);
- payload_size += EbmlMasterElementSize(kMkvSeek, entry_size[i]) +
- entry_size[i];
+ payload_size +=
+ EbmlMasterElementSize(kMkvSeek, entry_size[i]) + entry_size[i];
}
}
if (!WriteEbmlMasterElement(writer, kMkvSeek, entry_size[i]))
return false;
- if (!WriteEbmlElement(writer,
- kMkvSeekID,
+ if (!WriteEbmlElement(writer, kMkvSeekID,
static_cast<uint64>(seek_entry_id_[i])))
return false;
const uint64 total_entry_size = kSeekEntryCount * MaxEntrySize();
const uint64 total_size =
- EbmlMasterElementSize(kMkvSeekHead,
- total_entry_size) + total_entry_size;
+ EbmlMasterElementSize(kMkvSeekHead, total_entry_size) +
+ total_entry_size;
const int64 size_left = total_size - (writer->Position() - start_pos_);
const uint64 bytes_written = WriteVoidElement(writer, size_left);
muxing_app_(NULL),
timecode_scale_(1000000ULL),
writing_app_(NULL),
- duration_pos_(-1) {
-}
+ date_utc_(LLONG_MIN),
+ duration_pos_(-1) {}
SegmentInfo::~SegmentInfo() {
- delete [] muxing_app_;
- delete [] writing_app_;
+ delete[] muxing_app_;
+ delete[] writing_app_;
}
bool SegmentInfo::Init() {
GetVersion(&major, &minor, &build, &revision);
char temp[256];
#ifdef _MSC_VER
- sprintf_s(temp,
- sizeof(temp)/sizeof(temp[0]),
- "libwebm-%d.%d.%d.%d",
- major,
- minor,
- build,
- revision);
+ sprintf_s(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
+ minor, build, revision);
#else
- snprintf(temp,
- sizeof(temp)/sizeof(temp[0]),
- "libwebm-%d.%d.%d.%d",
- major,
- minor,
- build,
- revision);
+ snprintf(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
+ minor, build, revision);
#endif
const size_t app_len = strlen(temp) + 1;
- delete [] muxing_app_;
+ delete[] muxing_app_;
muxing_app_ = new (std::nothrow) char[app_len]; // NOLINT
if (!muxing_app_)
if (writer->Position(duration_pos_))
return false;
- if (!WriteEbmlElement(writer,
- kMkvDuration,
+ if (!WriteEbmlElement(writer, kMkvDuration,
static_cast<float>(duration_)))
return false;
uint64 size = EbmlElementSize(kMkvTimecodeScale, timecode_scale_);
if (duration_ > 0.0)
size += EbmlElementSize(kMkvDuration, static_cast<float>(duration_));
+ if (date_utc_ != LLONG_MIN)
+ size += EbmlDateElementSize(kMkvDateUTC, date_utc_);
size += EbmlElementSize(kMkvMuxingApp, muxing_app_);
size += EbmlElementSize(kMkvWritingApp, writing_app_);
return false;
}
+ if (date_utc_ != LLONG_MIN)
+ WriteEbmlDateElement(writer, kMkvDateUTC, date_utc_);
+
if (!WriteEbmlElement(writer, kMkvMuxingApp, muxing_app_))
return false;
if (!WriteEbmlElement(writer, kMkvWritingApp, writing_app_))
strcpy(temp_str, app);
#endif
- delete [] muxing_app_;
+ delete[] muxing_app_;
muxing_app_ = temp_str;
}
}
strcpy(temp_str, app);
#endif
- delete [] writing_app_;
+ delete[] writing_app_;
writing_app_ = temp_str;
}
}
Cluster* const cluster = cluster_list_[i];
delete cluster;
}
- delete [] cluster_list_;
+ delete[] cluster_list_;
}
if (frames_) {
Frame* const frame = frames_[i];
delete frame;
}
- delete [] frames_;
+ delete[] frames_;
}
- delete [] chunk_name_;
- delete [] chunking_base_name_;
+ delete[] chunk_name_;
+ delete[] chunking_base_name_;
if (chunk_writer_cluster_) {
chunk_writer_cluster_->Close();
}
}
-void Segment::MoveCuesBeforeClustersHelper(uint64 diff,
- int32 index,
+void Segment::MoveCuesBeforeClustersHelper(uint64 diff, int32 index,
uint64* cues_size) {
const uint64 old_cues_size = *cues_size;
CuePoint* const cue_point = cues_.GetCueByIndex(index);
// Let d = a + b + c. Now d is the new size of the Cues element which is
// passed on to the next recursive call.
const uint64 cue_point_size_diff = cue_point->Size() - old_cue_point_size;
- const uint64 cue_size_diff = GetCodedUIntSize(*cues_size +
- cue_point_size_diff) -
- GetCodedUIntSize(*cues_size);
+ const uint64 cue_size_diff =
+ GetCodedUIntSize(*cues_size + cue_point_size_diff) -
+ GetCodedUIntSize(*cues_size);
*cues_size += cue_point_size_diff + cue_size_diff;
diff = *cues_size - old_cues_size;
if (diff > 0) {
IMkvWriter* writer) {
if (!writer->Seekable() || chunking_)
return false;
- const int64 cluster_offset = cluster_list_[0]->size_position() -
- GetUIntSize(kMkvCluster);
+ const int64 cluster_offset =
+ cluster_list_[0]->size_position() - GetUIntSize(kMkvCluster);
// Copy the headers.
if (!ChunkedCopy(reader, writer, 0, cluster_offset))
const int64 pos = writer->Position();
const int64 segment_size = writer->Position() - payload_pos_;
if (writer->Position(size_position_) ||
- WriteUIntSize(writer, segment_size, 8) ||
- writer->Position(pos))
+ WriteUIntSize(writer, segment_size, 8) || writer->Position(pos))
return false;
return true;
}
if (mode_ == kFile) {
if (cluster_list_size_ > 0) {
// Update last cluster's size
- Cluster* const old_cluster = cluster_list_[cluster_list_size_-1];
+ Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
if (!old_cluster || !old_cluster->Finalize())
return false;
return false;
const bool cues_open = chunk_writer_cues_->Open(name);
- delete [] name;
+ delete[] name;
if (!cues_open)
return false;
}
return track;
}
-Chapter* Segment::AddChapter() {
- return chapters_.AddChapter(&seed_);
-}
+Chapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); }
uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_); // NOLINT
}
bool Segment::AddCuePoint(uint64 timestamp, uint64 track) {
- if (cluster_list_size_ < 1)
+ if (cluster_list_size_ < 1)
return false;
- const Cluster* const cluster = cluster_list_[cluster_list_size_-1];
+ const Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
if (!cluster)
return false;
return true;
}
-uint64 Segment::AddAudioTrack(int32 sample_rate,
- int32 channels,
- int32 number) {
+uint64 Segment::AddAudioTrack(int32 sample_rate, int32 channels, int32 number) {
AudioTrack* const track = new (std::nothrow) AudioTrack(&seed_); // NOLINT
if (!track)
return 0;
return track->number();
}
-bool Segment::AddFrame(const uint8* frame,
- uint64 length,
- uint64 track_number,
- uint64 timestamp,
- bool is_key) {
+bool Segment::AddFrame(const uint8* frame, uint64 length, uint64 track_number,
+ uint64 timestamp, bool is_key) {
if (!frame)
return false;
// 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);
const uint64 timecode_scale = segment_info_.timecode_scale();
const uint64 abs_timecode = timestamp / timecode_scale;
- if (!cluster->AddFrame(frame,
- length,
- track_number,
- abs_timecode,
- is_key))
+ if (!cluster->AddFrame(frame, length, track_number, abs_timecode, is_key))
return false;
if (new_cuepoint_ && cues_track_ == track_number) {
return true;
}
-bool Segment::AddFrameWithAdditional(const uint8* frame,
- uint64 length,
+bool Segment::AddFrameWithAdditional(const uint8* frame, uint64 length,
const uint8* additional,
- uint64 additional_length,
- uint64 add_id,
- uint64 track_number,
- uint64 timestamp,
+ uint64 additional_length, uint64 add_id,
+ uint64 track_number, uint64 timestamp,
bool is_key) {
- if (!frame || !additional)
+ if (frame == NULL || additional == NULL)
return false;
if (!CheckHeaderInfo())
// 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);
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;
+
+ 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 / 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_))
return true;
}
-bool Segment::AddMetadata(const uint8* frame,
- uint64 length,
- uint64 track_number,
- uint64 timestamp_ns,
+bool Segment::AddMetadata(const uint8* frame, uint64 length,
+ uint64 track_number, uint64 timestamp_ns,
uint64 duration_ns) {
if (!frame)
return false;
if (cluster_list_size_ < 1)
return false;
- Cluster* const cluster = cluster_list_[cluster_list_size_-1];
+ Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
if (!cluster)
return false;
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,
+ if (!cluster->AddMetadata(frame, length, track_number, abs_timecode,
duration_timecode))
return false;
bool Segment::AddGenericFrame(const Frame* frame) {
last_block_duration_ = frame->duration();
if (!tracks_.TrackIsAudio(frame->track_number()) &&
- !tracks_.TrackIsVideo(frame->track_number()) &&
- frame->duration() > 0) {
- return AddMetadata(frame->frame(),
- frame->length(),
- frame->track_number(),
- frame->timestamp(),
- frame->duration());
+ !tracks_.TrackIsVideo(frame->track_number()) && frame->duration() > 0) {
+ return AddMetadata(frame->frame(), frame->length(), frame->track_number(),
+ frame->timestamp(), frame->duration());
} else if (frame->additional() && frame->additional_length() > 0) {
- return AddFrameWithAdditional(frame->frame(),
- frame->length(),
- frame->additional(),
- frame->additional_length(),
- frame->add_id(),
- frame->track_number(),
- frame->timestamp(),
- frame->is_key());
+ return AddFrameWithAdditional(
+ frame->frame(), frame->length(), frame->additional(),
+ frame->additional_length(), frame->add_id(), 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(),
- frame->track_number(),
- frame->timestamp(),
- frame->is_key());
+ return AddFrame(frame->frame(), frame->length(), frame->track_number(),
+ frame->timestamp(), frame->is_key());
}
}
-void Segment::OutputCues(bool output_cues) {
- output_cues_ = output_cues;
-}
+void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; }
bool Segment::SetChunking(bool chunking, const char* filename) {
if (chunk_count_ > 0)
strcpy(temp, filename);
#endif
- delete [] chunking_base_name_;
+ delete[] chunking_base_name_;
chunking_base_name_ = temp;
if (!UpdateChunkName("chk", &chunk_name_))
strcat(header, ".hdr");
#endif
if (!chunk_writer_header_->Open(header)) {
- delete [] header;
+ delete[] header;
return false;
}
writer_cues_ = chunk_writer_cues_;
writer_header_ = chunk_writer_header_;
- delete [] header;
+ delete[] header;
}
chunking_ = chunking;
return true;
}
-void Segment::ForceNewClusterOnNextFrame() {
- force_new_cluster_ = true;
-}
+void Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; }
Track* Segment::GetTrackByNumber(uint64 track_number) const {
return tracks_.GetTrackByNumber(track_number);
if (SerializeInt(writer_header_, kEbmlUnknownValue, 8))
return false;
- payload_pos_ = writer_header_->Position();
+ payload_pos_ = writer_header_->Position();
if (mode_ == kFile && writer_header_->Seekable()) {
// Set the duration > 0.0 so SegmentInfo will write out the duration. When
// Here we are testing whether to create a new cluster, given a frame
// having time frame_timestamp_ns.
//
-int Segment::TestFrame(uint64 track_number,
- uint64 frame_timestamp_ns,
+int Segment::TestFrame(uint64 track_number, uint64 frame_timestamp_ns,
bool is_key) const {
if (force_new_cluster_)
return 1;
// so this indicates a bug somewhere in our algorithm.
if (frame_timecode < last_cluster_timecode) // should never happen
- return -1; // error
+ return -1; // error
// If the frame has a timestamp significantly larger than the last
// cluster (in Matroska, cluster-relative timestamps are serialized
const int32 new_capacity =
(cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2;
Cluster** const clusters =
- new (std::nothrow) Cluster*[new_capacity]; // NOLINT
+ new (std::nothrow) Cluster* [new_capacity]; // NOLINT
if (!clusters)
return false;
clusters[i] = cluster_list_[i];
}
- delete [] cluster_list_;
+ delete[] cluster_list_;
cluster_list_ = clusters;
cluster_list_capacity_ = new_capacity;
}
bool Segment::DoNewClusterProcessing(uint64 track_number,
- uint64 frame_timestamp_ns,
- bool is_key) {
+ uint64 frame_timestamp_ns, bool is_key) {
for (;;) {
// Based on the characteristics of the current frame and current
// cluster, decide whether to create a new cluster.
if (result < 0) // error
return false;
- // Always set force_new_cluster_ to false after TestFrame.
- force_new_cluster_ = false;
+ // Always set force_new_cluster_ to false after TestFrame.
+ force_new_cluster_ = false;
- // A non-zero result means create a new cluster.
- if (result > 0 && !MakeNewCluster(frame_timestamp_ns))
- return false;
+ // A non-zero result means create a new cluster.
+ if (result > 0 && !MakeNewCluster(frame_timestamp_ns))
+ return false;
// Write queued (audio) frames.
const int frame_count = WriteFramesAll();
return false;
#ifdef _MSC_VER
- strcpy_s(str, length-strlen(ext_chk), chunking_base_name_);
+ strcpy_s(str, length - strlen(ext_chk), chunking_base_name_);
strcat_s(str, length, ext_chk);
#else
strcpy(str, chunking_base_name_);
strcat(str, ext_chk);
#endif
- delete [] *name;
+ delete[] * name;
*name = str;
return true;
if (new_capacity < 1)
return false;
- Frame** const frames = new (std::nothrow) Frame*[new_capacity]; // NOLINT
+ Frame** const frames = new (std::nothrow) Frame* [new_capacity]; // NOLINT
if (!frames)
return false;
frames[i] = frames_[i];
}
- delete [] frames_;
+ delete[] frames_;
frames_ = frames;
frames_capacity_ = new_capacity;
}
if (cluster_list_size_ < 1)
return -1;
- Cluster* const cluster = cluster_list_[cluster_list_size_-1];
+ Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
if (!cluster)
return -1;
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_))
if (!frames_)
return false;
- Cluster* const cluster = cluster_list_[cluster_list_size_-1];
+ Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
if (!cluster)
return false;
if (frame_curr->timestamp() > timestamp)
break;
- const Frame* const frame_prev = frames_[i-1];
+ 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_))
const int32 new_frames_size = frames_size_ - shift_left;
for (int32 i = 0; i < new_frames_size; ++i) {
- frames_[i] = frames_[i+shift_left];
+ frames_[i] = frames_[i + shift_left];
}
frames_size_ = new_frames_size;