Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libwebm / source / mkvmuxer.cpp
index d6c1e85..9bee09b 100644 (file)
 #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 {
@@ -35,7 +40,7 @@ bool StrCpy(const char* src, char** dst_ptr) {
 
   char*& dst = *dst_ptr;
 
-  delete [] dst;
+  delete[] dst;
   dst = NULL;
 
   if (src == NULL)
@@ -56,11 +61,9 @@ bool StrCpy(const char* src, char** dst_ptr) {
 //
 // IMkvWriter Class
 
-IMkvWriter::IMkvWriter() {
-}
+IMkvWriter::IMkvWriter() {}
 
-IMkvWriter::~IMkvWriter() {
-}
+IMkvWriter::~IMkvWriter() {}
 
 bool WriteEbmlHeader(IMkvWriter* writer) {
   // Level 0
@@ -92,8 +95,7 @@ bool WriteEbmlHeader(IMkvWriter* writer) {
   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;
@@ -124,12 +126,12 @@ Frame::Frame()
       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) {
@@ -138,7 +140,7 @@ bool Frame::Init(const uint8* frame, uint64 length) {
   if (!data)
     return false;
 
-  delete [] frame_;
+  delete[] frame_;
   frame_ = data;
   length_ = length;
 
@@ -153,7 +155,7 @@ bool Frame::AddAdditionalData(const uint8* additional, uint64 length,
   if (!data)
     return false;
 
-  delete [] additional_;
+  delete[] additional_;
   additional_ = data;
   additional_length_ = length;
   add_id_ = add_id;
@@ -171,11 +173,9 @@ CuePoint::CuePoint()
       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)
@@ -185,10 +185,10 @@ bool CuePoint::Write(IMkvWriter* writer) const {
   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;
@@ -225,10 +225,10 @@ uint64 CuePoint::PayloadSize() const {
   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;
 }
@@ -246,8 +246,7 @@ Cues::Cues()
     : cue_entries_capacity_(0),
       cue_entries_size_(0),
       cue_entries_(NULL),
-      output_block_number_(true) {
-}
+      output_block_number_(true) {}
 
 Cues::~Cues() {
   if (cue_entries_) {
@@ -255,7 +254,7 @@ Cues::~Cues() {
       CuePoint* const cue = cue_entries_[i];
       delete cue;
     }
-    delete [] cue_entries_;
+    delete[] cue_entries_;
   }
 }
 
@@ -272,7 +271,7 @@ bool Cues::AddCue(CuePoint* cue) {
       return false;
 
     CuePoint** const cues =
-        new (std::nothrow) CuePoint*[new_capacity];  // NOLINT
+        new (std::nothrow) CuePoint* [new_capacity];  // NOLINT
     if (!cues)
       return false;
 
@@ -280,7 +279,7 @@ bool Cues::AddCue(CuePoint* cue) {
       cues[i] = cue_entries_[i];
     }
 
-    delete [] cue_entries_;
+    delete[] cue_entries_;
 
     cue_entries_ = cues;
     cue_entries_capacity_ = new_capacity;
@@ -396,18 +395,15 @@ ContentEncoding::ContentEncoding()
       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
@@ -423,9 +419,8 @@ bool ContentEncoding::SetEncryptionID(const uint8* id, uint64 length) {
 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;
 }
@@ -433,9 +428,8 @@ uint64 ContentEncoding::Size() const {
 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)
@@ -454,9 +448,7 @@ bool ContentEncoding::Write(IMkvWriter* writer) const {
     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;
 
@@ -480,9 +472,9 @@ uint64 ContentEncoding::EncodingSize(uint64 compresion_size,
   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_);
@@ -494,9 +486,8 @@ uint64 ContentEncoding::EncodingSize(uint64 compresion_size,
 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;
@@ -517,23 +508,23 @@ Track::Track(unsigned int* seed)
       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_;
   }
 }
 
@@ -541,14 +532,14 @@ bool Track::AddContentEncoding() {
   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;
   }
 
@@ -556,7 +547,7 @@ bool Track::AddContentEncoding() {
     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;
@@ -581,8 +572,7 @@ uint64 Track::PayloadSize() const {
   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_);
@@ -594,6 +584,8 @@ uint64 Track::PayloadSize() const {
     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;
@@ -602,9 +594,9 @@ uint64 Track::PayloadSize() const {
       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;
@@ -633,8 +625,7 @@ bool Track::Write(IMkvWriter* writer) const {
   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_);
@@ -646,7 +637,8 @@ bool Track::Write(IMkvWriter* writer) const {
     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)
@@ -659,8 +651,7 @@ bool Track::Write(IMkvWriter* writer) const {
   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;
     }
@@ -673,14 +664,16 @@ bool Track::Write(IMkvWriter* writer) const {
     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;
   }
@@ -705,8 +698,7 @@ bool Track::Write(IMkvWriter* writer) const {
       content_encodings_size += encoding->Size();
     }
 
-    if (!WriteEbmlMasterElement(writer,
-                                kMkvContentEncodings,
+    if (!WriteEbmlMasterElement(writer, kMkvContentEncodings,
                                 content_encodings_size))
       return false;
 
@@ -727,7 +719,7 @@ bool Track::SetCodecPrivate(const uint8* codec_private, uint64 length) {
   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
@@ -742,7 +734,7 @@ bool Track::SetCodecPrivate(const uint8* codec_private, uint64 length) {
 
 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
@@ -759,7 +751,7 @@ void Track::set_codec_id(const char* codec_id) {
 // 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
@@ -775,7 +767,7 @@ void Track::set_language(const char* language) {
 
 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
@@ -801,15 +793,12 @@ VideoTrack::VideoTrack(unsigned int* seed)
       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)
@@ -820,8 +809,7 @@ bool VideoTrack::SetStereoMode(uint64 stereo_mode) {
 }
 
 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;
@@ -867,8 +855,7 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
     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;
 
@@ -902,20 +889,15 @@ uint64 VideoTrack::VideoPayloadSize() const {
 // 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_);
@@ -929,8 +911,8 @@ bool AudioTrack::Write(IMkvWriter* writer) const {
     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_);
@@ -942,8 +924,7 @@ bool AudioTrack::Write(IMkvWriter* writer) const {
   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_))
@@ -969,11 +950,7 @@ const char Tracks::kVorbisCodecId[] = "A_VORBIS";
 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_) {
@@ -981,7 +958,7 @@ Tracks::~Tracks() {
       Track* const track = track_entries_[i];
       delete track;
     }
-    delete [] track_entries_;
+    delete[] track_entries_;
   }
 }
 
@@ -1009,7 +986,7 @@ bool Tracks::AddTrack(Track* track, int32 number) {
 
   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;
 
@@ -1017,7 +994,7 @@ bool Tracks::AddTrack(Track* track, int32 number) {
     track_entries[i] = track_entries_[i];
   }
 
-  delete [] track_entries_;
+  delete[] track_entries_;
 
   // Find the lowest availible track number > 0.
   if (track_num == 0) {
@@ -1119,21 +1096,16 @@ bool Tracks::Write(IMkvWriter* writer) const {
 //
 // 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;
@@ -1165,8 +1137,7 @@ Chapter::Chapter() {
   // active on the array.
 }
 
-Chapter::~Chapter() {
-}
+Chapter::~Chapter() {}
 
 void Chapter::Init(unsigned int* seed) {
   id_ = NULL;
@@ -1194,7 +1165,7 @@ void Chapter::Clear() {
     d.Clear();
   }
 
-  delete [] displays_;
+  delete[] displays_;
   displays_ = NULL;
 
   displays_size_ = 0;
@@ -1214,7 +1185,7 @@ bool Chapter::ExpandDisplaysArray() {
     displays[idx] = displays_[idx];  // shallow copy
   }
 
-  delete [] displays_;
+  delete[] displays_;
 
   displays_ = displays;
   displays_size_ = size;
@@ -1223,11 +1194,10 @@ bool Chapter::ExpandDisplaysArray() {
 }
 
 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];
@@ -1235,8 +1205,7 @@ uint64 Chapter::WriteAtom(IMkvWriter* writer) const {
   }
 
   const uint64 atom_size =
-      EbmlMasterElementSize(kMkvChapterAtom, payload_size) +
-      payload_size;
+      EbmlMasterElementSize(kMkvChapterAtom, payload_size) + payload_size;
 
   if (writer == NULL)
     return atom_size;
@@ -1307,8 +1276,7 @@ uint64 Chapter::Display::WriteDisplay(IMkvWriter* writer) const {
     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;
@@ -1343,11 +1311,7 @@ uint64 Chapter::Display::WriteDisplay(IMkvWriter* writer) const {
 //
 // 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) {
@@ -1355,13 +1319,11 @@ Chapters::~Chapters() {
     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())
@@ -1411,7 +1373,7 @@ bool Chapters::ExpandChaptersArray() {
     src.ShallowCopy(dst);
   }
 
-  delete [] chapters_;
+  delete[] chapters_;
 
   chapters_ = chapters;
   chapters_size_ = size;
@@ -1428,8 +1390,7 @@ uint64 Chapters::WriteEdition(IMkvWriter* writer) const {
   }
 
   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;
@@ -1467,11 +1428,9 @@ Cluster::Cluster(uint64 timecode, int64 cues_pos)
       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) {
@@ -1481,55 +1440,40 @@ bool Cluster::Init(IMkvWriter* 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;
@@ -1554,121 +1498,123 @@ bool Cluster::Finalize() {
 
 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;
 }
 
@@ -1706,8 +1652,7 @@ SeekHead::SeekHead() : start_pos_(0ULL) {
   }
 }
 
-SeekHead::~SeekHead() {
-}
+SeekHead::~SeekHead() {}
 
 bool SeekHead::Finalize(IMkvWriter* writer) const {
   if (writer->Seekable()) {
@@ -1719,13 +1664,12 @@ bool SeekHead::Finalize(IMkvWriter* writer) const {
 
     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];
       }
     }
 
@@ -1745,8 +1689,7 @@ bool SeekHead::Finalize(IMkvWriter* writer) const {
         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;
 
@@ -1757,8 +1700,8 @@ bool SeekHead::Finalize(IMkvWriter* writer) const {
 
     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);
@@ -1836,12 +1779,12 @@ SegmentInfo::SegmentInfo()
       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() {
@@ -1852,26 +1795,16 @@ 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_)
@@ -1903,8 +1836,7 @@ bool SegmentInfo::Finalize(IMkvWriter* writer) const {
       if (writer->Position(duration_pos_))
         return false;
 
-      if (!WriteEbmlElement(writer,
-                            kMkvDuration,
+      if (!WriteEbmlElement(writer, kMkvDuration,
                             static_cast<float>(duration_)))
         return false;
 
@@ -1923,6 +1855,8 @@ bool SegmentInfo::Write(IMkvWriter* writer) {
   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_);
 
@@ -1944,6 +1878,9 @@ bool SegmentInfo::Write(IMkvWriter* writer) {
       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_))
@@ -1970,7 +1907,7 @@ void SegmentInfo::set_muxing_app(const char* app) {
     strcpy(temp_str, app);
 #endif
 
-    delete [] muxing_app_;
+    delete[] muxing_app_;
     muxing_app_ = temp_str;
   }
 }
@@ -1988,7 +1925,7 @@ void SegmentInfo::set_writing_app(const char* app) {
     strcpy(temp_str, app);
 #endif
 
-    delete [] writing_app_;
+    delete[] writing_app_;
     writing_app_ = temp_str;
   }
 }
@@ -2041,7 +1978,7 @@ Segment::~Segment() {
       Cluster* const cluster = cluster_list_[i];
       delete cluster;
     }
-    delete [] cluster_list_;
+    delete[] cluster_list_;
   }
 
   if (frames_) {
@@ -2049,11 +1986,11 @@ Segment::~Segment() {
       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();
@@ -2069,8 +2006,7 @@ Segment::~Segment() {
   }
 }
 
-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);
@@ -2087,9 +2023,9 @@ void Segment::MoveCuesBeforeClustersHelper(uint64 diff,
   //    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) {
@@ -2135,8 +2071,8 @@ bool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
                                             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))
@@ -2162,8 +2098,7 @@ bool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
   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;
 }
@@ -2175,7 +2110,7 @@ bool Segment::Finalize() {
   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;
@@ -2206,7 +2141,7 @@ bool Segment::Finalize() {
         return false;
 
       const bool cues_open = chunk_writer_cues_->Open(name);
-      delete [] name;
+      delete[] name;
       if (!cues_open)
         return false;
     }
@@ -2269,9 +2204,7 @@ Track* Segment::AddTrack(int32 number) {
   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
@@ -2290,10 +2223,10 @@ uint64 Segment::AddVideoTrack(int32 width, int32 height, int32 number) {
 }
 
 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;
 
@@ -2312,9 +2245,7 @@ bool Segment::AddCuePoint(uint64 timestamp, uint64 track) {
   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;
@@ -2329,11 +2260,8 @@ uint64 Segment::AddAudioTrack(int32 sample_rate,
   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;
 
@@ -2348,8 +2276,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);
@@ -2374,11 +2302,7 @@ bool Segment::AddFrame(const uint8* frame,
   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) {
@@ -2392,15 +2316,12 @@ bool Segment::AddFrame(const uint8* frame,
   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())
@@ -2414,8 +2335,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);
@@ -2434,21 +2355,77 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
     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_))
@@ -2461,10 +2438,8 @@ bool Segment::AddFrameWithAdditional(const uint8* frame,
   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;
@@ -2482,7 +2457,7 @@ bool Segment::AddMetadata(const uint8* frame,
   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;
@@ -2491,10 +2466,7 @@ bool Segment::AddMetadata(const uint8* frame,
   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;
 
@@ -2507,34 +2479,25 @@ bool Segment::AddMetadata(const uint8* frame,
 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)
@@ -2559,7 +2522,7 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
     strcpy(temp, filename);
 #endif
 
-    delete [] chunking_base_name_;
+    delete[] chunking_base_name_;
     chunking_base_name_ = temp;
 
     if (!UpdateChunkName("chk", &chunk_name_))
@@ -2599,7 +2562,7 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
     strcat(header, ".hdr");
 #endif
     if (!chunk_writer_header_->Open(header)) {
-      delete [] header;
+      delete[] header;
       return false;
     }
 
@@ -2607,7 +2570,7 @@ bool Segment::SetChunking(bool chunking, const char* filename) {
     writer_cues_ = chunk_writer_cues_;
     writer_header_ = chunk_writer_header_;
 
-    delete [] header;
+    delete[] header;
   }
 
   chunking_ = chunking;
@@ -2624,9 +2587,7 @@ bool Segment::CuesTrack(uint64 track_number) {
   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);
@@ -2651,7 +2612,7 @@ bool Segment::WriteSegmentHeader() {
   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
@@ -2695,8 +2656,7 @@ bool Segment::WriteSegmentHeader() {
 // 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;
@@ -2726,7 +2686,7 @@ int Segment::TestFrame(uint64 track_number,
   // 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
@@ -2776,7 +2736,7 @@ bool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
     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;
 
@@ -2784,7 +2744,7 @@ bool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
       clusters[i] = cluster_list_[i];
     }
 
-    delete [] cluster_list_;
+    delete[] cluster_list_;
 
     cluster_list_ = clusters;
     cluster_list_capacity_ = new_capacity;
@@ -2844,8 +2804,7 @@ bool Segment::MakeNewCluster(uint64 frame_timestamp_ns) {
 }
 
 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.
@@ -2853,12 +2812,12 @@ bool Segment::DoNewClusterProcessing(uint64 track_number,
     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();
@@ -2927,14 +2886,14 @@ bool Segment::UpdateChunkName(const char* ext, char** name) const {
     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;
@@ -2969,7 +2928,7 @@ bool Segment::QueueFrame(Frame* frame) {
     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;
 
@@ -2977,7 +2936,7 @@ bool Segment::QueueFrame(Frame* frame) {
       frames[i] = frames_[i];
     }
 
-    delete [] frames_;
+    delete[] frames_;
     frames_ = frames;
     frames_capacity_ = new_capacity;
   }
@@ -2994,7 +2953,7 @@ int Segment::WriteFramesAll() {
   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;
@@ -3006,12 +2965,19 @@ 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_))
@@ -3039,7 +3005,7 @@ bool Segment::WriteFramesLessThan(uint64 timestamp) {
     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;
 
@@ -3054,16 +3020,25 @@ bool Segment::WriteFramesLessThan(uint64 timestamp) {
       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_))
@@ -3083,7 +3058,7 @@ bool Segment::WriteFramesLessThan(uint64 timestamp) {
 
       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;