summaryrefslogtreecommitdiff
path: root/third_party/libwebm
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebm')
-rw-r--r--third_party/libwebm/README.libvpx3
-rw-r--r--third_party/libwebm/common/file_util.cc17
-rw-r--r--third_party/libwebm/common/hdr_util.cc168
-rw-r--r--third_party/libwebm/common/hdr_util.h24
-rw-r--r--third_party/libwebm/common/webmids.h8
-rw-r--r--third_party/libwebm/mkvmuxer/mkvmuxer.cc814
-rw-r--r--third_party/libwebm/mkvmuxer/mkvmuxer.h302
-rw-r--r--third_party/libwebm/mkvmuxer/mkvmuxerutil.cc325
-rw-r--r--third_party/libwebm/mkvmuxer/mkvmuxerutil.h85
-rw-r--r--third_party/libwebm/mkvmuxer/mkvwriter.cc2
-rw-r--r--third_party/libwebm/mkvparser/mkvparser.cc112
-rw-r--r--third_party/libwebm/mkvparser/mkvparser.h33
-rw-r--r--third_party/libwebm/mkvparser/mkvreader.cc4
13 files changed, 1408 insertions, 489 deletions
diff --git a/third_party/libwebm/README.libvpx b/third_party/libwebm/README.libvpx
index 73f830322..83250221c 100644
--- a/third_party/libwebm/README.libvpx
+++ b/third_party/libwebm/README.libvpx
@@ -1,5 +1,6 @@
URL: https://chromium.googlesource.com/webm/libwebm
-Version: 32d5ac49414a8914ec1e1f285f3f927c6e8ec29d
+Version: fc5f88d3d1914e027456c069d91a0cd6c89dec85
+
License: BSD
License File: LICENSE.txt
diff --git a/third_party/libwebm/common/file_util.cc b/third_party/libwebm/common/file_util.cc
index 4f91318f3..6dab146dd 100644
--- a/third_party/libwebm/common/file_util.cc
+++ b/third_party/libwebm/common/file_util.cc
@@ -14,6 +14,7 @@
#include <cstdio>
#include <cstdlib>
+#include <cstring>
#include <fstream>
#include <ios>
@@ -21,13 +22,23 @@ namespace libwebm {
std::string GetTempFileName() {
#if !defined _MSC_VER && !defined __MINGW32__
- char temp_file_name_template[] = "libwebm_temp.XXXXXX";
+ std::string temp_file_name_template_str =
+ std::string(std::getenv("TEST_TMPDIR") ? std::getenv("TEST_TMPDIR") :
+ ".") +
+ "/libwebm_temp.XXXXXX";
+ char* temp_file_name_template =
+ new char[temp_file_name_template_str.length() + 1];
+ memset(temp_file_name_template, 0, temp_file_name_template_str.length() + 1);
+ temp_file_name_template_str.copy(temp_file_name_template,
+ temp_file_name_template_str.length(), 0);
int fd = mkstemp(temp_file_name_template);
+ std::string temp_file_name =
+ (fd != -1) ? std::string(temp_file_name_template) : std::string();
+ delete[] temp_file_name_template;
if (fd != -1) {
close(fd);
- return std::string(temp_file_name_template);
}
- return std::string();
+ return temp_file_name;
#else
char tmp_file_name[_MAX_PATH];
errno_t err = tmpnam_s(tmp_file_name);
diff --git a/third_party/libwebm/common/hdr_util.cc b/third_party/libwebm/common/hdr_util.cc
index e1a9842fb..e1618ce75 100644
--- a/third_party/libwebm/common/hdr_util.cc
+++ b/third_party/libwebm/common/hdr_util.cc
@@ -7,12 +7,15 @@
// be found in the AUTHORS file in the root of the source tree.
#include "hdr_util.h"
+#include <climits>
#include <cstddef>
#include <new>
#include "mkvparser/mkvparser.h"
namespace libwebm {
+const int Vp9CodecFeatures::kValueNotPresent = INT_MAX;
+
bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
PrimaryChromaticityPtr* muxer_pc) {
muxer_pc->reset(new (std::nothrow)
@@ -29,9 +32,9 @@ bool MasteringMetadataValuePresent(double value) {
bool CopyMasteringMetadata(const mkvparser::MasteringMetadata& parser_mm,
mkvmuxer::MasteringMetadata* muxer_mm) {
if (MasteringMetadataValuePresent(parser_mm.luminance_max))
- muxer_mm->luminance_max = parser_mm.luminance_max;
+ muxer_mm->set_luminance_max(parser_mm.luminance_max);
if (MasteringMetadataValuePresent(parser_mm.luminance_min))
- muxer_mm->luminance_min = parser_mm.luminance_min;
+ muxer_mm->set_luminance_min(parser_mm.luminance_min);
PrimaryChromaticityPtr r_ptr(NULL);
PrimaryChromaticityPtr g_ptr(NULL);
@@ -73,34 +76,37 @@ bool CopyColour(const mkvparser::Colour& parser_colour,
return false;
if (ColourValuePresent(parser_colour.matrix_coefficients))
- muxer_colour->matrix_coefficients = parser_colour.matrix_coefficients;
+ muxer_colour->set_matrix_coefficients(parser_colour.matrix_coefficients);
if (ColourValuePresent(parser_colour.bits_per_channel))
- muxer_colour->bits_per_channel = parser_colour.bits_per_channel;
- if (ColourValuePresent(parser_colour.chroma_subsampling_horz))
- muxer_colour->chroma_subsampling_horz =
- parser_colour.chroma_subsampling_horz;
- if (ColourValuePresent(parser_colour.chroma_subsampling_vert))
- muxer_colour->chroma_subsampling_vert =
- parser_colour.chroma_subsampling_vert;
+ muxer_colour->set_bits_per_channel(parser_colour.bits_per_channel);
+ if (ColourValuePresent(parser_colour.chroma_subsampling_horz)) {
+ muxer_colour->set_chroma_subsampling_horz(
+ parser_colour.chroma_subsampling_horz);
+ }
+ if (ColourValuePresent(parser_colour.chroma_subsampling_vert)) {
+ muxer_colour->set_chroma_subsampling_vert(
+ parser_colour.chroma_subsampling_vert);
+ }
if (ColourValuePresent(parser_colour.cb_subsampling_horz))
- muxer_colour->cb_subsampling_horz = parser_colour.cb_subsampling_horz;
+ muxer_colour->set_cb_subsampling_horz(parser_colour.cb_subsampling_horz);
if (ColourValuePresent(parser_colour.cb_subsampling_vert))
- muxer_colour->cb_subsampling_vert = parser_colour.cb_subsampling_vert;
+ muxer_colour->set_cb_subsampling_vert(parser_colour.cb_subsampling_vert);
if (ColourValuePresent(parser_colour.chroma_siting_horz))
- muxer_colour->chroma_siting_horz = parser_colour.chroma_siting_horz;
+ muxer_colour->set_chroma_siting_horz(parser_colour.chroma_siting_horz);
if (ColourValuePresent(parser_colour.chroma_siting_vert))
- muxer_colour->chroma_siting_vert = parser_colour.chroma_siting_vert;
+ muxer_colour->set_chroma_siting_vert(parser_colour.chroma_siting_vert);
if (ColourValuePresent(parser_colour.range))
- muxer_colour->range = parser_colour.range;
- if (ColourValuePresent(parser_colour.transfer_characteristics))
- muxer_colour->transfer_characteristics =
- parser_colour.transfer_characteristics;
+ muxer_colour->set_range(parser_colour.range);
+ if (ColourValuePresent(parser_colour.transfer_characteristics)) {
+ muxer_colour->set_transfer_characteristics(
+ parser_colour.transfer_characteristics);
+ }
if (ColourValuePresent(parser_colour.primaries))
- muxer_colour->primaries = parser_colour.primaries;
+ muxer_colour->set_primaries(parser_colour.primaries);
if (ColourValuePresent(parser_colour.max_cll))
- muxer_colour->max_cll = parser_colour.max_cll;
+ muxer_colour->set_max_cll(parser_colour.max_cll);
if (ColourValuePresent(parser_colour.max_fall))
- muxer_colour->max_fall = parser_colour.max_fall;
+ muxer_colour->set_max_fall(parser_colour.max_fall);
if (parser_colour.mastering_metadata) {
mkvmuxer::MasteringMetadata muxer_mm;
@@ -116,8 +122,8 @@ bool CopyColour(const mkvparser::Colour& parser_colour,
//
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | ID Byte | Length | |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+// | ID Byte | Length | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
// | |
// : Bytes 1..Length of Codec Feature :
// | |
@@ -132,51 +138,83 @@ bool CopyColour(const mkvparser::Colour& parser_colour,
//
// The X bit is reserved.
//
-// Currently only profile level is supported. ID byte must be set to 1, and
-// length must be 1. Supported values are:
-//
-// 10: Level 1
-// 11: Level 1.1
-// 20: Level 2
-// 21: Level 2.1
-// 30: Level 3
-// 31: Level 3.1
-// 40: Level 4
-// 41: Level 4.1
-// 50: Level 5
-// 51: Level 5.1
-// 52: Level 5.2
-// 60: Level 6
-// 61: Level 6.1
-// 62: Level 6.2
-//
// See the following link for more information:
// http://www.webmproject.org/vp9/profiles/
-int ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length) {
- const int kVpxCodecPrivateLength = 3;
- if (!private_data || length != kVpxCodecPrivateLength)
- return 0;
-
- const uint8_t id_byte = *private_data;
- if (id_byte != 1)
- return 0;
-
- const int kVpxProfileLength = 1;
- const uint8_t length_byte = private_data[1];
- if (length_byte != kVpxProfileLength)
- return 0;
-
- const int level = static_cast<int>(private_data[2]);
-
- const int kNumLevels = 14;
- const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
- 41, 50, 51, 52, 60, 61, 62};
+bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length,
+ Vp9CodecFeatures* features) {
+ const int kVpxCodecPrivateMinLength = 3;
+ if (!private_data || !features || length < kVpxCodecPrivateMinLength)
+ return false;
- for (int i = 0; i < kNumLevels; ++i) {
- if (level == levels[i])
- return level;
- }
+ const uint8_t kVp9ProfileId = 1;
+ const uint8_t kVp9LevelId = 2;
+ const uint8_t kVp9BitDepthId = 3;
+ const uint8_t kVp9ChromaSubsamplingId = 4;
+ const int kVpxFeatureLength = 1;
+ int offset = 0;
+
+ // Set features to not set.
+ features->profile = Vp9CodecFeatures::kValueNotPresent;
+ features->level = Vp9CodecFeatures::kValueNotPresent;
+ features->bit_depth = Vp9CodecFeatures::kValueNotPresent;
+ features->chroma_subsampling = Vp9CodecFeatures::kValueNotPresent;
+ do {
+ const uint8_t id_byte = private_data[offset++];
+ const uint8_t length_byte = private_data[offset++];
+ if (length_byte != kVpxFeatureLength)
+ return false;
+ if (id_byte == kVp9ProfileId) {
+ const int priv_profile = static_cast<int>(private_data[offset++]);
+ if (priv_profile < 0 || priv_profile > 3)
+ return false;
+ if (features->profile != Vp9CodecFeatures::kValueNotPresent &&
+ features->profile != priv_profile) {
+ return false;
+ }
+ features->profile = priv_profile;
+ } else if (id_byte == kVp9LevelId) {
+ const int priv_level = static_cast<int>(private_data[offset++]);
+
+ const int kNumLevels = 14;
+ const int levels[kNumLevels] = {10, 11, 20, 21, 30, 31, 40,
+ 41, 50, 51, 52, 60, 61, 62};
+
+ for (int i = 0; i < kNumLevels; ++i) {
+ if (priv_level == levels[i]) {
+ if (features->level != Vp9CodecFeatures::kValueNotPresent &&
+ features->level != priv_level) {
+ return false;
+ }
+ features->level = priv_level;
+ break;
+ }
+ }
+ if (features->level == Vp9CodecFeatures::kValueNotPresent)
+ return false;
+ } else if (id_byte == kVp9BitDepthId) {
+ const int priv_profile = static_cast<int>(private_data[offset++]);
+ if (priv_profile != 8 && priv_profile != 10 && priv_profile != 12)
+ return false;
+ if (features->bit_depth != Vp9CodecFeatures::kValueNotPresent &&
+ features->bit_depth != priv_profile) {
+ return false;
+ }
+ features->bit_depth = priv_profile;
+ } else if (id_byte == kVp9ChromaSubsamplingId) {
+ const int priv_profile = static_cast<int>(private_data[offset++]);
+ if (priv_profile != 0 && priv_profile != 2 && priv_profile != 3)
+ return false;
+ if (features->chroma_subsampling != Vp9CodecFeatures::kValueNotPresent &&
+ features->chroma_subsampling != priv_profile) {
+ return false;
+ }
+ features->chroma_subsampling = priv_profile;
+ } else {
+ // Invalid ID.
+ return false;
+ }
+ } while (offset + kVpxCodecPrivateMinLength <= length);
- return 0;
+ return true;
}
} // namespace libwebm
diff --git a/third_party/libwebm/common/hdr_util.h b/third_party/libwebm/common/hdr_util.h
index d30c2b9f2..689fb30a3 100644
--- a/third_party/libwebm/common/hdr_util.h
+++ b/third_party/libwebm/common/hdr_util.h
@@ -28,6 +28,25 @@ namespace libwebm {
// TODO(tomfinegan): These should be moved to libwebm_utils once c++11 is
// required by libwebm.
+// Features of the VP9 codec that may be set in the CodecPrivate of a VP9 video
+// stream. A value of kValueNotPresent represents that the value was not set in
+// the CodecPrivate.
+struct Vp9CodecFeatures {
+ static const int kValueNotPresent;
+
+ Vp9CodecFeatures()
+ : profile(kValueNotPresent),
+ level(kValueNotPresent),
+ bit_depth(kValueNotPresent),
+ chroma_subsampling(kValueNotPresent) {}
+ ~Vp9CodecFeatures() {}
+
+ int profile;
+ int level;
+ int bit_depth;
+ int chroma_subsampling;
+};
+
typedef std::auto_ptr<mkvmuxer::PrimaryChromaticity> PrimaryChromaticityPtr;
bool CopyPrimaryChromaticity(const mkvparser::PrimaryChromaticity& parser_pc,
@@ -43,8 +62,9 @@ bool ColourValuePresent(long long value);
bool CopyColour(const mkvparser::Colour& parser_colour,
mkvmuxer::Colour* muxer_colour);
-// Returns VP9 profile upon success or 0 upon failure.
-int ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length);
+// Returns true if |features| is set to one or more valid values.
+bool ParseVpxCodecPrivate(const uint8_t* private_data, int32_t length,
+ Vp9CodecFeatures* features);
} // namespace libwebm
diff --git a/third_party/libwebm/common/webmids.h b/third_party/libwebm/common/webmids.h
index 32a0c5fb9..89d722a71 100644
--- a/third_party/libwebm/common/webmids.h
+++ b/third_party/libwebm/common/webmids.h
@@ -124,6 +124,14 @@ enum MkvId {
kMkvLuminanceMin = 0x55DA,
// end mastering metadata
// end colour
+ // projection
+ kMkvProjection = 0x7670,
+ kMkvProjectionType = 0x7671,
+ kMkvProjectionPrivate = 0x7672,
+ kMkvProjectionPoseYaw = 0x7673,
+ kMkvProjectionPosePitch = 0x7674,
+ kMkvProjectionPoseRoll = 0x7675,
+ // end projection
// audio
kMkvAudio = 0xE1,
kMkvSamplingFrequency = 0xB5,
diff --git a/third_party/libwebm/mkvmuxer/mkvmuxer.cc b/third_party/libwebm/mkvmuxer/mkvmuxer.cc
index c79ce24ed..31920c744 100644
--- a/third_party/libwebm/mkvmuxer/mkvmuxer.cc
+++ b/third_party/libwebm/mkvmuxer/mkvmuxer.cc
@@ -16,6 +16,7 @@
#include <ctime>
#include <memory>
#include <new>
+#include <string>
#include <vector>
#include "common/webmids.h"
@@ -25,10 +26,19 @@
namespace mkvmuxer {
+const float PrimaryChromaticity::kChromaticityMin = 0.0f;
+const float PrimaryChromaticity::kChromaticityMax = 1.0f;
+const float MasteringMetadata::kMinLuminance = 0.0f;
+const float MasteringMetadata::kMinLuminanceMax = 999.99f;
+const float MasteringMetadata::kMaxLuminanceMax = 9999.99f;
const float MasteringMetadata::kValueNotPresent = FLT_MAX;
const uint64_t Colour::kValueNotPresent = UINT64_MAX;
namespace {
+
+const char kDocTypeWebm[] = "webm";
+const char kDocTypeMatroska[] = "matroska";
+
// Deallocate the string designated by |dst|, and then copy the |src|
// string to |dst|. The caller owns both the |src| string and the
// |dst| copy (hence the caller is responsible for eventually
@@ -63,7 +73,7 @@ bool CopyChromaticity(const PrimaryChromaticity* src,
if (!dst)
return false;
- dst->reset(new (std::nothrow) PrimaryChromaticity(src->x, src->y));
+ dst->reset(new (std::nothrow) PrimaryChromaticity(src->x(), src->y()));
if (!dst->get())
return false;
@@ -80,36 +90,57 @@ IMkvWriter::IMkvWriter() {}
IMkvWriter::~IMkvWriter() {}
-bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version) {
+bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version,
+ const char* const doc_type) {
// Level 0
- uint64_t size = EbmlElementSize(libwebm::kMkvEBMLVersion, UINT64_C(1));
- size += EbmlElementSize(libwebm::kMkvEBMLReadVersion, UINT64_C(1));
- size += EbmlElementSize(libwebm::kMkvEBMLMaxIDLength, UINT64_C(4));
- size += EbmlElementSize(libwebm::kMkvEBMLMaxSizeLength, UINT64_C(8));
- size += EbmlElementSize(libwebm::kMkvDocType, "webm");
- size += EbmlElementSize(libwebm::kMkvDocTypeVersion, doc_type_version);
- size += EbmlElementSize(libwebm::kMkvDocTypeReadVersion, UINT64_C(2));
+ uint64_t size =
+ EbmlElementSize(libwebm::kMkvEBMLVersion, static_cast<uint64>(1));
+ size += EbmlElementSize(libwebm::kMkvEBMLReadVersion, static_cast<uint64>(1));
+ size += EbmlElementSize(libwebm::kMkvEBMLMaxIDLength, static_cast<uint64>(4));
+ size +=
+ EbmlElementSize(libwebm::kMkvEBMLMaxSizeLength, static_cast<uint64>(8));
+ size += EbmlElementSize(libwebm::kMkvDocType, doc_type);
+ size += EbmlElementSize(libwebm::kMkvDocTypeVersion,
+ static_cast<uint64>(doc_type_version));
+ size +=
+ EbmlElementSize(libwebm::kMkvDocTypeReadVersion, static_cast<uint64>(2));
if (!WriteEbmlMasterElement(writer, libwebm::kMkvEBML, size))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvEBMLVersion, UINT64_C(1)))
+ if (!WriteEbmlElement(writer, libwebm::kMkvEBMLVersion,
+ static_cast<uint64>(1))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvEBMLReadVersion, UINT64_C(1)))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvEBMLReadVersion,
+ static_cast<uint64>(1))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxIDLength, UINT64_C(4)))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxIDLength,
+ static_cast<uint64>(4))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxSizeLength, UINT64_C(8)))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxSizeLength,
+ static_cast<uint64>(8))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvDocType, "webm"))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvDocType, doc_type))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeVersion, doc_type_version))
+ if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeVersion,
+ static_cast<uint64>(doc_type_version))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeReadVersion, UINT64_C(2)))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeReadVersion,
+ static_cast<uint64>(2))) {
return false;
+ }
return true;
}
+bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version) {
+ return WriteEbmlHeader(writer, doc_type_version, kDocTypeWebm);
+}
+
bool WriteEbmlHeader(IMkvWriter* writer) {
return WriteEbmlHeader(writer, mkvmuxer::Segment::kDefaultDocTypeVersion);
}
@@ -262,15 +293,17 @@ bool CuePoint::Write(IMkvWriter* writer) const {
if (!writer || track_ < 1 || cluster_pos_ < 1)
return false;
- uint64_t size =
- EbmlElementSize(libwebm::kMkvCueClusterPosition, cluster_pos_);
- size += EbmlElementSize(libwebm::kMkvCueTrack, track_);
+ uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition,
+ static_cast<uint64>(cluster_pos_));
+ size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast<uint64>(track_));
if (output_block_number_ && block_number_ > 1)
- size += EbmlElementSize(libwebm::kMkvCueBlockNumber, block_number_);
+ size += EbmlElementSize(libwebm::kMkvCueBlockNumber,
+ static_cast<uint64>(block_number_));
const uint64_t track_pos_size =
EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size;
const uint64_t payload_size =
- EbmlElementSize(libwebm::kMkvCueTime, time_) + track_pos_size;
+ EbmlElementSize(libwebm::kMkvCueTime, static_cast<uint64>(time_)) +
+ track_pos_size;
if (!WriteEbmlMasterElement(writer, libwebm::kMkvCuePoint, payload_size))
return false;
@@ -279,18 +312,27 @@ bool CuePoint::Write(IMkvWriter* writer) const {
if (payload_position < 0)
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvCueTime, time_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvCueTime,
+ static_cast<uint64>(time_))) {
return false;
+ }
if (!WriteEbmlMasterElement(writer, libwebm::kMkvCueTrackPositions, size))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvCueTrack, track_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvCueTrack,
+ static_cast<uint64>(track_))) {
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvCueClusterPosition, cluster_pos_))
+ }
+ if (!WriteEbmlElement(writer, libwebm::kMkvCueClusterPosition,
+ static_cast<uint64>(cluster_pos_))) {
return false;
- if (output_block_number_ && block_number_ > 1)
- if (!WriteEbmlElement(writer, libwebm::kMkvCueBlockNumber, block_number_))
+ }
+ if (output_block_number_ && block_number_ > 1) {
+ if (!WriteEbmlElement(writer, libwebm::kMkvCueBlockNumber,
+ static_cast<uint64>(block_number_))) {
return false;
+ }
+ }
const int64_t stop_position = writer->Position();
if (stop_position < 0)
@@ -303,15 +345,17 @@ bool CuePoint::Write(IMkvWriter* writer) const {
}
uint64_t CuePoint::PayloadSize() const {
- uint64_t size =
- EbmlElementSize(libwebm::kMkvCueClusterPosition, cluster_pos_);
- size += EbmlElementSize(libwebm::kMkvCueTrack, track_);
+ uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition,
+ static_cast<uint64>(cluster_pos_));
+ size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast<uint64>(track_));
if (output_block_number_ && block_number_ > 1)
- size += EbmlElementSize(libwebm::kMkvCueBlockNumber, block_number_);
+ size += EbmlElementSize(libwebm::kMkvCueBlockNumber,
+ static_cast<uint64>(block_number_));
const uint64_t track_pos_size =
EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size;
const uint64_t payload_size =
- EbmlElementSize(libwebm::kMkvCueTime, time_) + track_pos_size;
+ EbmlElementSize(libwebm::kMkvCueTime, static_cast<uint64>(time_)) +
+ track_pos_size;
return payload_size;
}
@@ -456,8 +500,9 @@ bool ContentEncAESSettings::Write(IMkvWriter* writer) const {
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvAESSettingsCipherMode,
- cipher_mode_))
+ static_cast<uint64>(cipher_mode_))) {
return false;
+ }
const int64_t stop_position = writer->Position();
if (stop_position < 0 ||
@@ -468,8 +513,8 @@ bool ContentEncAESSettings::Write(IMkvWriter* writer) const {
}
uint64_t ContentEncAESSettings::PayloadSize() const {
- uint64_t size =
- EbmlElementSize(libwebm::kMkvAESSettingsCipherMode, cipher_mode_);
+ uint64_t size = EbmlElementSize(libwebm::kMkvAESSettingsCipherMode,
+ static_cast<uint64>(cipher_mode_));
return size;
}
@@ -529,20 +574,22 @@ bool ContentEncoding::Write(IMkvWriter* writer) const {
encoding_size))
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingOrder,
- encoding_order_))
+ static_cast<uint64>(encoding_order_)))
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingScope,
- encoding_scope_))
+ static_cast<uint64>(encoding_scope_)))
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingType,
- encoding_type_))
+ static_cast<uint64>(encoding_type_)))
return false;
if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncryption,
encryption_size))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvContentEncAlgo, enc_algo_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvContentEncAlgo,
+ static_cast<uint64>(enc_algo_))) {
return false;
+ }
if (!WriteEbmlElement(writer, libwebm::kMkvContentEncKeyID, enc_key_id_,
enc_key_id_length_))
return false;
@@ -571,12 +618,12 @@ uint64_t ContentEncoding::EncodingSize(uint64_t compresion_size,
EbmlMasterElementSize(libwebm::kMkvContentEncryption, encryption_size) +
encryption_size;
}
- encoding_size +=
- EbmlElementSize(libwebm::kMkvContentEncodingType, encoding_type_);
- encoding_size +=
- EbmlElementSize(libwebm::kMkvContentEncodingScope, encoding_scope_);
- encoding_size +=
- EbmlElementSize(libwebm::kMkvContentEncodingOrder, encoding_order_);
+ encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingType,
+ static_cast<uint64>(encoding_type_));
+ encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingScope,
+ static_cast<uint64>(encoding_scope_));
+ encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingOrder,
+ static_cast<uint64>(encoding_order_));
return encoding_size;
}
@@ -586,7 +633,8 @@ uint64_t ContentEncoding::EncryptionSize() const {
uint64_t encryption_size = EbmlElementSize(libwebm::kMkvContentEncKeyID,
enc_key_id_, enc_key_id_length_);
- encryption_size += EbmlElementSize(libwebm::kMkvContentEncAlgo, enc_algo_);
+ encryption_size += EbmlElementSize(libwebm::kMkvContentEncAlgo,
+ static_cast<uint64>(enc_algo_));
return encryption_size + aes_size;
}
@@ -664,9 +712,10 @@ ContentEncoding* Track::GetContentEncodingByIndex(uint32_t index) const {
}
uint64_t Track::PayloadSize() const {
- uint64_t size = EbmlElementSize(libwebm::kMkvTrackNumber, number_);
- size += EbmlElementSize(libwebm::kMkvTrackUID, uid_);
- size += EbmlElementSize(libwebm::kMkvTrackType, type_);
+ uint64_t size =
+ EbmlElementSize(libwebm::kMkvTrackNumber, static_cast<uint64>(number_));
+ size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast<uint64>(uid_));
+ size += EbmlElementSize(libwebm::kMkvTrackType, static_cast<uint64>(type_));
if (codec_id_)
size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_);
if (codec_private_)
@@ -676,15 +725,22 @@ uint64_t Track::PayloadSize() const {
size += EbmlElementSize(libwebm::kMkvLanguage, language_);
if (name_)
size += EbmlElementSize(libwebm::kMkvName, name_);
- if (max_block_additional_id_)
+ if (max_block_additional_id_) {
size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID,
- max_block_additional_id_);
- if (codec_delay_)
- size += EbmlElementSize(libwebm::kMkvCodecDelay, codec_delay_);
- if (seek_pre_roll_)
- size += EbmlElementSize(libwebm::kMkvSeekPreRoll, seek_pre_roll_);
- if (default_duration_)
- size += EbmlElementSize(libwebm::kMkvDefaultDuration, default_duration_);
+ static_cast<uint64>(max_block_additional_id_));
+ }
+ if (codec_delay_) {
+ size += EbmlElementSize(libwebm::kMkvCodecDelay,
+ static_cast<uint64>(codec_delay_));
+ }
+ if (seek_pre_roll_) {
+ size += EbmlElementSize(libwebm::kMkvSeekPreRoll,
+ static_cast<uint64>(seek_pre_roll_));
+ }
+ if (default_duration_) {
+ size += EbmlElementSize(libwebm::kMkvDefaultDuration,
+ static_cast<uint64>(default_duration_));
+ }
if (content_encoding_entries_size_ > 0) {
uint64_t content_encodings_size = 0;
@@ -722,55 +778,64 @@ bool Track::Write(IMkvWriter* writer) const {
if (!WriteEbmlMasterElement(writer, libwebm::kMkvTrackEntry, payload_size))
return false;
- uint64_t size = EbmlElementSize(libwebm::kMkvTrackNumber, number_);
- size += EbmlElementSize(libwebm::kMkvTrackUID, uid_);
- size += EbmlElementSize(libwebm::kMkvTrackType, type_);
+ uint64_t size =
+ EbmlElementSize(libwebm::kMkvTrackNumber, static_cast<uint64>(number_));
+ size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast<uint64>(uid_));
+ size += EbmlElementSize(libwebm::kMkvTrackType, static_cast<uint64>(type_));
if (codec_id_)
size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_);
if (codec_private_)
size += EbmlElementSize(libwebm::kMkvCodecPrivate, codec_private_,
- codec_private_length_);
+ static_cast<uint64>(codec_private_length_));
if (language_)
size += EbmlElementSize(libwebm::kMkvLanguage, language_);
if (name_)
size += EbmlElementSize(libwebm::kMkvName, name_);
if (max_block_additional_id_)
size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID,
- max_block_additional_id_);
+ static_cast<uint64>(max_block_additional_id_));
if (codec_delay_)
- size += EbmlElementSize(libwebm::kMkvCodecDelay, codec_delay_);
+ size += EbmlElementSize(libwebm::kMkvCodecDelay,
+ static_cast<uint64>(codec_delay_));
if (seek_pre_roll_)
- size += EbmlElementSize(libwebm::kMkvSeekPreRoll, seek_pre_roll_);
+ size += EbmlElementSize(libwebm::kMkvSeekPreRoll,
+ static_cast<uint64>(seek_pre_roll_));
if (default_duration_)
- size += EbmlElementSize(libwebm::kMkvDefaultDuration, default_duration_);
+ size += EbmlElementSize(libwebm::kMkvDefaultDuration,
+ static_cast<uint64>(default_duration_));
const int64_t payload_position = writer->Position();
if (payload_position < 0)
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvTrackNumber, number_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvTrackNumber,
+ static_cast<uint64>(number_)))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvTrackUID, uid_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvTrackUID,
+ static_cast<uint64>(uid_)))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvTrackType, type_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvTrackType,
+ static_cast<uint64>(type_)))
return false;
if (max_block_additional_id_) {
if (!WriteEbmlElement(writer, libwebm::kMkvMaxBlockAdditionID,
- max_block_additional_id_)) {
+ static_cast<uint64>(max_block_additional_id_))) {
return false;
}
}
if (codec_delay_) {
- if (!WriteEbmlElement(writer, libwebm::kMkvCodecDelay, codec_delay_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvCodecDelay,
+ static_cast<uint64>(codec_delay_)))
return false;
}
if (seek_pre_roll_) {
- if (!WriteEbmlElement(writer, libwebm::kMkvSeekPreRoll, seek_pre_roll_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvSeekPreRoll,
+ static_cast<uint64>(seek_pre_roll_)))
return false;
}
if (default_duration_) {
if (!WriteEbmlElement(writer, libwebm::kMkvDefaultDuration,
- default_duration_))
+ static_cast<uint64>(default_duration_)))
return false;
}
if (codec_id_) {
@@ -779,7 +844,7 @@ bool Track::Write(IMkvWriter* writer) const {
}
if (codec_private_) {
if (!WriteEbmlElement(writer, libwebm::kMkvCodecPrivate, codec_private_,
- codec_private_length_))
+ static_cast<uint64>(codec_private_length_)))
return false;
}
if (language_) {
@@ -890,14 +955,23 @@ void Track::set_name(const char* name) {
//
// Colour and its child elements
-uint64_t PrimaryChromaticity::PrimaryChromaticityPayloadSize(
+uint64_t PrimaryChromaticity::PrimaryChromaticitySize(
libwebm::MkvId x_id, libwebm::MkvId y_id) const {
- return EbmlElementSize(x_id, x) + EbmlElementSize(y_id, y);
+ return EbmlElementSize(x_id, x_) + EbmlElementSize(y_id, y_);
}
bool PrimaryChromaticity::Write(IMkvWriter* writer, libwebm::MkvId x_id,
libwebm::MkvId y_id) const {
- return WriteEbmlElement(writer, x_id, x) && WriteEbmlElement(writer, y_id, y);
+ if (!Valid()) {
+ return false;
+ }
+ return WriteEbmlElement(writer, x_id, x_) &&
+ WriteEbmlElement(writer, y_id, y_);
+}
+
+bool PrimaryChromaticity::Valid() const {
+ return (x_ >= kChromaticityMin && x_ <= kChromaticityMax &&
+ y_ >= kChromaticityMin && y_ <= kChromaticityMax);
}
uint64_t MasteringMetadata::MasteringMetadataSize() const {
@@ -909,6 +983,31 @@ uint64_t MasteringMetadata::MasteringMetadataSize() const {
return size;
}
+bool MasteringMetadata::Valid() const {
+ if (luminance_min_ != kValueNotPresent) {
+ if (luminance_min_ < kMinLuminance || luminance_min_ > kMinLuminanceMax ||
+ luminance_min_ > luminance_max_) {
+ return false;
+ }
+ }
+ if (luminance_max_ != kValueNotPresent) {
+ if (luminance_max_ < kMinLuminance || luminance_max_ > kMaxLuminanceMax ||
+ luminance_max_ < luminance_min_) {
+ return false;
+ }
+ }
+ if (r_ && !r_->Valid())
+ return false;
+ if (g_ && !g_->Valid())
+ return false;
+ if (b_ && !b_->Valid())
+ return false;
+ if (white_point_ && !white_point_->Valid())
+ return false;
+
+ return true;
+}
+
bool MasteringMetadata::Write(IMkvWriter* writer) const {
const uint64_t size = PayloadSize();
@@ -918,12 +1017,12 @@ bool MasteringMetadata::Write(IMkvWriter* writer) const {
if (!WriteEbmlMasterElement(writer, libwebm::kMkvMasteringMetadata, size))
return false;
- if (luminance_max != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvLuminanceMax, luminance_max)) {
+ if (luminance_max_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvLuminanceMax, luminance_max_)) {
return false;
}
- if (luminance_min != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvLuminanceMin, luminance_min)) {
+ if (luminance_min_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvLuminanceMin, luminance_min_)) {
return false;
}
if (r_ &&
@@ -984,25 +1083,25 @@ bool MasteringMetadata::SetChromaticity(
uint64_t MasteringMetadata::PayloadSize() const {
uint64_t size = 0;
- if (luminance_max != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvLuminanceMax, luminance_max);
- if (luminance_min != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvLuminanceMin, luminance_min);
+ if (luminance_max_ != kValueNotPresent)
+ size += EbmlElementSize(libwebm::kMkvLuminanceMax, luminance_max_);
+ if (luminance_min_ != kValueNotPresent)
+ size += EbmlElementSize(libwebm::kMkvLuminanceMin, luminance_min_);
if (r_) {
- size += r_->PrimaryChromaticityPayloadSize(
- libwebm::kMkvPrimaryRChromaticityX, libwebm::kMkvPrimaryRChromaticityY);
+ size += r_->PrimaryChromaticitySize(libwebm::kMkvPrimaryRChromaticityX,
+ libwebm::kMkvPrimaryRChromaticityY);
}
if (g_) {
- size += g_->PrimaryChromaticityPayloadSize(
- libwebm::kMkvPrimaryGChromaticityX, libwebm::kMkvPrimaryGChromaticityY);
+ size += g_->PrimaryChromaticitySize(libwebm::kMkvPrimaryGChromaticityX,
+ libwebm::kMkvPrimaryGChromaticityY);
}
if (b_) {
- size += b_->PrimaryChromaticityPayloadSize(
- libwebm::kMkvPrimaryBChromaticityX, libwebm::kMkvPrimaryBChromaticityY);
+ size += b_->PrimaryChromaticitySize(libwebm::kMkvPrimaryBChromaticityX,
+ libwebm::kMkvPrimaryBChromaticityY);
}
if (white_point_) {
- size += white_point_->PrimaryChromaticityPayloadSize(
+ size += white_point_->PrimaryChromaticitySize(
libwebm::kMkvWhitePointChromaticityX,
libwebm::kMkvWhitePointChromaticityY);
}
@@ -1019,6 +1118,33 @@ uint64_t Colour::ColourSize() const {
return size;
}
+bool Colour::Valid() const {
+ if (mastering_metadata_ && !mastering_metadata_->Valid())
+ return false;
+ if (matrix_coefficients_ != kValueNotPresent &&
+ !IsMatrixCoefficientsValueValid(matrix_coefficients_)) {
+ return false;
+ }
+ if (chroma_siting_horz_ != kValueNotPresent &&
+ !IsChromaSitingHorzValueValid(chroma_siting_horz_)) {
+ return false;
+ }
+ if (chroma_siting_vert_ != kValueNotPresent &&
+ !IsChromaSitingVertValueValid(chroma_siting_vert_)) {
+ return false;
+ }
+ if (range_ != kValueNotPresent && !IsColourRangeValueValid(range_))
+ return false;
+ if (transfer_characteristics_ != kValueNotPresent &&
+ !IsTransferCharacteristicsValueValid(transfer_characteristics_)) {
+ return false;
+ }
+ if (primaries_ != kValueNotPresent && !IsPrimariesValueValid(primaries_))
+ return false;
+
+ return true;
+}
+
bool Colour::Write(IMkvWriter* writer) const {
const uint64_t size = PayloadSize();
@@ -1026,69 +1152,77 @@ bool Colour::Write(IMkvWriter* writer) const {
if (size == 0)
return true;
+ // Don't write an invalid element.
+ if (!Valid())
+ return false;
+
if (!WriteEbmlMasterElement(writer, libwebm::kMkvColour, size))
return false;
- if (matrix_coefficients != kValueNotPresent &&
+ if (matrix_coefficients_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvMatrixCoefficients,
- matrix_coefficients)) {
+ static_cast<uint64>(matrix_coefficients_))) {
return false;
}
- if (bits_per_channel != kValueNotPresent &&
+ if (bits_per_channel_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvBitsPerChannel,
- bits_per_channel)) {
+ static_cast<uint64>(bits_per_channel_))) {
return false;
}
- if (chroma_subsampling_horz != kValueNotPresent &&
+ if (chroma_subsampling_horz_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingHorz,
- chroma_subsampling_horz)) {
+ static_cast<uint64>(chroma_subsampling_horz_))) {
return false;
}
- if (chroma_subsampling_vert != kValueNotPresent &&
+ if (chroma_subsampling_vert_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingVert,
- chroma_subsampling_vert)) {
+ static_cast<uint64>(chroma_subsampling_vert_))) {
return false;
}
- if (cb_subsampling_horz != kValueNotPresent &&
+ if (cb_subsampling_horz_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingHorz,
- cb_subsampling_horz)) {
+ static_cast<uint64>(cb_subsampling_horz_))) {
return false;
}
- if (cb_subsampling_vert != kValueNotPresent &&
+ if (cb_subsampling_vert_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingVert,
- cb_subsampling_vert)) {
+ static_cast<uint64>(cb_subsampling_vert_))) {
return false;
}
- if (chroma_siting_horz != kValueNotPresent &&
+ if (chroma_siting_horz_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvChromaSitingHorz,
- chroma_siting_horz)) {
+ static_cast<uint64>(chroma_siting_horz_))) {
return false;
}
- if (chroma_siting_vert != kValueNotPresent &&
+ if (chroma_siting_vert_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvChromaSitingVert,
- chroma_siting_vert)) {
+ static_cast<uint64>(chroma_siting_vert_))) {
return false;
}
- if (range != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvRange, range)) {
+ if (range_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvRange,
+ static_cast<uint64>(range_))) {
return false;
}
- if (transfer_characteristics != kValueNotPresent &&
+ if (transfer_characteristics_ != kValueNotPresent &&
!WriteEbmlElement(writer, libwebm::kMkvTransferCharacteristics,
- transfer_characteristics)) {
+ static_cast<uint64>(transfer_characteristics_))) {
return false;
}
- if (primaries != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvPrimaries, primaries)) {
+ if (primaries_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvPrimaries,
+ static_cast<uint64>(primaries_))) {
return false;
}
- if (max_cll != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvMaxCLL, max_cll)) {
+ if (max_cll_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvMaxCLL,
+ static_cast<uint64>(max_cll_))) {
return false;
}
- if (max_fall != kValueNotPresent &&
- !WriteEbmlElement(writer, libwebm::kMkvMaxFALL, max_fall)) {
+ if (max_fall_ != kValueNotPresent &&
+ !WriteEbmlElement(writer, libwebm::kMkvMaxFALL,
+ static_cast<uint64>(max_fall_))) {
return false;
}
@@ -1103,8 +1237,8 @@ bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) {
if (!mm_ptr.get())
return false;
- mm_ptr->luminance_max = mastering_metadata.luminance_max;
- mm_ptr->luminance_min = mastering_metadata.luminance_min;
+ mm_ptr->set_luminance_max(mastering_metadata.luminance_max());
+ mm_ptr->set_luminance_min(mastering_metadata.luminance_min());
if (!mm_ptr->SetChromaticity(mastering_metadata.r(), mastering_metadata.g(),
mastering_metadata.b(),
@@ -1120,38 +1254,56 @@ bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) {
uint64_t Colour::PayloadSize() const {
uint64_t size = 0;
- if (matrix_coefficients != kValueNotPresent)
- size +=
- EbmlElementSize(libwebm::kMkvMatrixCoefficients, matrix_coefficients);
- if (bits_per_channel != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvBitsPerChannel, bits_per_channel);
- if (chroma_subsampling_horz != kValueNotPresent)
+ if (matrix_coefficients_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvMatrixCoefficients,
+ static_cast<uint64>(matrix_coefficients_));
+ }
+ if (bits_per_channel_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvBitsPerChannel,
+ static_cast<uint64>(bits_per_channel_));
+ }
+ if (chroma_subsampling_horz_ != kValueNotPresent) {
size += EbmlElementSize(libwebm::kMkvChromaSubsamplingHorz,
- chroma_subsampling_horz);
- if (chroma_subsampling_vert != kValueNotPresent)
+ static_cast<uint64>(chroma_subsampling_horz_));
+ }
+ if (chroma_subsampling_vert_ != kValueNotPresent) {
size += EbmlElementSize(libwebm::kMkvChromaSubsamplingVert,
- chroma_subsampling_vert);
- if (cb_subsampling_horz != kValueNotPresent)
- size +=
- EbmlElementSize(libwebm::kMkvCbSubsamplingHorz, cb_subsampling_horz);
- if (cb_subsampling_vert != kValueNotPresent)
- size +=
- EbmlElementSize(libwebm::kMkvCbSubsamplingVert, cb_subsampling_vert);
- if (chroma_siting_horz != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvChromaSitingHorz, chroma_siting_horz);
- if (chroma_siting_vert != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvChromaSitingVert, chroma_siting_vert);
- if (range != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvRange, range);
- if (transfer_characteristics != kValueNotPresent)
+ static_cast<uint64>(chroma_subsampling_vert_));
+ }
+ if (cb_subsampling_horz_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvCbSubsamplingHorz,
+ static_cast<uint64>(cb_subsampling_horz_));
+ }
+ if (cb_subsampling_vert_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvCbSubsamplingVert,
+ static_cast<uint64>(cb_subsampling_vert_));
+ }
+ if (chroma_siting_horz_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvChromaSitingHorz,
+ static_cast<uint64>(chroma_siting_horz_));
+ }
+ if (chroma_siting_vert_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvChromaSitingVert,
+ static_cast<uint64>(chroma_siting_vert_));
+ }
+ if (range_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvRange, static_cast<uint64>(range_));
+ }
+ if (transfer_characteristics_ != kValueNotPresent) {
size += EbmlElementSize(libwebm::kMkvTransferCharacteristics,
- transfer_characteristics);
- if (primaries != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvPrimaries, primaries);
- if (max_cll != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvMaxCLL, max_cll);
- if (max_fall != kValueNotPresent)
- size += EbmlElementSize(libwebm::kMkvMaxFALL, max_fall);
+ static_cast<uint64>(transfer_characteristics_));
+ }
+ if (primaries_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvPrimaries,
+ static_cast<uint64>(primaries_));
+ }
+ if (max_cll_ != kValueNotPresent) {
+ size += EbmlElementSize(libwebm::kMkvMaxCLL, static_cast<uint64>(max_cll_));
+ }
+ if (max_fall_ != kValueNotPresent) {
+ size +=
+ EbmlElementSize(libwebm::kMkvMaxFALL, static_cast<uint64>(max_fall_));
+ }
if (mastering_metadata_)
size += mastering_metadata_->MasteringMetadataSize();
@@ -1161,12 +1313,98 @@ uint64_t Colour::PayloadSize() const {
///////////////////////////////////////////////////////////////
//
+// Projection element
+
+uint64_t Projection::ProjectionSize() const {
+ uint64_t size = PayloadSize();
+
+ if (size > 0)
+ size += EbmlMasterElementSize(libwebm::kMkvProjection, size);
+
+ return size;
+}
+
+bool Projection::Write(IMkvWriter* writer) const {
+ const uint64_t size = PayloadSize();
+
+ // Don't write an empty element.
+ if (size == 0)
+ return true;
+
+ if (!WriteEbmlMasterElement(writer, libwebm::kMkvProjection, size))
+ return false;
+
+ if (!WriteEbmlElement(writer, libwebm::kMkvProjectionType,
+ static_cast<uint64>(type_))) {
+ return false;
+ }
+
+ if (private_data_length_ > 0 && private_data_ != NULL &&
+ !WriteEbmlElement(writer, libwebm::kMkvProjectionPrivate, private_data_,
+ private_data_length_)) {
+ return false;
+ }
+
+ if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseYaw, pose_yaw_))
+ return false;
+
+ if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPosePitch,
+ pose_pitch_)) {
+ return false;
+ }
+
+ if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseRoll, pose_roll_)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool Projection::SetProjectionPrivate(const uint8_t* data,
+ uint64_t data_length) {
+ if (data == NULL || data_length == 0) {
+ return false;
+ }
+
+ uint8_t* new_private_data = new (std::nothrow) uint8_t[data_length];
+ if (new_private_data == NULL) {
+ return false;
+ }
+
+ delete[] private_data_;
+ private_data_ = new_private_data;
+ private_data_length_ = data_length;
+ memcpy(private_data_, data, static_cast<size_t>(data_length));
+
+ return true;
+}
+
+uint64_t Projection::PayloadSize() const {
+ uint64_t size =
+ EbmlElementSize(libwebm::kMkvProjection, static_cast<uint64>(type_));
+
+ if (private_data_length_ > 0 && private_data_ != NULL) {
+ size += EbmlElementSize(libwebm::kMkvProjectionPrivate, private_data_,
+ private_data_length_);
+ }
+
+ size += EbmlElementSize(libwebm::kMkvProjectionPoseYaw, pose_yaw_);
+ size += EbmlElementSize(libwebm::kMkvProjectionPosePitch, pose_pitch_);
+ size += EbmlElementSize(libwebm::kMkvProjectionPoseRoll, pose_roll_);
+
+ return size;
+}
+
+///////////////////////////////////////////////////////////////
+//
// VideoTrack Class
VideoTrack::VideoTrack(unsigned int* seed)
: Track(seed),
display_height_(0),
display_width_(0),
+ pixel_height_(0),
+ pixel_width_(0),
crop_left_(0),
crop_right_(0),
crop_top_(0),
@@ -1176,9 +1414,13 @@ VideoTrack::VideoTrack(unsigned int* seed)
stereo_mode_(0),
alpha_mode_(0),
width_(0),
- colour_(NULL) {}
+ colour_(NULL),
+ projection_(NULL) {}
-VideoTrack::~VideoTrack() { delete colour_; }
+VideoTrack::~VideoTrack() {
+ delete colour_;
+ delete projection_;
+}
bool VideoTrack::SetStereoMode(uint64_t stereo_mode) {
if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
@@ -1221,40 +1463,52 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
if (payload_position < 0)
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelWidth, width_))
+ if (!WriteEbmlElement(
+ writer, libwebm::kMkvPixelWidth,
+ static_cast<uint64>((pixel_width_ > 0) ? pixel_width_ : width_)))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelHeight, height_))
+ if (!WriteEbmlElement(
+ writer, libwebm::kMkvPixelHeight,
+ static_cast<uint64>((pixel_height_ > 0) ? pixel_height_ : height_)))
return false;
if (display_width_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvDisplayWidth, display_width_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvDisplayWidth,
+ static_cast<uint64>(display_width_)))
return false;
}
if (display_height_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvDisplayHeight, display_height_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvDisplayHeight,
+ static_cast<uint64>(display_height_)))
return false;
}
if (crop_left_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropLeft, crop_left_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropLeft,
+ static_cast<uint64>(crop_left_)))
return false;
}
if (crop_right_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropRight, crop_right_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropRight,
+ static_cast<uint64>(crop_right_)))
return false;
}
if (crop_top_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropTop, crop_top_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropTop,
+ static_cast<uint64>(crop_top_)))
return false;
}
if (crop_bottom_ > 0) {
- if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropBottom, crop_bottom_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropBottom,
+ static_cast<uint64>(crop_bottom_)))
return false;
}
if (stereo_mode_ > kMono) {
- if (!WriteEbmlElement(writer, libwebm::kMkvStereoMode, stereo_mode_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvStereoMode,
+ static_cast<uint64>(stereo_mode_)))
return false;
}
if (alpha_mode_ > kNoAlpha) {
- if (!WriteEbmlElement(writer, libwebm::kMkvAlphaMode, alpha_mode_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvAlphaMode,
+ static_cast<uint64>(alpha_mode_)))
return false;
}
if (frame_rate_ > 0.0) {
@@ -1267,6 +1521,10 @@ bool VideoTrack::Write(IMkvWriter* writer) const {
if (!colour_->Write(writer))
return false;
}
+ if (projection_) {
+ if (!projection_->Write(writer))
+ return false;
+ }
const int64_t stop_position = writer->Position();
if (stop_position < 0 ||
@@ -1287,47 +1545,83 @@ bool VideoTrack::SetColour(const Colour& colour) {
return false;
}
- colour_ptr->matrix_coefficients = colour.matrix_coefficients;
- colour_ptr->bits_per_channel = colour.bits_per_channel;
- colour_ptr->chroma_subsampling_horz = colour.chroma_subsampling_horz;
- colour_ptr->chroma_subsampling_vert = colour.chroma_subsampling_vert;
- colour_ptr->cb_subsampling_horz = colour.cb_subsampling_horz;
- colour_ptr->cb_subsampling_vert = colour.cb_subsampling_vert;
- colour_ptr->chroma_siting_horz = colour.chroma_siting_horz;
- colour_ptr->chroma_siting_vert = colour.chroma_siting_vert;
- colour_ptr->range = colour.range;
- colour_ptr->transfer_characteristics = colour.transfer_characteristics;
- colour_ptr->primaries = colour.primaries;
- colour_ptr->max_cll = colour.max_cll;
- colour_ptr->max_fall = colour.max_fall;
+ colour_ptr->set_matrix_coefficients(colour.matrix_coefficients());
+ colour_ptr->set_bits_per_channel(colour.bits_per_channel());
+ colour_ptr->set_chroma_subsampling_horz(colour.chroma_subsampling_horz());
+ colour_ptr->set_chroma_subsampling_vert(colour.chroma_subsampling_vert());
+ colour_ptr->set_cb_subsampling_horz(colour.cb_subsampling_horz());
+ colour_ptr->set_cb_subsampling_vert(colour.cb_subsampling_vert());
+ colour_ptr->set_chroma_siting_horz(colour.chroma_siting_horz());
+ colour_ptr->set_chroma_siting_vert(colour.chroma_siting_vert());
+ colour_ptr->set_range(colour.range());
+ colour_ptr->set_transfer_characteristics(colour.transfer_characteristics());
+ colour_ptr->set_primaries(colour.primaries());
+ colour_ptr->set_max_cll(colour.max_cll());
+ colour_ptr->set_max_fall(colour.max_fall());
+ delete colour_;
colour_ = colour_ptr.release();
return true;
}
+bool VideoTrack::SetProjection(const Projection& projection) {
+ std::auto_ptr<Projection> projection_ptr(new Projection());
+ if (!projection_ptr.get())
+ return false;
+
+ if (projection.private_data()) {
+ if (!projection_ptr->SetProjectionPrivate(
+ projection.private_data(), projection.private_data_length())) {
+ return false;
+ }
+ }
+
+ projection_ptr->set_type(projection.type());
+ projection_ptr->set_pose_yaw(projection.pose_yaw());
+ projection_ptr->set_pose_pitch(projection.pose_pitch());
+ projection_ptr->set_pose_roll(projection.pose_roll());
+ delete projection_;
+ projection_ = projection_ptr.release();
+ return true;
+}
+
uint64_t VideoTrack::VideoPayloadSize() const {
- uint64_t size = EbmlElementSize(libwebm::kMkvPixelWidth, width_);
- size += EbmlElementSize(libwebm::kMkvPixelHeight, height_);
+ uint64_t size = EbmlElementSize(
+ libwebm::kMkvPixelWidth,
+ static_cast<uint64>((pixel_width_ > 0) ? pixel_width_ : width_));
+ size += EbmlElementSize(
+ libwebm::kMkvPixelHeight,
+ static_cast<uint64>((pixel_height_ > 0) ? pixel_height_ : height_));
if (display_width_ > 0)
- size += EbmlElementSize(libwebm::kMkvDisplayWidth, display_width_);
+ size += EbmlElementSize(libwebm::kMkvDisplayWidth,
+ static_cast<uint64>(display_width_));
if (display_height_ > 0)
- size += EbmlElementSize(libwebm::kMkvDisplayHeight, display_height_);
+ size += EbmlElementSize(libwebm::kMkvDisplayHeight,
+ static_cast<uint64>(display_height_));
if (crop_left_ > 0)
- size += EbmlElementSize(libwebm::kMkvPixelCropLeft, crop_left_);
+ size += EbmlElementSize(libwebm::kMkvPixelCropLeft,
+ static_cast<uint64>(crop_left_));
if (crop_right_ > 0)
- size += EbmlElementSize(libwebm::kMkvPixelCropRight, crop_right_);
+ size += EbmlElementSize(libwebm::kMkvPixelCropRight,
+ static_cast<uint64>(crop_right_));
if (crop_top_ > 0)
- size += EbmlElementSize(libwebm::kMkvPixelCropTop, crop_top_);
+ size += EbmlElementSize(libwebm::kMkvPixelCropTop,
+ static_cast<uint64>(crop_top_));
if (crop_bottom_ > 0)
- size += EbmlElementSize(libwebm::kMkvPixelCropBottom, crop_bottom_);
+ size += EbmlElementSize(libwebm::kMkvPixelCropBottom,
+ static_cast<uint64>(crop_bottom_));
if (stereo_mode_ > kMono)
- size += EbmlElementSize(libwebm::kMkvStereoMode, stereo_mode_);
+ size += EbmlElementSize(libwebm::kMkvStereoMode,
+ static_cast<uint64>(stereo_mode_));
if (alpha_mode_ > kNoAlpha)
- size += EbmlElementSize(libwebm::kMkvAlphaMode, alpha_mode_);
+ size += EbmlElementSize(libwebm::kMkvAlphaMode,
+ static_cast<uint64>(alpha_mode_));
if (frame_rate_ > 0.0)
size += EbmlElementSize(libwebm::kMkvFrameRate,
static_cast<float>(frame_rate_));
if (colour_)
size += colour_->ColourSize();
+ if (projection_)
+ size += projection_->ProjectionSize();
return size;
}
@@ -1346,9 +1640,11 @@ uint64_t AudioTrack::PayloadSize() const {
uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency,
static_cast<float>(sample_rate_));
- size += EbmlElementSize(libwebm::kMkvChannels, channels_);
+ size +=
+ EbmlElementSize(libwebm::kMkvChannels, static_cast<uint64>(channels_));
if (bit_depth_ > 0)
- size += EbmlElementSize(libwebm::kMkvBitDepth, bit_depth_);
+ size +=
+ EbmlElementSize(libwebm::kMkvBitDepth, static_cast<uint64>(bit_depth_));
size += EbmlMasterElementSize(libwebm::kMkvAudio, size);
return parent_size + size;
@@ -1361,9 +1657,11 @@ bool AudioTrack::Write(IMkvWriter* writer) const {
// Calculate AudioSettings size.
uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency,
static_cast<float>(sample_rate_));
- size += EbmlElementSize(libwebm::kMkvChannels, channels_);
+ size +=
+ EbmlElementSize(libwebm::kMkvChannels, static_cast<uint64>(channels_));
if (bit_depth_ > 0)
- size += EbmlElementSize(libwebm::kMkvBitDepth, bit_depth_);
+ size +=
+ EbmlElementSize(libwebm::kMkvBitDepth, static_cast<uint64>(bit_depth_));
if (!WriteEbmlMasterElement(writer, libwebm::kMkvAudio, size))
return false;
@@ -1375,10 +1673,12 @@ bool AudioTrack::Write(IMkvWriter* writer) const {
if (!WriteEbmlElement(writer, libwebm::kMkvSamplingFrequency,
static_cast<float>(sample_rate_)))
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvChannels, channels_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvChannels,
+ static_cast<uint64>(channels_)))
return false;
if (bit_depth_ > 0)
- if (!WriteEbmlElement(writer, libwebm::kMkvBitDepth, bit_depth_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvBitDepth,
+ static_cast<uint64>(bit_depth_)))
return false;
const int64_t stop_position = writer->Position();
@@ -1398,6 +1698,10 @@ const char Tracks::kVorbisCodecId[] = "A_VORBIS";
const char Tracks::kVp8CodecId[] = "V_VP8";
const char Tracks::kVp9CodecId[] = "V_VP9";
const char Tracks::kVp10CodecId[] = "V_VP10";
+const char Tracks::kWebVttCaptionsId[] = "D_WEBVTT/CAPTIONS";
+const char Tracks::kWebVttDescriptionsId[] = "D_WEBVTT/DESCRIPTIONS";
+const char Tracks::kWebVttMetadataId[] = "D_WEBVTT/METADATA";
+const char Tracks::kWebVttSubtitlesId[] = "D_WEBVTT/SUBTITLES";
Tracks::Tracks()
: track_entries_(NULL), track_entries_size_(0), wrote_tracks_(false) {}
@@ -1650,9 +1954,11 @@ bool Chapter::ExpandDisplaysArray() {
uint64_t Chapter::WriteAtom(IMkvWriter* writer) const {
uint64_t payload_size =
EbmlElementSize(libwebm::kMkvChapterStringUID, id_) +
- EbmlElementSize(libwebm::kMkvChapterUID, uid_) +
- EbmlElementSize(libwebm::kMkvChapterTimeStart, start_timecode_) +
- EbmlElementSize(libwebm::kMkvChapterTimeEnd, end_timecode_);
+ EbmlElementSize(libwebm::kMkvChapterUID, static_cast<uint64>(uid_)) +
+ EbmlElementSize(libwebm::kMkvChapterTimeStart,
+ static_cast<uint64>(start_timecode_)) +
+ EbmlElementSize(libwebm::kMkvChapterTimeEnd,
+ static_cast<uint64>(end_timecode_));
for (int idx = 0; idx < displays_count_; ++idx) {
const Display& d = displays_[idx];
@@ -1674,13 +1980,16 @@ uint64_t Chapter::WriteAtom(IMkvWriter* writer) const {
if (!WriteEbmlElement(writer, libwebm::kMkvChapterStringUID, id_))
return 0;
- if (!WriteEbmlElement(writer, libwebm::kMkvChapterUID, uid_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvChapterUID,
+ static_cast<uint64>(uid_)))
return 0;
- if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeStart, start_timecode_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeStart,
+ static_cast<uint64>(start_timecode_)))
return 0;
- if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeEnd, end_timecode_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeEnd,
+ static_cast<uint64>(end_timecode_)))
return 0;
for (int idx = 0; idx < displays_count_; ++idx) {
@@ -2125,7 +2434,17 @@ Cluster::Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
write_last_frame_with_duration_(write_last_frame_with_duration),
writer_(NULL) {}
-Cluster::~Cluster() {}
+Cluster::~Cluster() {
+ // Delete any stored frames that are left behind. This will happen if the
+ // Cluster was not Finalized for whatever reason.
+ while (!stored_frames_.empty()) {
+ while (!stored_frames_.begin()->second.empty()) {
+ delete stored_frames_.begin()->second.front();
+ stored_frames_.begin()->second.pop_front();
+ }
+ stored_frames_.erase(stored_frames_.begin()->first);
+ }
+}
bool Cluster::Init(IMkvWriter* ptr_writer) {
if (!ptr_writer) {
@@ -2421,10 +2740,10 @@ bool SeekHead::Finalize(IMkvWriter* writer) const {
for (int32_t i = 0; i < kSeekEntryCount; ++i) {
if (seek_entry_id_[i] != 0) {
- entry_size[i] = EbmlElementSize(
- libwebm::kMkvSeekID, static_cast<uint64_t>(seek_entry_id_[i]));
- entry_size[i] +=
- EbmlElementSize(libwebm::kMkvSeekPosition, seek_entry_pos_[i]);
+ entry_size[i] = EbmlElementSize(libwebm::kMkvSeekID,
+ static_cast<uint64>(seek_entry_id_[i]));
+ entry_size[i] += EbmlElementSize(
+ libwebm::kMkvSeekPosition, static_cast<uint64>(seek_entry_pos_[i]));
payload_size +=
EbmlMasterElementSize(libwebm::kMkvSeek, entry_size[i]) +
@@ -2449,11 +2768,11 @@ bool SeekHead::Finalize(IMkvWriter* writer) const {
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvSeekID,
- static_cast<uint64_t>(seek_entry_id_[i])))
+ static_cast<uint64>(seek_entry_id_[i])))
return false;
if (!WriteEbmlElement(writer, libwebm::kMkvSeekPosition,
- seek_entry_pos_[i]))
+ static_cast<uint64>(seek_entry_pos_[i])))
return false;
}
}
@@ -2522,8 +2841,10 @@ bool SeekHead::SetSeekEntry(int index, uint32_t id, uint64_t position) {
uint64_t SeekHead::MaxEntrySize() const {
const uint64_t max_entry_payload_size =
- EbmlElementSize(libwebm::kMkvSeekID, UINT64_C(0xffffffff)) +
- EbmlElementSize(libwebm::kMkvSeekPosition, UINT64_C(0xffffffffffffffff));
+ EbmlElementSize(libwebm::kMkvSeekID,
+ static_cast<uint64>(UINT64_C(0xffffffff))) +
+ EbmlElementSize(libwebm::kMkvSeekPosition,
+ static_cast<uint64>(UINT64_C(0xffffffffffffffff)));
const uint64_t max_entry_size =
EbmlMasterElementSize(libwebm::kMkvSeek, max_entry_payload_size) +
max_entry_payload_size;
@@ -2613,7 +2934,8 @@ bool SegmentInfo::Write(IMkvWriter* writer) {
if (!writer || !muxing_app_ || !writing_app_)
return false;
- uint64_t size = EbmlElementSize(libwebm::kMkvTimecodeScale, timecode_scale_);
+ uint64_t size = EbmlElementSize(libwebm::kMkvTimecodeScale,
+ static_cast<uint64>(timecode_scale_));
if (duration_ > 0.0)
size +=
EbmlElementSize(libwebm::kMkvDuration, static_cast<float>(duration_));
@@ -2629,7 +2951,8 @@ bool SegmentInfo::Write(IMkvWriter* writer) {
if (payload_position < 0)
return false;
- if (!WriteEbmlElement(writer, libwebm::kMkvTimecodeScale, timecode_scale_))
+ if (!WriteEbmlElement(writer, libwebm::kMkvTimecodeScale,
+ static_cast<uint64>(timecode_scale_)))
return false;
if (duration_ > 0.0) {
@@ -2725,10 +3048,12 @@ Segment::Segment()
output_cues_(true),
accurate_cluster_duration_(false),
fixed_size_cluster_timecode_(false),
+ estimate_file_duration_(true),
payload_pos_(0),
size_position_(0),
doc_type_version_(kDefaultDocTypeVersion),
doc_type_version_written_(0),
+ duration_(0.0),
writer_cluster_(NULL),
writer_cues_(NULL),
writer_header_(NULL) {
@@ -2833,6 +3158,10 @@ bool Segment::Init(IMkvWriter* ptr_writer) {
writer_cluster_ = ptr_writer;
writer_cues_ = ptr_writer;
writer_header_ = ptr_writer;
+ memset(&track_frames_written_, 0,
+ sizeof(track_frames_written_[0]) * kMaxTrackNumber);
+ memset(&last_track_timestamp_, 0,
+ sizeof(last_track_timestamp_[0]) * kMaxTrackNumber);
return segment_info_.Init();
}
@@ -2876,7 +3205,10 @@ bool Segment::Finalize() {
if (WriteFramesAll() < 0)
return false;
- if (cluster_list_size_ > 0) {
+ // In kLive mode, call Cluster::Finalize only if |accurate_cluster_duration_|
+ // is set. In all other modes, always call Cluster::Finalize.
+ if ((mode_ == kLive ? accurate_cluster_duration_ : true) &&
+ cluster_list_size_ > 0) {
// Update last cluster's size
Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
@@ -2892,9 +3224,30 @@ bool Segment::Finalize() {
chunk_count_++;
}
- const double duration =
+ double duration =
(static_cast<double>(last_timestamp_) + last_block_duration_) /
segment_info_.timecode_scale();
+ if (duration_ > 0.0) {
+ duration = duration_;
+ } else {
+ if (last_block_duration_ == 0 && estimate_file_duration_) {
+ const int num_tracks = static_cast<int>(tracks_.track_entries_size());
+ for (int i = 0; i < num_tracks; ++i) {
+ if (track_frames_written_[i] < 2)
+ continue;
+
+ // Estimate the duration for the last block of a Track.
+ const double nano_per_frame =
+ static_cast<double>(last_track_timestamp_[i]) /
+ (track_frames_written_[i] - 1);
+ const double track_duration =
+ (last_track_timestamp_[i] + nano_per_frame) /
+ segment_info_.timecode_scale();
+ if (track_duration > duration)
+ duration = track_duration;
+ }
+ }
+ }
segment_info_.set_duration(duration);
if (!segment_info_.Finalize(writer_header_))
return false;
@@ -2941,7 +3294,9 @@ bool Segment::Finalize() {
if (writer_header_->Position(0))
return false;
- if (!WriteEbmlHeader(writer_header_, doc_type_version_))
+ const char* const doc_type =
+ DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska;
+ if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type))
return false;
if (writer_header_->Position() != ebml_header_size_)
return false;
@@ -3138,7 +3493,10 @@ bool Segment::AddGenericFrame(const Frame* frame) {
Frame* const new_frame = new (std::nothrow) Frame();
if (!new_frame || !new_frame->CopyFrom(*frame))
return false;
- return QueueFrame(new_frame);
+ if (!QueueFrame(new_frame))
+ return false;
+ track_frames_written_[frame->track_number() - 1]++;
+ return true;
}
if (!DoNewClusterProcessing(frame->track_number(), frame->timestamp(),
@@ -3178,10 +3536,10 @@ bool Segment::AddGenericFrame(const Frame* frame) {
last_timestamp_ = frame->timestamp();
last_track_timestamp_[frame->track_number() - 1] = frame->timestamp();
last_block_duration_ = frame->duration();
+ track_frames_written_[frame->track_number() - 1]++;
if (frame_created)
delete frame;
-
return true;
}
@@ -3292,8 +3650,9 @@ Track* Segment::GetTrackByNumber(uint64_t track_number) const {
bool Segment::WriteSegmentHeader() {
UpdateDocTypeVersion();
- // TODO(fgalligan): Support more than one segment.
- if (!WriteEbmlHeader(writer_header_, doc_type_version_))
+ const char* const doc_type =
+ DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska;
+ if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type))
return false;
doc_type_version_written_ = doc_type_version_;
ebml_header_size_ = static_cast<int32_t>(writer_header_->Position());
@@ -3766,4 +4125,35 @@ bool Segment::WriteFramesLessThan(uint64_t timestamp) {
return true;
}
+bool Segment::DocTypeIsWebm() const {
+ const int kNumCodecIds = 9;
+
+ // TODO(vigneshv): Tweak .clang-format.
+ const char* kWebmCodecIds[kNumCodecIds] = {
+ Tracks::kOpusCodecId, Tracks::kVorbisCodecId,
+ Tracks::kVp8CodecId, Tracks::kVp9CodecId,
+ Tracks::kVp10CodecId, Tracks::kWebVttCaptionsId,
+ Tracks::kWebVttDescriptionsId, Tracks::kWebVttMetadataId,
+ Tracks::kWebVttSubtitlesId};
+
+ const int num_tracks = static_cast<int>(tracks_.track_entries_size());
+ for (int track_index = 0; track_index < num_tracks; ++track_index) {
+ const Track* const track = tracks_.GetTrackByIndex(track_index);
+ const std::string codec_id = track->codec_id();
+
+ bool id_is_webm = false;
+ for (int id_index = 0; id_index < kNumCodecIds; ++id_index) {
+ if (codec_id == kWebmCodecIds[id_index]) {
+ id_is_webm = true;
+ break;
+ }
+ }
+
+ if (!id_is_webm)
+ return false;
+ }
+
+ return true;
+}
+
} // namespace mkvmuxer
diff --git a/third_party/libwebm/mkvmuxer/mkvmuxer.h b/third_party/libwebm/mkvmuxer/mkvmuxer.h
index 55ba07196..c3c1c5975 100644
--- a/third_party/libwebm/mkvmuxer/mkvmuxer.h
+++ b/third_party/libwebm/mkvmuxer/mkvmuxer.h
@@ -64,6 +64,12 @@ class IMkvWriter {
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(IMkvWriter);
};
+// Writes out the EBML header for a WebM file, but allows caller to specify
+// DocType. This function must be called before any other libwebm writing
+// functions are called.
+bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version,
+ const char* const doc_type);
+
// Writes out the EBML header for a WebM file. This function must be called
// before any other libwebm writing functions are called.
bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version);
@@ -348,26 +354,42 @@ class ContentEncoding {
///////////////////////////////////////////////////////////////
// Colour element.
-struct PrimaryChromaticity {
- PrimaryChromaticity(float x_val, float y_val) : x(x_val), y(y_val) {}
- PrimaryChromaticity() : x(0), y(0) {}
+class PrimaryChromaticity {
+ public:
+ static const float kChromaticityMin;
+ static const float kChromaticityMax;
+
+ PrimaryChromaticity(float x_val, float y_val) : x_(x_val), y_(y_val) {}
+ PrimaryChromaticity() : x_(0), y_(0) {}
~PrimaryChromaticity() {}
- uint64_t PrimaryChromaticityPayloadSize(libwebm::MkvId x_id,
- libwebm::MkvId y_id) const;
+
+ // Returns sum of |x_id| and |y_id| element id sizes and payload sizes.
+ uint64_t PrimaryChromaticitySize(libwebm::MkvId x_id,
+ libwebm::MkvId y_id) const;
+ bool Valid() const;
bool Write(IMkvWriter* writer, libwebm::MkvId x_id,
libwebm::MkvId y_id) const;
- float x;
- float y;
+ float x() const { return x_; }
+ void set_x(float new_x) { x_ = new_x; }
+ float y() const { return y_; }
+ void set_y(float new_y) { y_ = new_y; }
+
+ private:
+ float x_;
+ float y_;
};
class MasteringMetadata {
public:
static const float kValueNotPresent;
+ static const float kMinLuminance;
+ static const float kMinLuminanceMax;
+ static const float kMaxLuminanceMax;
MasteringMetadata()
- : luminance_max(kValueNotPresent),
- luminance_min(kValueNotPresent),
+ : luminance_max_(kValueNotPresent),
+ luminance_min_(kValueNotPresent),
r_(NULL),
g_(NULL),
b_(NULL),
@@ -381,6 +403,7 @@ class MasteringMetadata {
// Returns total size of the MasteringMetadata element.
uint64_t MasteringMetadataSize() const;
+ bool Valid() const;
bool Write(IMkvWriter* writer) const;
// Copies non-null chromaticity.
@@ -393,13 +416,21 @@ class MasteringMetadata {
const PrimaryChromaticity* b() const { return b_; }
const PrimaryChromaticity* white_point() const { return white_point_; }
- float luminance_max;
- float luminance_min;
+ float luminance_max() const { return luminance_max_; }
+ void set_luminance_max(float luminance_max) {
+ luminance_max_ = luminance_max;
+ }
+ float luminance_min() const { return luminance_min_; }
+ void set_luminance_min(float luminance_min) {
+ luminance_min_ = luminance_min;
+ }
private:
// Returns size of MasteringMetadata child elements.
uint64_t PayloadSize() const;
+ float luminance_max_;
+ float luminance_min_;
PrimaryChromaticity* r_;
PrimaryChromaticity* g_;
PrimaryChromaticity* b_;
@@ -408,26 +439,90 @@ class MasteringMetadata {
class Colour {
public:
+ enum MatrixCoefficients {
+ kGbr = 0,
+ kBt709 = 1,
+ kUnspecifiedMc = 2,
+ kReserved = 3,
+ kFcc = 4,
+ kBt470bg = 5,
+ kSmpte170MMc = 6,
+ kSmpte240MMc = 7,
+ kYcocg = 8,
+ kBt2020NonConstantLuminance = 9,
+ kBt2020ConstantLuminance = 10,
+ };
+ enum ChromaSitingHorz {
+ kUnspecifiedCsh = 0,
+ kLeftCollocated = 1,
+ kHalfCsh = 2,
+ };
+ enum ChromaSitingVert {
+ kUnspecifiedCsv = 0,
+ kTopCollocated = 1,
+ kHalfCsv = 2,
+ };
+ enum Range {
+ kUnspecifiedCr = 0,
+ kBroadcastRange = 1,
+ kFullRange = 2,
+ kMcTcDefined = 3, // Defined by MatrixCoefficients/TransferCharacteristics.
+ };
+ enum TransferCharacteristics {
+ kIturBt709Tc = 1,
+ kUnspecifiedTc = 2,
+ kReservedTc = 3,
+ kGamma22Curve = 4,
+ kGamma28Curve = 5,
+ kSmpte170MTc = 6,
+ kSmpte240MTc = 7,
+ kLinear = 8,
+ kLog = 9,
+ kLogSqrt = 10,
+ kIec6196624 = 11,
+ kIturBt1361ExtendedColourGamut = 12,
+ kIec6196621 = 13,
+ kIturBt202010bit = 14,
+ kIturBt202012bit = 15,
+ kSmpteSt2084 = 16,
+ kSmpteSt4281Tc = 17,
+ kAribStdB67Hlg = 18,
+ };
+ enum Primaries {
+ kReservedP0 = 0,
+ kIturBt709P = 1,
+ kUnspecifiedP = 2,
+ kReservedP3 = 3,
+ kIturBt470M = 4,
+ kIturBt470Bg = 5,
+ kSmpte170MP = 6,
+ kSmpte240MP = 7,
+ kFilm = 8,
+ kIturBt2020 = 9,
+ kSmpteSt4281P = 10,
+ kJedecP22Phosphors = 22,
+ };
static const uint64_t kValueNotPresent;
Colour()
- : matrix_coefficients(kValueNotPresent),
- bits_per_channel(kValueNotPresent),
- chroma_subsampling_horz(kValueNotPresent),
- chroma_subsampling_vert(kValueNotPresent),
- cb_subsampling_horz(kValueNotPresent),
- cb_subsampling_vert(kValueNotPresent),
- chroma_siting_horz(kValueNotPresent),
- chroma_siting_vert(kValueNotPresent),
- range(kValueNotPresent),
- transfer_characteristics(kValueNotPresent),
- primaries(kValueNotPresent),
- max_cll(kValueNotPresent),
- max_fall(kValueNotPresent),
+ : matrix_coefficients_(kValueNotPresent),
+ bits_per_channel_(kValueNotPresent),
+ chroma_subsampling_horz_(kValueNotPresent),
+ chroma_subsampling_vert_(kValueNotPresent),
+ cb_subsampling_horz_(kValueNotPresent),
+ cb_subsampling_vert_(kValueNotPresent),
+ chroma_siting_horz_(kValueNotPresent),
+ chroma_siting_vert_(kValueNotPresent),
+ range_(kValueNotPresent),
+ transfer_characteristics_(kValueNotPresent),
+ primaries_(kValueNotPresent),
+ max_cll_(kValueNotPresent),
+ max_fall_(kValueNotPresent),
mastering_metadata_(NULL) {}
~Colour() { delete mastering_metadata_; }
// Returns total size of the Colour element.
uint64_t ColourSize() const;
+ bool Valid() const;
bool Write(IMkvWriter* writer) const;
// Deep copies |mastering_metadata|.
@@ -437,28 +532,125 @@ class Colour {
return mastering_metadata_;
}
- uint64_t matrix_coefficients;
- uint64_t bits_per_channel;
- uint64_t chroma_subsampling_horz;
- uint64_t chroma_subsampling_vert;
- uint64_t cb_subsampling_horz;
- uint64_t cb_subsampling_vert;
- uint64_t chroma_siting_horz;
- uint64_t chroma_siting_vert;
- uint64_t range;
- uint64_t transfer_characteristics;
- uint64_t primaries;
- uint64_t max_cll;
- uint64_t max_fall;
+ uint64_t matrix_coefficients() const { return matrix_coefficients_; }
+ void set_matrix_coefficients(uint64_t matrix_coefficients) {
+ matrix_coefficients_ = matrix_coefficients;
+ }
+ uint64_t bits_per_channel() const { return bits_per_channel_; }
+ void set_bits_per_channel(uint64_t bits_per_channel) {
+ bits_per_channel_ = bits_per_channel;
+ }
+ uint64_t chroma_subsampling_horz() const { return chroma_subsampling_horz_; }
+ void set_chroma_subsampling_horz(uint64_t chroma_subsampling_horz) {
+ chroma_subsampling_horz_ = chroma_subsampling_horz;
+ }
+ uint64_t chroma_subsampling_vert() const { return chroma_subsampling_vert_; }
+ void set_chroma_subsampling_vert(uint64_t chroma_subsampling_vert) {
+ chroma_subsampling_vert_ = chroma_subsampling_vert;
+ }
+ uint64_t cb_subsampling_horz() const { return cb_subsampling_horz_; }
+ void set_cb_subsampling_horz(uint64_t cb_subsampling_horz) {
+ cb_subsampling_horz_ = cb_subsampling_horz;
+ }
+ uint64_t cb_subsampling_vert() const { return cb_subsampling_vert_; }
+ void set_cb_subsampling_vert(uint64_t cb_subsampling_vert) {
+ cb_subsampling_vert_ = cb_subsampling_vert;
+ }
+ uint64_t chroma_siting_horz() const { return chroma_siting_horz_; }
+ void set_chroma_siting_horz(uint64_t chroma_siting_horz) {
+ chroma_siting_horz_ = chroma_siting_horz;
+ }
+ uint64_t chroma_siting_vert() const { return chroma_siting_vert_; }
+ void set_chroma_siting_vert(uint64_t chroma_siting_vert) {
+ chroma_siting_vert_ = chroma_siting_vert;
+ }
+ uint64_t range() const { return range_; }
+ void set_range(uint64_t range) { range_ = range; }
+ uint64_t transfer_characteristics() const {
+ return transfer_characteristics_;
+ }
+ void set_transfer_characteristics(uint64_t transfer_characteristics) {
+ transfer_characteristics_ = transfer_characteristics;
+ }
+ uint64_t primaries() const { return primaries_; }
+ void set_primaries(uint64_t primaries) { primaries_ = primaries; }
+ uint64_t max_cll() const { return max_cll_; }
+ void set_max_cll(uint64_t max_cll) { max_cll_ = max_cll; }
+ uint64_t max_fall() const { return max_fall_; }
+ void set_max_fall(uint64_t max_fall) { max_fall_ = max_fall; }
private:
// Returns size of Colour child elements.
uint64_t PayloadSize() const;
+ uint64_t matrix_coefficients_;
+ uint64_t bits_per_channel_;
+ uint64_t chroma_subsampling_horz_;
+ uint64_t chroma_subsampling_vert_;
+ uint64_t cb_subsampling_horz_;
+ uint64_t cb_subsampling_vert_;
+ uint64_t chroma_siting_horz_;
+ uint64_t chroma_siting_vert_;
+ uint64_t range_;
+ uint64_t transfer_characteristics_;
+ uint64_t primaries_;
+ uint64_t max_cll_;
+ uint64_t max_fall_;
+
MasteringMetadata* mastering_metadata_;
};
///////////////////////////////////////////////////////////////
+// Projection element.
+class Projection {
+ public:
+ enum ProjectionType {
+ kTypeNotPresent = -1,
+ kRectangular = 0,
+ kEquirectangular = 1,
+ kCubeMap = 2,
+ kMesh = 3,
+ };
+ static const uint64_t kValueNotPresent;
+ Projection()
+ : type_(kRectangular),
+ pose_yaw_(0.0),
+ pose_pitch_(0.0),
+ pose_roll_(0.0),
+ private_data_(NULL),
+ private_data_length_(0) {}
+ ~Projection() { delete[] private_data_; }
+
+ uint64_t ProjectionSize() const;
+ bool Write(IMkvWriter* writer) const;
+
+ bool SetProjectionPrivate(const uint8_t* private_data,
+ uint64_t private_data_length);
+
+ ProjectionType type() const { return type_; }
+ void set_type(ProjectionType type) { type_ = type; }
+ float pose_yaw() const { return pose_yaw_; }
+ void set_pose_yaw(float pose_yaw) { pose_yaw_ = pose_yaw; }
+ float pose_pitch() const { return pose_pitch_; }
+ void set_pose_pitch(float pose_pitch) { pose_pitch_ = pose_pitch; }
+ float pose_roll() const { return pose_roll_; }
+ void set_pose_roll(float pose_roll) { pose_roll_ = pose_roll; }
+ uint8_t* private_data() const { return private_data_; }
+ uint64_t private_data_length() const { return private_data_length_; }
+
+ private:
+ // Returns size of VideoProjection child elements.
+ uint64_t PayloadSize() const;
+
+ ProjectionType type_;
+ float pose_yaw_;
+ float pose_pitch_;
+ float pose_roll_;
+ uint8_t* private_data_;
+ uint64_t private_data_length_;
+};
+
+///////////////////////////////////////////////////////////////
// Track element.
class Track {
public:
@@ -581,6 +773,10 @@ class VideoTrack : public Track {
uint64_t display_height() const { return display_height_; }
void set_display_width(uint64_t width) { display_width_ = width; }
uint64_t display_width() const { return display_width_; }
+ void set_pixel_height(uint64_t height) { pixel_height_ = height; }
+ uint64_t pixel_height() const { return pixel_height_; }
+ void set_pixel_width(uint64_t width) { pixel_width_ = width; }
+ uint64_t pixel_width() const { return pixel_width_; }
void set_crop_left(uint64_t crop_left) { crop_left_ = crop_left; }
uint64_t crop_left() const { return crop_left_; }
@@ -605,6 +801,11 @@ class VideoTrack : public Track {
// Deep copies |colour|.
bool SetColour(const Colour& colour);
+ Projection* projection() { return projection_; };
+
+ // Deep copies |projection|.
+ bool SetProjection(const Projection& projection);
+
private:
// Returns the size in bytes of the Video element.
uint64_t VideoPayloadSize() const;
@@ -612,6 +813,8 @@ class VideoTrack : public Track {
// Video track element names.
uint64_t display_height_;
uint64_t display_width_;
+ uint64_t pixel_height_;
+ uint64_t pixel_width_;
uint64_t crop_left_;
uint64_t crop_right_;
uint64_t crop_top_;
@@ -623,6 +826,7 @@ class VideoTrack : public Track {
uint64_t width_;
Colour* colour_;
+ Projection* projection_;
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(VideoTrack);
};
@@ -670,6 +874,10 @@ class Tracks {
static const char kVp8CodecId[];
static const char kVp9CodecId[];
static const char kVp10CodecId[];
+ static const char kWebVttCaptionsId[];
+ static const char kWebVttDescriptionsId[];
+ static const char kWebVttMetadataId[];
+ static const char kWebVttSubtitlesId[];
Tracks();
~Tracks();
@@ -1294,7 +1502,7 @@ class Segment {
kBeforeClusters = 0x1 // Position Cues before Clusters
};
- const static uint32_t kDefaultDocTypeVersion = 2;
+ const static uint32_t kDefaultDocTypeVersion = 4;
const static uint64_t kDefaultMaxClusterDuration = 30000000000ULL;
Segment();
@@ -1481,7 +1689,16 @@ class Segment {
Mode mode() const { return mode_; }
CuesPosition cues_position() const { return cues_position_; }
bool output_cues() const { return output_cues_; }
+ void set_estimate_file_duration(bool estimate_duration) {
+ estimate_file_duration_ = estimate_duration;
+ }
+ bool estimate_file_duration() const { return estimate_file_duration_; }
const SegmentInfo* segment_info() const { return &segment_info_; }
+ void set_duration(double duration) { duration_ = duration; }
+ double duration() const { return duration_; }
+
+ // Returns true when codec IDs are valid for WebM.
+ bool DocTypeIsWebm() const;
private:
// Checks if header information has been output and initialized. If not it
@@ -1637,6 +1854,9 @@ class Segment {
// Last timestamp in nanoseconds by track number added to a cluster.
uint64_t last_track_timestamp_[kMaxTrackNumber];
+ // Number of frames written per track.
+ uint64_t track_frames_written_[kMaxTrackNumber];
+
// Maximum time in nanoseconds for a cluster duration. This variable is a
// guideline and some clusters may have a longer duration. Default is 30
// seconds.
@@ -1665,6 +1885,9 @@ class Segment {
// Flag whether or not to write the Cluster Timecode using exactly 8 bytes.
bool fixed_size_cluster_timecode_;
+ // Flag whether or not to estimate the file duration.
+ bool estimate_file_duration_;
+
// The size of the EBML header, used to validate the header if
// WriteEbmlHeader() is called more than once.
int32_t ebml_header_size_;
@@ -1682,6 +1905,9 @@ class Segment {
uint32_t doc_type_version_;
uint32_t doc_type_version_written_;
+ // If |duration_| is > 0, then explicitly set the duration of the segment.
+ double duration_;
+
// Pointer to the writer objects. Not owned by this class.
IMkvWriter* writer_cluster_;
IMkvWriter* writer_cues_;
diff --git a/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc b/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
index 3562b8ab8..b9972de63 100644
--- a/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
+++ b/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc
@@ -31,20 +31,20 @@ namespace {
// Date elements are always 8 octets in size.
const int kDateElementSize = 8;
-uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
- int64_t timecode, uint64_t timecode_scale) {
- uint64_t block_additional_elem_size = 0;
- uint64_t block_addid_elem_size = 0;
- uint64_t block_more_payload_size = 0;
- uint64_t block_more_elem_size = 0;
- uint64_t block_additions_payload_size = 0;
- uint64_t block_additions_elem_size = 0;
+uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
+ uint64 timecode_scale) {
+ uint64 block_additional_elem_size = 0;
+ uint64 block_addid_elem_size = 0;
+ uint64 block_more_payload_size = 0;
+ uint64 block_more_elem_size = 0;
+ uint64 block_additions_payload_size = 0;
+ uint64 block_additions_elem_size = 0;
if (frame->additional()) {
block_additional_elem_size =
EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(),
frame->additional_length());
- block_addid_elem_size =
- EbmlElementSize(libwebm::kMkvBlockAddID, frame->add_id());
+ block_addid_elem_size = EbmlElementSize(
+ libwebm::kMkvBlockAddID, static_cast<uint64>(frame->add_id()));
block_more_payload_size =
block_addid_elem_size + block_additional_elem_size;
@@ -58,32 +58,33 @@ uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
block_additions_payload_size;
}
- uint64_t discard_padding_elem_size = 0;
+ uint64 discard_padding_elem_size = 0;
if (frame->discard_padding() != 0) {
discard_padding_elem_size =
- EbmlElementSize(libwebm::kMkvDiscardPadding, frame->discard_padding());
+ EbmlElementSize(libwebm::kMkvDiscardPadding,
+ static_cast<int64>(frame->discard_padding()));
}
- const uint64_t reference_block_timestamp =
+ const uint64 reference_block_timestamp =
frame->reference_block_timestamp() / timecode_scale;
- uint64_t reference_block_elem_size = 0;
+ uint64 reference_block_elem_size = 0;
if (!frame->is_key()) {
reference_block_elem_size =
EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp);
}
- const uint64_t duration = frame->duration() / timecode_scale;
- uint64_t block_duration_elem_size = 0;
+ const uint64 duration = frame->duration() / timecode_scale;
+ uint64 block_duration_elem_size = 0;
if (duration > 0)
block_duration_elem_size =
EbmlElementSize(libwebm::kMkvBlockDuration, duration);
- const uint64_t block_payload_size = 4 + frame->length();
- const uint64_t block_elem_size =
+ const uint64 block_payload_size = 4 + frame->length();
+ const uint64 block_elem_size =
EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) +
block_payload_size;
- const uint64_t block_group_payload_size =
+ const uint64 block_group_payload_size =
block_elem_size + block_additions_elem_size + block_duration_elem_size +
discard_padding_elem_size + reference_block_elem_size;
@@ -105,7 +106,7 @@ uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
if (SerializeInt(writer, 0, 1))
return 0;
- if (writer->Write(frame->frame(), static_cast<uint32_t>(frame->length())))
+ if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
return 0;
if (frame->additional()) {
@@ -118,7 +119,8 @@ uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
block_more_payload_size))
return 0;
- if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID, frame->add_id()))
+ if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID,
+ static_cast<uint64>(frame->add_id())))
return 0;
if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional,
@@ -129,7 +131,7 @@ uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
if (frame->discard_padding() != 0 &&
!WriteEbmlElement(writer, libwebm::kMkvDiscardPadding,
- frame->discard_padding())) {
+ static_cast<int64>(frame->discard_padding()))) {
return false;
}
@@ -148,38 +150,38 @@ uint64_t WriteBlock(IMkvWriter* writer, const Frame* const frame,
block_group_payload_size;
}
-uint64_t WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
- int64_t timecode) {
+uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
+ int64 timecode) {
if (WriteID(writer, libwebm::kMkvSimpleBlock))
return 0;
- const int32_t size = static_cast<int32_t>(frame->length()) + 4;
+ const int32 size = static_cast<int32>(frame->length()) + 4;
if (WriteUInt(writer, size))
return 0;
- if (WriteUInt(writer, static_cast<uint64_t>(frame->track_number())))
+ if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
return 0;
if (SerializeInt(writer, timecode, 2))
return 0;
- uint64_t flags = 0;
+ uint64 flags = 0;
if (frame->is_key())
flags |= 0x80;
if (SerializeInt(writer, flags, 1))
return 0;
- if (writer->Write(frame->frame(), static_cast<uint32_t>(frame->length())))
+ if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
return 0;
- return static_cast<uint64_t>(GetUIntSize(libwebm::kMkvSimpleBlock) +
- GetCodedUIntSize(size) + 4 + frame->length());
+ return GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
+ frame->length();
}
} // namespace
-int32_t GetCodedUIntSize(uint64_t value) {
+int32 GetCodedUIntSize(uint64 value) {
if (value < 0x000000000000007FULL)
return 1;
else if (value < 0x0000000000003FFFULL)
@@ -197,7 +199,7 @@ int32_t GetCodedUIntSize(uint64_t value) {
return 8;
}
-int32_t GetUIntSize(uint64_t value) {
+int32 GetUIntSize(uint64 value) {
if (value < 0x0000000000000100ULL)
return 1;
else if (value < 0x0000000000010000ULL)
@@ -215,26 +217,26 @@ int32_t GetUIntSize(uint64_t value) {
return 8;
}
-int32_t GetIntSize(int64_t value) {
+int32 GetIntSize(int64 value) {
// Doubling the requested value ensures positive values with their high bit
// set are written with 0-padding to avoid flipping the signedness.
- const uint64_t v = (value < 0) ? value ^ -1LL : value;
+ const uint64 v = (value < 0) ? value ^ -1LL : value;
return GetUIntSize(2 * v);
}
-uint64_t EbmlMasterElementSize(uint64_t type, uint64_t value) {
+uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
// Size of EBML ID
- int32_t ebml_size = GetUIntSize(type);
+ int32 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += GetCodedUIntSize(value);
- return static_cast<uint64_t>(ebml_size);
+ return ebml_size;
}
-uint64_t EbmlElementSize(uint64_t type, int64_t value) {
+uint64 EbmlElementSize(uint64 type, int64 value) {
// Size of EBML ID
- int32_t ebml_size = GetUIntSize(type);
+ int32 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += GetIntSize(value);
@@ -242,20 +244,19 @@ uint64_t EbmlElementSize(uint64_t type, int64_t value) {
// Size of Datasize
ebml_size++;
- return static_cast<uint64_t>(ebml_size);
+ return ebml_size;
}
-uint64_t EbmlElementSize(uint64_t type, uint64_t value) {
+uint64 EbmlElementSize(uint64 type, uint64 value) {
return EbmlElementSize(type, value, 0);
}
-uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size) {
+uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size) {
// Size of EBML ID
- uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
+ int32 ebml_size = GetUIntSize(type);
// Datasize
- ebml_size +=
- (fixed_size > 0) ? fixed_size : static_cast<uint64_t>(GetUIntSize(value));
+ ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value);
// Size of Datasize
ebml_size++;
@@ -263,9 +264,9 @@ uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size) {
return ebml_size;
}
-uint64_t EbmlElementSize(uint64_t type, float /* value */) {
+uint64 EbmlElementSize(uint64 type, float /* value */) {
// Size of EBML ID
- uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
+ uint64 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += sizeof(float);
@@ -276,12 +277,12 @@ uint64_t EbmlElementSize(uint64_t type, float /* value */) {
return ebml_size;
}
-uint64_t EbmlElementSize(uint64_t type, const char* value) {
+uint64 EbmlElementSize(uint64 type, const char* value) {
if (!value)
return 0;
// Size of EBML ID
- uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
+ uint64 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += strlen(value);
@@ -292,12 +293,12 @@ uint64_t EbmlElementSize(uint64_t type, const char* value) {
return ebml_size;
}
-uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size) {
+uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
if (!value)
return 0;
// Size of EBML ID
- uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
+ uint64 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += size;
@@ -308,9 +309,9 @@ uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size) {
return ebml_size;
}
-uint64_t EbmlDateElementSize(uint64_t type) {
+uint64 EbmlDateElementSize(uint64 type) {
// Size of EBML ID
- uint64_t ebml_size = static_cast<uint64_t>(GetUIntSize(type));
+ uint64 ebml_size = GetUIntSize(type);
// Datasize
ebml_size += kDateElementSize;
@@ -321,18 +322,18 @@ uint64_t EbmlDateElementSize(uint64_t type) {
return ebml_size;
}
-int32_t SerializeInt(IMkvWriter* writer, int64_t value, int32_t size) {
+int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
if (!writer || size < 1 || size > 8)
return -1;
- for (int32_t i = 1; i <= size; ++i) {
- const int32_t byte_count = size - i;
- const int32_t bit_count = byte_count * 8;
+ for (int32 i = 1; i <= size; ++i) {
+ const int32 byte_count = size - i;
+ const int32 bit_count = byte_count * 8;
- const int64_t bb = value >> bit_count;
- const uint8_t b = static_cast<uint8_t>(bb);
+ const int64 bb = value >> bit_count;
+ const uint8 b = static_cast<uint8>(bb);
- const int32_t status = writer->Write(&b, 1);
+ const int32 status = writer->Write(&b, 1);
if (status < 0)
return status;
@@ -341,26 +342,26 @@ int32_t SerializeInt(IMkvWriter* writer, int64_t value, int32_t size) {
return 0;
}
-int32_t SerializeFloat(IMkvWriter* writer, float f) {
+int32 SerializeFloat(IMkvWriter* writer, float f) {
if (!writer)
return -1;
- assert(sizeof(uint32_t) == sizeof(float));
+ assert(sizeof(uint32) == sizeof(float));
// This union is merely used to avoid a reinterpret_cast from float& to
// uint32& which will result in violation of strict aliasing.
union U32 {
- uint32_t u32;
+ uint32 u32;
float f;
} value;
value.f = f;
- for (int32_t i = 1; i <= 4; ++i) {
- const int32_t byte_count = 4 - i;
- const int32_t bit_count = byte_count * 8;
+ for (int32 i = 1; i <= 4; ++i) {
+ const int32 byte_count = 4 - i;
+ const int32 bit_count = byte_count * 8;
- const uint8_t byte = static_cast<uint8_t>(value.u32 >> bit_count);
+ const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
- const int32_t status = writer->Write(&byte, 1);
+ const int32 status = writer->Write(&byte, 1);
if (status < 0)
return status;
@@ -369,21 +370,21 @@ int32_t SerializeFloat(IMkvWriter* writer, float f) {
return 0;
}
-int32_t WriteUInt(IMkvWriter* writer, uint64_t value) {
+int32 WriteUInt(IMkvWriter* writer, uint64 value) {
if (!writer)
return -1;
- int32_t size = GetCodedUIntSize(value);
+ int32 size = GetCodedUIntSize(value);
return WriteUIntSize(writer, value, size);
}
-int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size) {
+int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
if (!writer || size < 0 || size > 8)
return -1;
if (size > 0) {
- const uint64_t bit = 1LL << (size * 7);
+ const uint64 bit = 1LL << (size * 7);
if (value > (bit - 2))
return -1;
@@ -391,11 +392,11 @@ int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size) {
value |= bit;
} else {
size = 1;
- int64_t bit;
+ int64 bit;
for (;;) {
bit = 1LL << (size * 7);
- const uint64_t max = bit - 2;
+ const uint64 max = bit - 2;
if (value <= max)
break;
@@ -412,18 +413,18 @@ int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size) {
return SerializeInt(writer, value, size);
}
-int32_t WriteID(IMkvWriter* writer, uint64_t type) {
+int32 WriteID(IMkvWriter* writer, uint64 type) {
if (!writer)
return -1;
writer->ElementStartNotify(type, writer->Position());
- const int32_t size = GetUIntSize(type);
+ const int32 size = GetUIntSize(type);
return SerializeInt(writer, type, size);
}
-bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t type, uint64_t size) {
+bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
if (!writer)
return false;
@@ -436,19 +437,19 @@ bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t type, uint64_t size) {
return true;
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
return WriteEbmlElement(writer, type, value, 0);
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
- uint64_t fixed_size) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
+ uint64 fixed_size) {
if (!writer)
return false;
if (WriteID(writer, type))
return false;
- uint64_t size = static_cast<uint64_t>(GetUIntSize(value));
+ uint64 size = GetUIntSize(value);
if (fixed_size > 0) {
if (size > fixed_size)
return false;
@@ -457,30 +458,30 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
if (WriteUInt(writer, size))
return false;
- if (SerializeInt(writer, value, static_cast<int32_t>(size)))
+ if (SerializeInt(writer, value, static_cast<int32>(size)))
return false;
return true;
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, int64_t value) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
if (!writer)
return false;
if (WriteID(writer, type))
return 0;
- const uint64_t size = GetIntSize(value);
+ const uint64 size = GetIntSize(value);
if (WriteUInt(writer, size))
return false;
- if (SerializeInt(writer, value, static_cast<int32_t>(size)))
+ if (SerializeInt(writer, value, static_cast<int32>(size)))
return false;
return true;
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, float value) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
if (!writer)
return false;
@@ -496,25 +497,25 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, float value) {
return true;
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const char* value) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
if (!writer || !value)
return false;
if (WriteID(writer, type))
return false;
- const uint64_t length = strlen(value);
+ const uint64 length = strlen(value);
if (WriteUInt(writer, length))
return false;
- if (writer->Write(value, static_cast<const uint32_t>(length)))
+ if (writer->Write(value, static_cast<const uint32>(length)))
return false;
return true;
}
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
- uint64_t size) {
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
+ uint64 size) {
if (!writer || !value || size < 1)
return false;
@@ -524,13 +525,13 @@ bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
if (WriteUInt(writer, size))
return false;
- if (writer->Write(value, static_cast<uint32_t>(size)))
+ if (writer->Write(value, static_cast<uint32>(size)))
return false;
return true;
}
-bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value) {
+bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
if (!writer)
return false;
@@ -546,8 +547,8 @@ bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value) {
return true;
}
-uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
- Cluster* cluster) {
+uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
+ Cluster* cluster) {
if (!writer || !frame || !frame->IsValid() || !cluster ||
!cluster->timecode_scale())
return 0;
@@ -556,7 +557,7 @@ uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
// timecode for the cluster itself (remember that block timecode
// is a signed, 16-bit integer). However, as a simplification we
// only permit non-negative cluster-relative timecodes for blocks.
- const int64_t relative_timecode = cluster->GetRelativeTimecode(
+ const int64 relative_timecode = cluster->GetRelativeTimecode(
frame->timestamp() / cluster->timecode_scale());
if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
return 0;
@@ -567,20 +568,19 @@ uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
cluster->timecode_scale());
}
-uint64_t WriteVoidElement(IMkvWriter* writer, uint64_t size) {
+uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
if (!writer)
return false;
// Subtract one for the void ID and the coded size.
- uint64_t void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
- uint64_t void_size =
- EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
- void_entry_size;
+ uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
+ uint64 void_size = EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
+ void_entry_size;
if (void_size != size)
return 0;
- const int64_t payload_position = writer->Position();
+ const int64 payload_position = writer->Position();
if (payload_position < 0)
return 0;
@@ -590,30 +590,29 @@ uint64_t WriteVoidElement(IMkvWriter* writer, uint64_t size) {
if (WriteUInt(writer, void_entry_size))
return 0;
- const uint8_t value = 0;
- for (int32_t i = 0; i < static_cast<int32_t>(void_entry_size); ++i) {
+ const uint8 value = 0;
+ for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
if (writer->Write(&value, 1))
return 0;
}
- const int64_t stop_position = writer->Position();
+ const int64 stop_position = writer->Position();
if (stop_position < 0 ||
- stop_position - payload_position != static_cast<int64_t>(void_size))
+ stop_position - payload_position != static_cast<int64>(void_size))
return 0;
return void_size;
}
-void GetVersion(int32_t* major, int32_t* minor, int32_t* build,
- int32_t* revision) {
+void GetVersion(int32* major, int32* minor, int32* build, int32* revision) {
*major = 0;
*minor = 2;
*build = 1;
*revision = 0;
}
-uint64_t MakeUID(unsigned int* seed) {
- uint64_t uid = 0;
+uint64 MakeUID(unsigned int* seed) {
+ uint64 uid = 0;
#ifdef __MINGW32__
srand(*seed);
@@ -625,21 +624,22 @@ uint64_t MakeUID(unsigned int* seed) {
// TODO(fgalligan): Move random number generation to platform specific code.
#ifdef _MSC_VER
(void)seed;
- const int32_t nn = rand();
+ const int32 nn = rand();
#elif __ANDROID__
- int32_t temp_num = 1;
+ (void)seed;
+ int32 temp_num = 1;
int fd = open("/dev/urandom", O_RDONLY);
if (fd != -1) {
read(fd, &temp_num, sizeof(temp_num));
close(fd);
}
- const int32_t nn = temp_num;
+ const int32 nn = temp_num;
#elif defined __MINGW32__
- const int32_t nn = rand();
+ const int32 nn = rand();
#else
- const int32_t nn = rand_r(seed);
+ const int32 nn = rand_r(seed);
#endif
- const int32_t n = 0xFF & (nn >> 4); // throw away low-order bits
+ const int32 n = 0xFF & (nn >> 4); // throw away low-order bits
uid |= n;
}
@@ -647,4 +647,97 @@ uint64_t MakeUID(unsigned int* seed) {
return uid;
}
+bool IsMatrixCoefficientsValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kGbr:
+ case mkvmuxer::Colour::kBt709:
+ case mkvmuxer::Colour::kUnspecifiedMc:
+ case mkvmuxer::Colour::kReserved:
+ case mkvmuxer::Colour::kFcc:
+ case mkvmuxer::Colour::kBt470bg:
+ case mkvmuxer::Colour::kSmpte170MMc:
+ case mkvmuxer::Colour::kSmpte240MMc:
+ case mkvmuxer::Colour::kYcocg:
+ case mkvmuxer::Colour::kBt2020NonConstantLuminance:
+ case mkvmuxer::Colour::kBt2020ConstantLuminance:
+ return true;
+ }
+ return false;
+}
+
+bool IsChromaSitingHorzValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kUnspecifiedCsh:
+ case mkvmuxer::Colour::kLeftCollocated:
+ case mkvmuxer::Colour::kHalfCsh:
+ return true;
+ }
+ return false;
+}
+
+bool IsChromaSitingVertValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kUnspecifiedCsv:
+ case mkvmuxer::Colour::kTopCollocated:
+ case mkvmuxer::Colour::kHalfCsv:
+ return true;
+ }
+ return false;
+}
+
+bool IsColourRangeValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kUnspecifiedCr:
+ case mkvmuxer::Colour::kBroadcastRange:
+ case mkvmuxer::Colour::kFullRange:
+ case mkvmuxer::Colour::kMcTcDefined:
+ return true;
+ }
+ return false;
+}
+
+bool IsTransferCharacteristicsValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kIturBt709Tc:
+ case mkvmuxer::Colour::kUnspecifiedTc:
+ case mkvmuxer::Colour::kReservedTc:
+ case mkvmuxer::Colour::kGamma22Curve:
+ case mkvmuxer::Colour::kGamma28Curve:
+ case mkvmuxer::Colour::kSmpte170MTc:
+ case mkvmuxer::Colour::kSmpte240MTc:
+ case mkvmuxer::Colour::kLinear:
+ case mkvmuxer::Colour::kLog:
+ case mkvmuxer::Colour::kLogSqrt:
+ case mkvmuxer::Colour::kIec6196624:
+ case mkvmuxer::Colour::kIturBt1361ExtendedColourGamut:
+ case mkvmuxer::Colour::kIec6196621:
+ case mkvmuxer::Colour::kIturBt202010bit:
+ case mkvmuxer::Colour::kIturBt202012bit:
+ case mkvmuxer::Colour::kSmpteSt2084:
+ case mkvmuxer::Colour::kSmpteSt4281Tc:
+ case mkvmuxer::Colour::kAribStdB67Hlg:
+ return true;
+ }
+ return false;
+}
+
+bool IsPrimariesValueValid(uint64_t value) {
+ switch (value) {
+ case mkvmuxer::Colour::kReservedP0:
+ case mkvmuxer::Colour::kIturBt709P:
+ case mkvmuxer::Colour::kUnspecifiedP:
+ case mkvmuxer::Colour::kReservedP3:
+ case mkvmuxer::Colour::kIturBt470M:
+ case mkvmuxer::Colour::kIturBt470Bg:
+ case mkvmuxer::Colour::kSmpte170MP:
+ case mkvmuxer::Colour::kSmpte240MP:
+ case mkvmuxer::Colour::kFilm:
+ case mkvmuxer::Colour::kIturBt2020:
+ case mkvmuxer::Colour::kSmpteSt4281P:
+ case mkvmuxer::Colour::kJedecP22Phosphors:
+ return true;
+ }
+ return false;
+}
+
} // namespace mkvmuxer
diff --git a/third_party/libwebm/mkvmuxer/mkvmuxerutil.h b/third_party/libwebm/mkvmuxer/mkvmuxerutil.h
index 0e21a2dcb..132388da5 100644
--- a/third_party/libwebm/mkvmuxer/mkvmuxerutil.h
+++ b/third_party/libwebm/mkvmuxer/mkvmuxerutil.h
@@ -8,87 +8,104 @@
#ifndef MKVMUXER_MKVMUXERUTIL_H_
#define MKVMUXER_MKVMUXERUTIL_H_
-#include <stdint.h>
+#include "mkvmuxertypes.h"
+
+#include "stdint.h"
namespace mkvmuxer {
class Cluster;
class Frame;
class IMkvWriter;
-const uint64_t kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL;
-const int64_t kMaxBlockTimecode = 0x07FFFLL;
+// TODO(tomfinegan): mkvmuxer:: integer types continue to be used here because
+// changing them causes pain for downstream projects. It would be nice if a
+// solution that allows removal of the mkvmuxer:: integer types while avoiding
+// pain for downstream users of libwebm. Considering that mkvmuxerutil.{cc,h}
+// are really, for the great majority of cases, EBML size calculation and writer
+// functions, perhaps a more EBML focused utility would be the way to go as a
+// first step.
+
+const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL;
+const int64 kMaxBlockTimecode = 0x07FFFLL;
// Writes out |value| in Big Endian order. Returns 0 on success.
-int32_t SerializeInt(IMkvWriter* writer, int64_t value, int32_t size);
+int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
// Returns the size in bytes of the element.
-int32_t GetUIntSize(uint64_t value);
-int32_t GetIntSize(int64_t value);
-int32_t GetCodedUIntSize(uint64_t value);
-uint64_t EbmlMasterElementSize(uint64_t type, uint64_t value);
-uint64_t EbmlElementSize(uint64_t type, int64_t value);
-uint64_t EbmlElementSize(uint64_t type, uint64_t value);
-uint64_t EbmlElementSize(uint64_t type, float value);
-uint64_t EbmlElementSize(uint64_t type, const char* value);
-uint64_t EbmlElementSize(uint64_t type, const uint8_t* value, uint64_t size);
-uint64_t EbmlDateElementSize(uint64_t type);
+int32 GetUIntSize(uint64 value);
+int32 GetIntSize(int64 value);
+int32 GetCodedUIntSize(uint64 value);
+uint64 EbmlMasterElementSize(uint64 type, uint64 value);
+uint64 EbmlElementSize(uint64 type, int64 value);
+uint64 EbmlElementSize(uint64 type, uint64 value);
+uint64 EbmlElementSize(uint64 type, float value);
+uint64 EbmlElementSize(uint64 type, const char* value);
+uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size);
+uint64 EbmlDateElementSize(uint64 type);
// Returns the size in bytes of the element assuming that the element was
// written using |fixed_size| bytes. If |fixed_size| is set to zero, then it
// computes the necessary number of bytes based on |value|.
-uint64_t EbmlElementSize(uint64_t type, uint64_t value, uint64_t fixed_size);
+uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size);
// Creates an EBML coded number from |value| and writes it out. The size of
// the coded number is determined by the value of |value|. |value| must not
// be in a coded form. Returns 0 on success.
-int32_t WriteUInt(IMkvWriter* writer, uint64_t value);
+int32 WriteUInt(IMkvWriter* writer, uint64 value);
// Creates an EBML coded number from |value| and writes it out. The size of
// the coded number is determined by the value of |size|. |value| must not
// be in a coded form. Returns 0 on success.
-int32_t WriteUIntSize(IMkvWriter* writer, uint64_t value, int32_t size);
+int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size);
// Output an Mkv master element. Returns true if the element was written.
-bool WriteEbmlMasterElement(IMkvWriter* writer, uint64_t value, uint64_t size);
+bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size);
// Outputs an Mkv ID, calls |IMkvWriter::ElementStartNotify|, and passes the
// ID to |SerializeInt|. Returns 0 on success.
-int32_t WriteID(IMkvWriter* writer, uint64_t type);
+int32 WriteID(IMkvWriter* writer, uint64 type);
// Output an Mkv non-master element. Returns true if the element was written.
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value);
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, int64_t value);
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, float value);
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const char* value);
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, const uint8_t* value,
- uint64_t size);
-bool WriteEbmlDateElement(IMkvWriter* writer, uint64_t type, int64_t value);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
+ uint64 size);
+bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value);
// Output an Mkv non-master element using fixed size. The element will be
// written out using exactly |fixed_size| bytes. If |fixed_size| is set to zero
// then it computes the necessary number of bytes based on |value|. Returns true
// if the element was written.
-bool WriteEbmlElement(IMkvWriter* writer, uint64_t type, uint64_t value,
- uint64_t fixed_size);
+bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
+ uint64 fixed_size);
// Output a Mkv Frame. It decides the correct element to write (Block vs
// SimpleBlock) based on the parameters of the Frame.
-uint64_t WriteFrame(IMkvWriter* writer, const Frame* const frame,
- Cluster* cluster);
+uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
+ Cluster* cluster);
// Output a void element. |size| must be the entire size in bytes that will be
// void. The function will calculate the size of the void header and subtract
// it from |size|.
-uint64_t WriteVoidElement(IMkvWriter* writer, uint64_t size);
+uint64 WriteVoidElement(IMkvWriter* writer, uint64 size);
// Returns the version number of the muxer in |major|, |minor|, |build|,
// and |revision|.
-void GetVersion(int32_t* major, int32_t* minor, int32_t* build,
- int32_t* revision);
+void GetVersion(int32* major, int32* minor, int32* build, int32* revision);
// Returns a random number to be used for UID, using |seed| to seed
// the random-number generator (see POSIX rand_r() for semantics).
-uint64_t MakeUID(unsigned int* seed);
+uint64 MakeUID(unsigned int* seed);
+
+// Colour field validation helpers. All return true when |value| is valid.
+bool IsMatrixCoefficientsValueValid(uint64_t value);
+bool IsChromaSitingHorzValueValid(uint64_t value);
+bool IsChromaSitingVertValueValid(uint64_t value);
+bool IsColourRangeValueValid(uint64_t value);
+bool IsTransferCharacteristicsValueValid(uint64_t value);
+bool IsPrimariesValueValid(uint64_t value);
} // namespace mkvmuxer
diff --git a/third_party/libwebm/mkvmuxer/mkvwriter.cc b/third_party/libwebm/mkvmuxer/mkvwriter.cc
index ca48e149c..ec34e4df8 100644
--- a/third_party/libwebm/mkvmuxer/mkvwriter.cc
+++ b/third_party/libwebm/mkvmuxer/mkvwriter.cc
@@ -77,7 +77,7 @@ int32 MkvWriter::Position(int64 position) {
#ifdef _MSC_VER
return _fseeki64(file_, position, SEEK_SET);
#else
- return fseek(file_, position, SEEK_SET);
+ return fseeko(file_, static_cast<off_t>(position), SEEK_SET);
#endif
}
diff --git a/third_party/libwebm/mkvparser/mkvparser.cc b/third_party/libwebm/mkvparser/mkvparser.cc
index 21801154d..d92637b75 100644
--- a/third_party/libwebm/mkvparser/mkvparser.cc
+++ b/third_party/libwebm/mkvparser/mkvparser.cc
@@ -25,6 +25,7 @@
namespace mkvparser {
const float MasteringMetadata::kValueNotPresent = FLT_MAX;
const long long Colour::kValueNotPresent = LLONG_MAX;
+const float Projection::kValueNotPresent = FLT_MAX;
#ifdef MSC_COMPAT
inline bool isnan(double val) { return !!_isnan(val); }
@@ -1475,6 +1476,8 @@ long Segment::Load() {
}
}
+SeekHead::Entry::Entry() : id(0), pos(0), element_start(0), element_size(0) {}
+
SeekHead::SeekHead(Segment* pSegment, long long start, long long size_,
long long element_start, long long element_size)
: m_pSegment(pSegment),
@@ -1766,18 +1769,7 @@ bool SeekHead::ParseEntry(IMkvReader* pReader, long long start, long long size_,
if ((pos + seekIdSize) > stop)
return false;
- // Note that the SeekId payload really is serialized
- // as a "Matroska integer", not as a plain binary value.
- // In fact, Matroska requires that ID values in the
- // stream exactly match the binary representation as listed
- // in the Matroska specification.
- //
- // This parser is more liberal, and permits IDs to have
- // any width. (This could make the representation in the stream
- // different from what's in the spec, but it doesn't matter here,
- // since we always normalize "Matroska integer" values.)
-
- pEntry->id = ReadUInt(pReader, pos, len); // payload
+ pEntry->id = ReadID(pReader, pos, len); // payload
if (pEntry->id <= 0)
return false;
@@ -5188,11 +5180,92 @@ bool Colour::Parse(IMkvReader* reader, long long colour_start,
return true;
}
+bool Projection::Parse(IMkvReader* reader, long long start, long long size,
+ Projection** projection) {
+ if (!reader || *projection)
+ return false;
+
+ std::auto_ptr<Projection> projection_ptr(new Projection());
+ if (!projection_ptr.get())
+ return false;
+
+ const long long end = start + size;
+ long long read_pos = start;
+
+ while (read_pos < end) {
+ long long child_id = 0;
+ long long child_size = 0;
+
+ const long long status =
+ ParseElementHeader(reader, read_pos, end, child_id, child_size);
+ if (status < 0)
+ return false;
+
+ if (child_id == libwebm::kMkvProjectionType) {
+ long long projection_type = kTypeNotPresent;
+ projection_type = UnserializeUInt(reader, read_pos, child_size);
+ if (projection_type < 0)
+ return false;
+
+ projection_ptr->type = static_cast<ProjectionType>(projection_type);
+ } else if (child_id == libwebm::kMkvProjectionPrivate) {
+ unsigned char* data = SafeArrayAlloc<unsigned char>(1, child_size);
+
+ if (data == NULL)
+ return false;
+
+ const int status =
+ reader->Read(read_pos, static_cast<long>(child_size), data);
+
+ if (status) {
+ delete[] data;
+ return status;
+ }
+
+ projection_ptr->private_data = data;
+ projection_ptr->private_data_length = static_cast<size_t>(child_size);
+ } else {
+ double value = 0;
+ const long long value_parse_status =
+ UnserializeFloat(reader, read_pos, child_size, value);
+ if (value_parse_status < 0) {
+ return false;
+ }
+
+ switch (child_id) {
+ case libwebm::kMkvProjectionPoseYaw:
+ projection_ptr->pose_yaw = static_cast<float>(value);
+ break;
+ case libwebm::kMkvProjectionPosePitch:
+ projection_ptr->pose_pitch = static_cast<float>(value);
+ break;
+ case libwebm::kMkvProjectionPoseRoll:
+ projection_ptr->pose_roll = static_cast<float>(value);
+ break;
+ default:
+ return false;
+ }
+ }
+
+ read_pos += child_size;
+ if (read_pos > end)
+ return false;
+ }
+
+ *projection = projection_ptr.release();
+ return true;
+}
+
VideoTrack::VideoTrack(Segment* pSegment, long long element_start,
long long element_size)
- : Track(pSegment, element_start, element_size), m_colour(NULL) {}
+ : Track(pSegment, element_start, element_size),
+ m_colour(NULL),
+ m_projection(NULL) {}
-VideoTrack::~VideoTrack() { delete m_colour; }
+VideoTrack::~VideoTrack() {
+ delete m_colour;
+ delete m_projection;
+}
long VideoTrack::Parse(Segment* pSegment, const Info& info,
long long element_start, long long element_size,
@@ -5224,6 +5297,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
const long long stop = pos + s.size;
Colour* colour = NULL;
+ Projection* projection = NULL;
while (pos < stop) {
long long id, size;
@@ -5274,6 +5348,9 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
} else if (id == libwebm::kMkvColour) {
if (!Colour::Parse(pReader, pos, size, &colour))
return E_FILE_FORMAT_INVALID;
+ } else if (id == libwebm::kMkvProjection) {
+ if (!Projection::Parse(pReader, pos, size, &projection))
+ return E_FILE_FORMAT_INVALID;
}
pos += size; // consume payload
@@ -5305,6 +5382,7 @@ long VideoTrack::Parse(Segment* pSegment, const Info& info,
pTrack->m_stereo_mode = stereo_mode;
pTrack->m_rate = rate;
pTrack->m_colour = colour;
+ pTrack->m_projection = projection;
pResult = pTrack;
return 0; // success
@@ -5405,6 +5483,8 @@ long VideoTrack::Seek(long long time_ns, const BlockEntry*& pResult) const {
Colour* VideoTrack::GetColour() const { return m_colour; }
+Projection* VideoTrack::GetProjection() const { return m_projection; }
+
long long VideoTrack::GetWidth() const { return m_width; }
long long VideoTrack::GetHeight() const { return m_height; }
@@ -6698,8 +6778,10 @@ Cluster::Cluster(Segment* pSegment, long idx, long long element_start
{}
Cluster::~Cluster() {
- if (m_entries_count <= 0)
+ if (m_entries_count <= 0) {
+ delete[] m_entries;
return;
+ }
BlockEntry** i = m_entries;
BlockEntry** const j = m_entries + m_entries_count;
diff --git a/third_party/libwebm/mkvparser/mkvparser.h b/third_party/libwebm/mkvparser/mkvparser.h
index 42e6e88ab..26c2b7e5e 100644
--- a/third_party/libwebm/mkvparser/mkvparser.h
+++ b/third_party/libwebm/mkvparser/mkvparser.h
@@ -473,6 +473,34 @@ struct Colour {
MasteringMetadata* mastering_metadata;
};
+struct Projection {
+ enum ProjectionType {
+ kTypeNotPresent = -1,
+ kRectangular = 0,
+ kEquirectangular = 1,
+ kCubeMap = 2,
+ kMesh = 3,
+ };
+ static const float kValueNotPresent;
+ Projection()
+ : type(kTypeNotPresent),
+ private_data(NULL),
+ private_data_length(0),
+ pose_yaw(kValueNotPresent),
+ pose_pitch(kValueNotPresent),
+ pose_roll(kValueNotPresent) {}
+ ~Projection() { delete[] private_data; }
+ static bool Parse(IMkvReader* reader, long long element_start,
+ long long element_size, Projection** projection);
+
+ ProjectionType type;
+ unsigned char* private_data;
+ size_t private_data_length;
+ float pose_yaw;
+ float pose_pitch;
+ float pose_roll;
+};
+
class VideoTrack : public Track {
VideoTrack(const VideoTrack&);
VideoTrack& operator=(const VideoTrack&);
@@ -497,6 +525,8 @@ class VideoTrack : public Track {
Colour* GetColour() const;
+ Projection* GetProjection() const;
+
private:
long long m_width;
long long m_height;
@@ -508,6 +538,7 @@ class VideoTrack : public Track {
double m_rate;
Colour* m_colour;
+ Projection* m_projection;
};
class AudioTrack : public Track {
@@ -813,6 +844,8 @@ class SeekHead {
long Parse();
struct Entry {
+ Entry();
+
// the SeekHead entry payload
long long id;
long long pos;
diff --git a/third_party/libwebm/mkvparser/mkvreader.cc b/third_party/libwebm/mkvparser/mkvreader.cc
index 9f90d8c4f..b8fd00c26 100644
--- a/third_party/libwebm/mkvparser/mkvreader.cc
+++ b/third_party/libwebm/mkvparser/mkvreader.cc
@@ -117,7 +117,7 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
if (status)
return -1; // error
#else
- fseek(m_file, offset, SEEK_SET);
+ fseeko(m_file, static_cast<off_t>(offset), SEEK_SET);
#endif
const size_t size = fread(buffer, 1, len, m_file);
@@ -128,4 +128,4 @@ int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
return 0; // success
}
-} // namespace mkvparser \ No newline at end of file
+} // namespace mkvparser