From 93e9fb35f923b62365da4f9983ea4c949a05fc28 Mon Sep 17 00:00:00 2001 From: Tom Finegan Date: Wed, 31 Aug 2016 21:18:24 -0700 Subject: [PATCH] Validate Colour element values. webm:1284 Change-Id: Idc9fc2eee41e7ab445d90366c5ee3e8ca2509c81 --- mkvmuxer/mkvmuxer.cc | 61 +++++++++++++++++++++++ mkvmuxer/mkvmuxer.h | 73 ++++++++++++++++++++++++++- mkvmuxer/mkvmuxerutil.cc | 93 +++++++++++++++++++++++++++++++++++ mkvmuxer/mkvmuxerutil.h | 10 ++++ testing/mkvmuxer_tests.cc | 12 ++--- testing/mkvparser_tests.cc | 10 ++-- testing/testdata/colour.webm | Bin 416 -> 416 bytes 7 files changed, 247 insertions(+), 12 deletions(-) diff --git a/mkvmuxer/mkvmuxer.cc b/mkvmuxer/mkvmuxer.cc index 32aeda0..bc81634 100644 --- a/mkvmuxer/mkvmuxer.cc +++ b/mkvmuxer/mkvmuxer.cc @@ -26,6 +26,11 @@ 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; @@ -957,10 +962,18 @@ uint64_t PrimaryChromaticity::PrimaryChromaticitySize( bool PrimaryChromaticity::Write(IMkvWriter* writer, libwebm::MkvId x_id, libwebm::MkvId y_id) const { + 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 { uint64_t size = PayloadSize(); @@ -970,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(); @@ -1080,6 +1118,25 @@ uint64_t Colour::ColourSize() const { return size; } +bool Colour::Valid() const { + if (mastering_metadata_ && !mastering_metadata_->Valid()) + return false; + if (!IsMatrixCoefficientsValueValid(matrix_coefficients_)) + return false; + if (!IsChromaSitingHorzValueValid(chroma_siting_horz_)) + return false; + if (!IsChromaSitingVertValueValid(chroma_siting_vert_)) + return false; + if (!IsColourRangeValueValid(range_)) + return false; + if (!IsTransferCharacteristicsValueValid(transfer_characteristics_)) + return false; + if (!IsPrimariesValueValid(primaries_)) + return false; + + return true; +} + bool Colour::Write(IMkvWriter* writer) const { const uint64_t size = PayloadSize(); @@ -1087,6 +1144,10 @@ 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; diff --git a/mkvmuxer/mkvmuxer.h b/mkvmuxer/mkvmuxer.h index 7aa9632..386a2b2 100644 --- a/mkvmuxer/mkvmuxer.h +++ b/mkvmuxer/mkvmuxer.h @@ -356,6 +356,9 @@ class ContentEncoding { // Colour element. 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() {} @@ -363,7 +366,7 @@ class PrimaryChromaticity { // 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; @@ -380,6 +383,9 @@ class PrimaryChromaticity { class MasteringMetadata { public: static const float kValueNotPresent; + static const float kMinLuminance; + static const float kMinLuminanceMax; + static const float kMaxLuminanceMax; MasteringMetadata() : luminance_max_(kValueNotPresent), @@ -397,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. @@ -432,6 +439,69 @@ 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), @@ -452,6 +522,7 @@ class Colour { // Returns total size of the Colour element. uint64_t ColourSize() const; + bool Valid() const; bool Write(IMkvWriter* writer) const; // Deep copies |mastering_metadata|. diff --git a/mkvmuxer/mkvmuxerutil.cc b/mkvmuxer/mkvmuxerutil.cc index 01dc070..71d4dd1 100644 --- a/mkvmuxer/mkvmuxerutil.cc +++ b/mkvmuxer/mkvmuxerutil.cc @@ -646,4 +646,97 @@ uint64 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/mkvmuxer/mkvmuxerutil.h b/mkvmuxer/mkvmuxerutil.h index 2c9bdab..132388d 100644 --- a/mkvmuxer/mkvmuxerutil.h +++ b/mkvmuxer/mkvmuxerutil.h @@ -10,6 +10,8 @@ #include "mkvmuxertypes.h" +#include "stdint.h" + namespace mkvmuxer { class Cluster; class Frame; @@ -97,6 +99,14 @@ void GetVersion(int32* major, int32* minor, int32* build, int32* revision); // the random-number generator (see POSIX rand_r() for semantics). 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 #endif // MKVMUXER_MKVMUXERUTIL_H_ diff --git a/testing/mkvmuxer_tests.cc b/testing/mkvmuxer_tests.cc index 807b670..2eb6e0f 100644 --- a/testing/mkvmuxer_tests.cc +++ b/testing/mkvmuxer_tests.cc @@ -773,17 +773,17 @@ TEST_F(MuxerTest, Colour) { muxer_mm.SetChromaticity(&muxer_pc, &muxer_pc, &muxer_pc, &muxer_pc)); mkvmuxer::Colour muxer_colour; - muxer_colour.set_matrix_coefficients(0); + muxer_colour.set_matrix_coefficients(mkvmuxer::Colour::kGbr); muxer_colour.set_bits_per_channel(1); muxer_colour.set_chroma_subsampling_horz(2); muxer_colour.set_chroma_subsampling_vert(3); muxer_colour.set_cb_subsampling_horz(4); muxer_colour.set_cb_subsampling_vert(5); - muxer_colour.set_chroma_siting_horz(6); - muxer_colour.set_chroma_siting_vert(7); - muxer_colour.set_range(8); - muxer_colour.set_transfer_characteristics(9); - muxer_colour.set_primaries(10); + muxer_colour.set_chroma_siting_horz(mkvmuxer::Colour::kLeftCollocated); + muxer_colour.set_chroma_siting_vert(mkvmuxer::Colour::kTopCollocated); + muxer_colour.set_range(mkvmuxer::Colour::kFullRange); + muxer_colour.set_transfer_characteristics(mkvmuxer::Colour::kLog); + muxer_colour.set_primaries(mkvmuxer::Colour::kSmpteSt4281P); muxer_colour.set_max_cll(11); muxer_colour.set_max_fall(12); ASSERT_TRUE(muxer_colour.SetMasteringMetadata(muxer_mm)); diff --git a/testing/mkvparser_tests.cc b/testing/mkvparser_tests.cc index aaeb9b3..d3ce87a 100644 --- a/testing/mkvparser_tests.cc +++ b/testing/mkvparser_tests.cc @@ -621,9 +621,9 @@ TEST_F(ParserTest, CanParseColour) { EXPECT_EQ(3u, colour->chroma_subsampling_vert); EXPECT_EQ(4u, colour->cb_subsampling_horz); EXPECT_EQ(5u, colour->cb_subsampling_vert); - EXPECT_EQ(6u, colour->chroma_siting_horz); - EXPECT_EQ(7u, colour->chroma_siting_vert); - EXPECT_EQ(8u, colour->range); + EXPECT_EQ(1u, colour->chroma_siting_horz); + EXPECT_EQ(1u, colour->chroma_siting_vert); + EXPECT_EQ(2u, colour->range); EXPECT_EQ(9u, colour->transfer_characteristics); EXPECT_EQ(10u, colour->primaries); EXPECT_EQ(11u, colour->max_cll); @@ -652,8 +652,8 @@ TEST_F(ParserTest, CanParseProjection) { ASSERT_TRUE(CreateAndLoadSegment("projection.webm")); const unsigned int kTracksCount = 1; EXPECT_EQ(kTracksCount, segment_->GetTracks()->GetTracksCount()); - const VideoTrack* const video_track = static_cast( - segment_->GetTracks()->GetTrackByIndex(0)); + const VideoTrack* const video_track = + static_cast(segment_->GetTracks()->GetTrackByIndex(0)); const mkvparser::Projection* const projection = video_track->GetProjection(); ASSERT_TRUE(projection != nullptr); diff --git a/testing/testdata/colour.webm b/testing/testdata/colour.webm index ddd1c53af66f226ebff458a41425c17f6a2340a0..580cb50aad5e262b9a80ffd04199c9760e7cd629 100644 GIT binary patch delta 21 ccmZ3$ynuOwJR>J#=#ECl(4CD;lQkGC07ktAbpQYW delta 21 ccmZ3$ynuOwJR>Jt=#EDA(4CDOlQkGC07p^=h5!Hn