Validate Colour element values.

webm:1284

Change-Id: Idc9fc2eee41e7ab445d90366c5ee3e8ca2509c81
This commit is contained in:
Tom Finegan 2016-08-31 21:18:24 -07:00
parent 8036925b43
commit 93e9fb35f9
7 changed files with 247 additions and 12 deletions

View File

@ -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;

View File

@ -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|.

View File

@ -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

View File

@ -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_

View File

@ -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));

View File

@ -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<const VideoTrack*>(
segment_->GetTracks()->GetTrackByIndex(0));
const VideoTrack* const video_track =
static_cast<const VideoTrack*>(segment_->GetTracks()->GetTrackByIndex(0));
const mkvparser::Projection* const projection = video_track->GetProjection();
ASSERT_TRUE(projection != nullptr);

Binary file not shown.