Support v1 vp9 in iso-bmff
- Implemented according to v1.0 spec @ https://www.webmproject.org/vp9/mp4/ - v0 is no longer supported Change-Id: I189c813d788400beda797eea7da943a83dfa7d79
This commit is contained in:
parent
4d81979b16
commit
59f393779c
|
@ -20,10 +20,10 @@
|
||||||
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
||||||
</ContentProtection>
|
</ContentProtection>
|
||||||
<Representation id="1" bandwidth="210193" codecs="vp09.00.00.08.00.01.00.00" mimeType="video/mp4" sar="427:320">
|
<Representation id="1" bandwidth="210205" codecs="vp09.00.10.08.01.02.02.02.00" mimeType="video/mp4" sar="427:320">
|
||||||
<BaseURL>output_video.mp4</BaseURL>
|
<BaseURL>output_video.mp4</BaseURL>
|
||||||
<SegmentBase indexRange="1059-1126" timescale="1000000">
|
<SegmentBase indexRange="1063-1130" timescale="1000000">
|
||||||
<Initialization range="0-1058"/>
|
<Initialization range="0-1062"/>
|
||||||
</SegmentBase>
|
</SegmentBase>
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -12,10 +12,10 @@
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
<AdaptationSet id="1" contentType="video" width="320" height="240" frameRate="1000000/34000" par="16:9">
|
<AdaptationSet id="1" contentType="video" width="320" height="240" frameRate="1000000/34000" par="16:9">
|
||||||
<Representation id="1" bandwidth="203351" codecs="vp9" mimeType="video/webm" sar="427:320">
|
<Representation id="1" bandwidth="203360" codecs="vp9" mimeType="video/webm" sar="427:320">
|
||||||
<BaseURL>output_video.webm</BaseURL>
|
<BaseURL>output_video.webm</BaseURL>
|
||||||
<SegmentBase indexRange="299-347" timescale="1000000">
|
<SegmentBase indexRange="302-350" timescale="1000000">
|
||||||
<Initialization range="0-298"/>
|
<Initialization range="0-301"/>
|
||||||
</SegmentBase>
|
</SegmentBase>
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
|
|
Binary file not shown.
|
@ -7,10 +7,10 @@
|
||||||
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
||||||
</ContentProtection>
|
</ContentProtection>
|
||||||
<Representation id="0" bandwidth="341006" codecs="vp08.00.00.08.01.01.00.00" mimeType="video/mp4" sar="1:1">
|
<Representation id="0" bandwidth="341018" codecs="vp08.00.10.08.01.02.02.02.00" mimeType="video/mp4" sar="1:1">
|
||||||
<BaseURL>output_video.mp4</BaseURL>
|
<BaseURL>output_video.mp4</BaseURL>
|
||||||
<SegmentBase indexRange="1027-1094" timescale="1000000">
|
<SegmentBase indexRange="1031-1098" timescale="1000000">
|
||||||
<Initialization range="0-1026"/>
|
<Initialization range="0-1030"/>
|
||||||
</SegmentBase>
|
</SegmentBase>
|
||||||
</Representation>
|
</Representation>
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -154,10 +154,6 @@ bool VP8Parser::Parse(const uint8_t* data,
|
||||||
writable_codec_config()->set_bit_depth(8);
|
writable_codec_config()->set_bit_depth(8);
|
||||||
writable_codec_config()->set_chroma_subsampling(
|
writable_codec_config()->set_chroma_subsampling(
|
||||||
VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
|
VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
|
||||||
// VP8 uses YCrCb color space defined in ITU-R_BT.601.
|
|
||||||
// http://tools.ietf.org/html/rfc6386 Section 9.2.
|
|
||||||
writable_codec_config()->set_color_space(
|
|
||||||
VPCodecConfigurationRecord::COLOR_SPACE_BT_601);
|
|
||||||
|
|
||||||
VPxFrameInfo vpx_frame;
|
VPxFrameInfo vpx_frame;
|
||||||
vpx_frame.frame_size = data_size;
|
vpx_frame.frame_size = data_size;
|
||||||
|
|
|
@ -43,7 +43,7 @@ TEST(VP8ParserTest, Keyframe) {
|
||||||
VP8Parser parser;
|
VP8Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp08.02.00.08.01.01.00.00",
|
EXPECT_EQ("vp08.02.10.08.01.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP8));
|
parser.codec_config().GetCodecString(kCodecVP8));
|
||||||
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 22u, true,
|
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 22u, true,
|
||||||
320u, 240u)));
|
320u, 240u)));
|
||||||
|
|
|
@ -160,30 +160,66 @@ bool ReadSyncCode(BitReader* reader) {
|
||||||
return sync_code == VP9_SYNC_CODE;
|
return sync_code == VP9_SYNC_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VPCodecConfigurationRecord::ColorSpace GetColorSpace(uint8_t color_space) {
|
void SetColorAttributes(uint8_t bit_depth,
|
||||||
|
uint8_t color_space,
|
||||||
|
VPCodecConfigurationRecord* codec_config) {
|
||||||
switch (color_space) {
|
switch (color_space) {
|
||||||
case VPX_COLOR_SPACE_UNKNOWN:
|
case VPX_COLOR_SPACE_UNKNOWN:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_UNSPECIFIED;
|
codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_BT_601:
|
case VPX_COLOR_SPACE_BT_601:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_BT_601;
|
// Don't know if it is 525 line or 625 line.
|
||||||
|
codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE170M);
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_BT_709:
|
case VPX_COLOR_SPACE_BT_709:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_BT_709;
|
codec_config->set_color_primaries(AVCOL_PRI_BT709);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_BT709);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_BT709);
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_SMPTE_170:
|
case VPX_COLOR_SPACE_SMPTE_170:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_SMPTE_170;
|
codec_config->set_color_primaries(AVCOL_PRI_SMPTE170M);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_SMPTE170M);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE170M);
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_SMPTE_240:
|
case VPX_COLOR_SPACE_SMPTE_240:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_SMPTE_240;
|
codec_config->set_color_primaries(AVCOL_PRI_SMPTE240M);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_SMPTE240M);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE240M);
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_BT_2020:
|
case VPX_COLOR_SPACE_BT_2020:
|
||||||
|
codec_config->set_color_primaries(AVCOL_PRI_BT2020);
|
||||||
// VP9 does not specify if it is in the form of “constant luminance” or
|
// VP9 does not specify if it is in the form of “constant luminance” or
|
||||||
// “non-constant luminance”. As such, application should rely on the
|
// “non-constant luminance”. As such, application should rely on the
|
||||||
// signaling outside of VP9 bitstream. If there is no such signaling,
|
// signaling outside of VP9 bitstream. If there is no such signaling,
|
||||||
// application may assume non-constant luminance for BT.2020.
|
// application may assume non-constant luminance for BT.2020.
|
||||||
return VPCodecConfigurationRecord::
|
codec_config->set_matrix_coefficients(AVCOL_SPC_BT2020_NCL);
|
||||||
COLOR_SPACE_BT_2020_NON_CONSTANT_LUMINANCE;
|
switch (bit_depth) {
|
||||||
|
case 10:
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_10);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_12);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case VPX_COLOR_SPACE_SRGB:
|
case VPX_COLOR_SPACE_SRGB:
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_SRGB;
|
codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_RGB);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(WARNING) << "Unknown color space: " << static_cast<int>(color_space);
|
LOG(WARNING) << "Unknown color space: " << static_cast<int>(color_space);
|
||||||
return VPCodecConfigurationRecord::COLOR_SPACE_UNSPECIFIED;
|
codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
|
||||||
|
codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
|
||||||
|
codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +255,7 @@ bool ReadBitDepthAndColorSpace(BitReader* reader,
|
||||||
|
|
||||||
uint8_t color_space;
|
uint8_t color_space;
|
||||||
RCHECK(reader->ReadBits(3, &color_space));
|
RCHECK(reader->ReadBits(3, &color_space));
|
||||||
codec_config->set_color_space(GetColorSpace(color_space));
|
SetColorAttributes(bit_depth, color_space, codec_config);
|
||||||
|
|
||||||
bool yuv_full_range = false;
|
bool yuv_full_range = false;
|
||||||
auto chroma_subsampling = VPCodecConfigurationRecord::CHROMA_444;
|
auto chroma_subsampling = VPCodecConfigurationRecord::CHROMA_444;
|
||||||
|
@ -261,7 +297,8 @@ bool ReadBitDepthAndColorSpace(BitReader* reader,
|
||||||
|
|
||||||
VLOG(3) << "\n profile " << static_cast<int>(codec_config->profile())
|
VLOG(3) << "\n profile " << static_cast<int>(codec_config->profile())
|
||||||
<< "\n bit depth " << static_cast<int>(codec_config->bit_depth())
|
<< "\n bit depth " << static_cast<int>(codec_config->bit_depth())
|
||||||
<< "\n color space " << static_cast<int>(codec_config->color_space())
|
<< "\n matrix coefficients "
|
||||||
|
<< static_cast<int>(codec_config->matrix_coefficients())
|
||||||
<< "\n full_range "
|
<< "\n full_range "
|
||||||
<< static_cast<int>(codec_config->video_full_range_flag())
|
<< static_cast<int>(codec_config->video_full_range_flag())
|
||||||
<< "\n chroma subsampling "
|
<< "\n chroma subsampling "
|
||||||
|
|
|
@ -76,7 +76,7 @@ TEST(VP9ParserTest, KeyframeChroma420) {
|
||||||
VP9Parser parser;
|
VP9Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp09.00.00.08.00.01.00.00",
|
EXPECT_EQ("vp09.00.10.08.01.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP9));
|
parser.codec_config().GetCodecString(kCodecVP9));
|
||||||
EXPECT_THAT(frames,
|
EXPECT_THAT(frames,
|
||||||
ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true, 32u, 8u)));
|
ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true, 32u, 8u)));
|
||||||
|
@ -98,7 +98,7 @@ TEST(VP9ParserTest, KeyframeProfile1Chroma422) {
|
||||||
VP9Parser parser;
|
VP9Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp09.01.00.08.00.02.00.00",
|
EXPECT_EQ("vp09.01.10.08.02.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP9));
|
parser.codec_config().GetCodecString(kCodecVP9));
|
||||||
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true,
|
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true,
|
||||||
160u, 90u)));
|
160u, 90u)));
|
||||||
|
@ -120,7 +120,7 @@ TEST(VP9ParserTest, KeyframeProfile2Chroma420) {
|
||||||
VP9Parser parser;
|
VP9Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp09.02.00.10.00.01.00.00",
|
EXPECT_EQ("vp09.02.10.10.01.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP9));
|
parser.codec_config().GetCodecString(kCodecVP9));
|
||||||
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true,
|
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 18u, true,
|
||||||
160u, 90u)));
|
160u, 90u)));
|
||||||
|
@ -142,7 +142,7 @@ TEST(VP9ParserTest, KeyframeProfile3Chroma444) {
|
||||||
VP9Parser parser;
|
VP9Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp09.03.00.12.00.03.00.00",
|
EXPECT_EQ("vp09.03.10.12.03.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP9));
|
parser.codec_config().GetCodecString(kCodecVP9));
|
||||||
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 19u, true, 160u, 90u)));
|
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 19u, true, 160u, 90u)));
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ TEST(VP9ParserTest, Intra) {
|
||||||
VP9Parser parser;
|
VP9Parser parser;
|
||||||
std::vector<VPxFrameInfo> frames;
|
std::vector<VPxFrameInfo> frames;
|
||||||
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
ASSERT_TRUE(parser.Parse(kData, arraysize(kData), &frames));
|
||||||
EXPECT_EQ("vp09.00.00.08.00.01.00.00",
|
EXPECT_EQ("vp09.00.10.08.01.02.02.02.00",
|
||||||
parser.codec_config().GetCodecString(kCodecVP9));
|
parser.codec_config().GetCodecString(kCodecVP9));
|
||||||
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 19u, false,
|
EXPECT_THAT(frames, ElementsAre(EqualVPxFrame(arraysize(kData), 19u, false,
|
||||||
352u, 288u)));
|
352u, 288u)));
|
||||||
|
|
|
@ -40,18 +40,17 @@ std::string VPCodecAsString(Codec codec) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void MergeField(const std::string& name,
|
void MergeField(const std::string& name,
|
||||||
T source_value,
|
const base::Optional<T>& source_value,
|
||||||
bool source_is_set,
|
base::Optional<T>* dest_value) {
|
||||||
T* dest_value,
|
if (*dest_value) {
|
||||||
bool* dest_is_set) {
|
if (source_value && *source_value != **dest_value) {
|
||||||
if (!*dest_is_set || source_is_set) {
|
|
||||||
if (*dest_is_set && source_value != *dest_value) {
|
|
||||||
LOG(WARNING) << "VPx " << name << " is inconsistent, "
|
LOG(WARNING) << "VPx " << name << " is inconsistent, "
|
||||||
<< static_cast<uint32_t>(*dest_value) << " vs "
|
<< static_cast<int>(**dest_value) << " vs "
|
||||||
<< static_cast<uint32_t>(source_value);
|
<< static_cast<int>(*source_value);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Only set dest_value if it is not set.
|
||||||
*dest_value = source_value;
|
*dest_value = source_value;
|
||||||
*dest_is_set = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,45 +62,46 @@ VPCodecConfigurationRecord::VPCodecConfigurationRecord(
|
||||||
uint8_t profile,
|
uint8_t profile,
|
||||||
uint8_t level,
|
uint8_t level,
|
||||||
uint8_t bit_depth,
|
uint8_t bit_depth,
|
||||||
uint8_t color_space,
|
|
||||||
uint8_t chroma_subsampling,
|
uint8_t chroma_subsampling,
|
||||||
uint8_t transfer_function,
|
|
||||||
bool video_full_range_flag,
|
bool video_full_range_flag,
|
||||||
|
uint8_t color_primaries,
|
||||||
|
uint8_t transfer_characteristics,
|
||||||
|
uint8_t matrix_coefficients,
|
||||||
const std::vector<uint8_t>& codec_initialization_data)
|
const std::vector<uint8_t>& codec_initialization_data)
|
||||||
: profile_(profile),
|
: profile_(profile),
|
||||||
level_(level),
|
level_(level),
|
||||||
bit_depth_(bit_depth),
|
bit_depth_(bit_depth),
|
||||||
color_space_(color_space),
|
|
||||||
chroma_subsampling_(chroma_subsampling),
|
chroma_subsampling_(chroma_subsampling),
|
||||||
transfer_function_(transfer_function),
|
|
||||||
video_full_range_flag_(video_full_range_flag),
|
video_full_range_flag_(video_full_range_flag),
|
||||||
profile_is_set_(true),
|
color_primaries_(color_primaries),
|
||||||
level_is_set_(true),
|
transfer_characteristics_(transfer_characteristics),
|
||||||
bit_depth_is_set_(true),
|
matrix_coefficients_(matrix_coefficients),
|
||||||
color_space_is_set_(true),
|
|
||||||
chroma_subsampling_is_set_(true),
|
|
||||||
transfer_function_is_set_(true),
|
|
||||||
video_full_range_flag_is_set_(true),
|
|
||||||
codec_initialization_data_(codec_initialization_data) {}
|
codec_initialization_data_(codec_initialization_data) {}
|
||||||
|
|
||||||
VPCodecConfigurationRecord::~VPCodecConfigurationRecord(){};
|
VPCodecConfigurationRecord::~VPCodecConfigurationRecord(){};
|
||||||
|
|
||||||
|
// https://www.webmproject.org/vp9/mp4/
|
||||||
bool VPCodecConfigurationRecord::ParseMP4(const std::vector<uint8_t>& data) {
|
bool VPCodecConfigurationRecord::ParseMP4(const std::vector<uint8_t>& data) {
|
||||||
BitReader reader(data.data(), data.size());
|
BitReader reader(data.data(), data.size());
|
||||||
profile_is_set_ = true;
|
uint8_t value;
|
||||||
level_is_set_ = true;
|
RCHECK(reader.ReadBits(8, &value));
|
||||||
bit_depth_is_set_ = true;
|
profile_ = value;
|
||||||
color_space_is_set_ = true;
|
RCHECK(reader.ReadBits(8, &value));
|
||||||
chroma_subsampling_is_set_ = true;
|
level_ = value;
|
||||||
transfer_function_is_set_ = true;
|
RCHECK(reader.ReadBits(4, &value));
|
||||||
video_full_range_flag_is_set_ = true;
|
bit_depth_ = value;
|
||||||
RCHECK(reader.ReadBits(8, &profile_));
|
RCHECK(reader.ReadBits(3, &value));
|
||||||
RCHECK(reader.ReadBits(8, &level_));
|
chroma_subsampling_ = value;
|
||||||
RCHECK(reader.ReadBits(4, &bit_depth_));
|
bool bool_value;
|
||||||
RCHECK(reader.ReadBits(4, &color_space_));
|
RCHECK(reader.ReadBits(1, &bool_value));
|
||||||
RCHECK(reader.ReadBits(4, &chroma_subsampling_));
|
video_full_range_flag_ = bool_value;
|
||||||
RCHECK(reader.ReadBits(3, &transfer_function_));
|
RCHECK(reader.ReadBits(8, &value));
|
||||||
RCHECK(reader.ReadBits(1, &video_full_range_flag_));
|
color_primaries_ = value;
|
||||||
|
RCHECK(reader.ReadBits(8, &value));
|
||||||
|
transfer_characteristics_ = value;
|
||||||
|
RCHECK(reader.ReadBits(8, &value));
|
||||||
|
matrix_coefficients_ = value;
|
||||||
|
|
||||||
uint16_t codec_initialization_data_size = 0;
|
uint16_t codec_initialization_data_size = 0;
|
||||||
RCHECK(reader.ReadBits(16, &codec_initialization_data_size));
|
RCHECK(reader.ReadBits(16, &codec_initialization_data_size));
|
||||||
RCHECK(reader.bits_available() >= codec_initialization_data_size * 8u);
|
RCHECK(reader.bits_available() >= codec_initialization_data_size * 8u);
|
||||||
|
@ -121,26 +121,27 @@ bool VPCodecConfigurationRecord::ParseWebM(const std::vector<uint8_t>& data) {
|
||||||
RCHECK(reader.Read1(&id));
|
RCHECK(reader.Read1(&id));
|
||||||
RCHECK(reader.Read1(&size));
|
RCHECK(reader.Read1(&size));
|
||||||
|
|
||||||
|
uint8_t value = 0;
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case kFeatureProfile:
|
case kFeatureProfile:
|
||||||
RCHECK(size == 1);
|
RCHECK(size == 1);
|
||||||
RCHECK(reader.Read1(&profile_));
|
RCHECK(reader.Read1(&value));
|
||||||
profile_is_set_ = true;
|
profile_ = value;
|
||||||
break;
|
break;
|
||||||
case kFeatureLevel:
|
case kFeatureLevel:
|
||||||
RCHECK(size == 1);
|
RCHECK(size == 1);
|
||||||
RCHECK(reader.Read1(&level_));
|
RCHECK(reader.Read1(&value));
|
||||||
level_is_set_ = true;
|
level_ = value;
|
||||||
break;
|
break;
|
||||||
case kFeatureBitDepth:
|
case kFeatureBitDepth:
|
||||||
RCHECK(size == 1);
|
RCHECK(size == 1);
|
||||||
RCHECK(reader.Read1(&bit_depth_));
|
RCHECK(reader.Read1(&value));
|
||||||
bit_depth_is_set_ = true;
|
bit_depth_ = value;
|
||||||
break;
|
break;
|
||||||
case kFeatureChromaSubsampling:
|
case kFeatureChromaSubsampling:
|
||||||
RCHECK(size == 1);
|
RCHECK(size == 1);
|
||||||
RCHECK(reader.Read1(&chroma_subsampling_));
|
RCHECK(reader.Read1(&value));
|
||||||
chroma_subsampling_is_set_ = true;
|
chroma_subsampling_ = value;
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
LOG(WARNING) << "Skipping unknown VP9 codec feature " << id;
|
LOG(WARNING) << "Skipping unknown VP9 codec feature " << id;
|
||||||
|
@ -154,13 +155,14 @@ bool VPCodecConfigurationRecord::ParseWebM(const std::vector<uint8_t>& data) {
|
||||||
|
|
||||||
void VPCodecConfigurationRecord::WriteMP4(std::vector<uint8_t>* data) const {
|
void VPCodecConfigurationRecord::WriteMP4(std::vector<uint8_t>* data) const {
|
||||||
BufferWriter writer;
|
BufferWriter writer;
|
||||||
writer.AppendInt(profile_);
|
writer.AppendInt(profile());
|
||||||
writer.AppendInt(level_);
|
writer.AppendInt(level());
|
||||||
uint8_t bit_depth_color_space = (bit_depth_ << 4) | color_space_;
|
uint8_t bit_depth_chroma = (bit_depth() << 4) | (chroma_subsampling() << 1) |
|
||||||
writer.AppendInt(bit_depth_color_space);
|
(video_full_range_flag() ? 1 : 0);
|
||||||
uint8_t chroma = (chroma_subsampling_ << 4) | (transfer_function_ << 1) |
|
writer.AppendInt(bit_depth_chroma);
|
||||||
(video_full_range_flag_ ? 1 : 0);
|
writer.AppendInt(color_primaries());
|
||||||
writer.AppendInt(chroma);
|
writer.AppendInt(transfer_characteristics());
|
||||||
|
writer.AppendInt(matrix_coefficients());
|
||||||
uint16_t codec_initialization_data_size =
|
uint16_t codec_initialization_data_size =
|
||||||
static_cast<uint16_t>(codec_initialization_data_.size());
|
static_cast<uint16_t>(codec_initialization_data_.size());
|
||||||
writer.AppendInt(codec_initialization_data_size);
|
writer.AppendInt(codec_initialization_data_size);
|
||||||
|
@ -171,35 +173,29 @@ void VPCodecConfigurationRecord::WriteMP4(std::vector<uint8_t>* data) const {
|
||||||
void VPCodecConfigurationRecord::WriteWebM(std::vector<uint8_t>* data) const {
|
void VPCodecConfigurationRecord::WriteWebM(std::vector<uint8_t>* data) const {
|
||||||
BufferWriter writer;
|
BufferWriter writer;
|
||||||
|
|
||||||
if (profile_is_set_) {
|
if (profile_) {
|
||||||
writer.AppendInt(static_cast<uint8_t>(kFeatureProfile)); // ID = 1
|
writer.AppendInt(static_cast<uint8_t>(kFeatureProfile)); // ID = 1
|
||||||
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
||||||
writer.AppendInt(static_cast<uint8_t>(profile_));
|
writer.AppendInt(*profile_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level_is_set_ && level_ != 0) {
|
if (level_) {
|
||||||
writer.AppendInt(static_cast<uint8_t>(kFeatureLevel)); // ID = 2
|
writer.AppendInt(static_cast<uint8_t>(kFeatureLevel)); // ID = 2
|
||||||
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
||||||
writer.AppendInt(static_cast<uint8_t>(level_));
|
writer.AppendInt(*level_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bit_depth_is_set_) {
|
if (bit_depth_) {
|
||||||
writer.AppendInt(static_cast<uint8_t>(kFeatureBitDepth)); // ID = 3
|
writer.AppendInt(static_cast<uint8_t>(kFeatureBitDepth)); // ID = 3
|
||||||
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
writer.AppendInt(static_cast<uint8_t>(1)); // Length = 1
|
||||||
writer.AppendInt(static_cast<uint8_t>(bit_depth_));
|
writer.AppendInt(*bit_depth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chroma_subsampling_is_set_) {
|
if (chroma_subsampling_) {
|
||||||
// WebM doesn't differentiate whether it is vertical or collocated with luma
|
|
||||||
// for 4:2:0.
|
|
||||||
const uint8_t subsampling =
|
|
||||||
chroma_subsampling_ == CHROMA_420_COLLOCATED_WITH_LUMA
|
|
||||||
? CHROMA_420_VERTICAL
|
|
||||||
: chroma_subsampling_;
|
|
||||||
// ID = 4, Length = 1
|
// ID = 4, Length = 1
|
||||||
writer.AppendInt(static_cast<uint8_t>(kFeatureChromaSubsampling));
|
writer.AppendInt(static_cast<uint8_t>(kFeatureChromaSubsampling));
|
||||||
writer.AppendInt(static_cast<uint8_t>(1));
|
writer.AppendInt(static_cast<uint8_t>(1));
|
||||||
writer.AppendInt(subsampling);
|
writer.AppendInt(*chroma_subsampling_);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.SwapBuffer(data);
|
writer.SwapBuffer(data);
|
||||||
|
@ -207,13 +203,14 @@ void VPCodecConfigurationRecord::WriteWebM(std::vector<uint8_t>* data) const {
|
||||||
|
|
||||||
std::string VPCodecConfigurationRecord::GetCodecString(Codec codec) const {
|
std::string VPCodecConfigurationRecord::GetCodecString(Codec codec) const {
|
||||||
const std::string fields[] = {
|
const std::string fields[] = {
|
||||||
base::IntToString(profile_),
|
base::IntToString(profile()),
|
||||||
base::IntToString(level_),
|
base::IntToString(level()),
|
||||||
base::IntToString(bit_depth_),
|
base::IntToString(bit_depth()),
|
||||||
base::IntToString(color_space_),
|
base::IntToString(chroma_subsampling()),
|
||||||
base::IntToString(chroma_subsampling_),
|
base::IntToString(color_primaries()),
|
||||||
base::IntToString(transfer_function_),
|
base::IntToString(transfer_characteristics()),
|
||||||
(video_full_range_flag_ ? "01" : "00"),
|
base::IntToString(matrix_coefficients()),
|
||||||
|
(video_full_range_flag_ && *video_full_range_flag_) ? "01" : "00",
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string codec_string = VPCodecAsString(codec);
|
std::string codec_string = VPCodecAsString(codec);
|
||||||
|
@ -228,23 +225,18 @@ std::string VPCodecConfigurationRecord::GetCodecString(Codec codec) const {
|
||||||
|
|
||||||
void VPCodecConfigurationRecord::MergeFrom(
|
void VPCodecConfigurationRecord::MergeFrom(
|
||||||
const VPCodecConfigurationRecord& other) {
|
const VPCodecConfigurationRecord& other) {
|
||||||
MergeField("profile", other.profile_, other.profile_is_set_, &profile_,
|
MergeField("profile", other.profile_, &profile_);
|
||||||
&profile_is_set_);
|
MergeField("level", other.level_, &level_);
|
||||||
MergeField("level", other.level_, other.level_is_set_, &level_,
|
MergeField("bit depth", other.bit_depth_, &bit_depth_);
|
||||||
&level_is_set_);
|
|
||||||
MergeField("bit depth", other.bit_depth_, other.bit_depth_is_set_,
|
|
||||||
&bit_depth_, &bit_depth_is_set_);
|
|
||||||
MergeField("color space", other.color_space_, other.color_space_is_set_,
|
|
||||||
&color_space_, &color_space_is_set_);
|
|
||||||
MergeField("chroma subsampling", other.chroma_subsampling_,
|
MergeField("chroma subsampling", other.chroma_subsampling_,
|
||||||
other.chroma_subsampling_is_set_, &chroma_subsampling_,
|
&chroma_subsampling_);
|
||||||
&chroma_subsampling_is_set_);
|
|
||||||
MergeField("transfer function", other.transfer_function_,
|
|
||||||
other.transfer_function_is_set_, &transfer_function_,
|
|
||||||
&transfer_function_is_set_);
|
|
||||||
MergeField("video full range flag", other.video_full_range_flag_,
|
MergeField("video full range flag", other.video_full_range_flag_,
|
||||||
other.video_full_range_flag_is_set_, &video_full_range_flag_,
|
&video_full_range_flag_);
|
||||||
&video_full_range_flag_is_set_);
|
MergeField("color primaries", other.color_primaries_, &color_primaries_);
|
||||||
|
MergeField("transfer characteristics", other.transfer_characteristics_,
|
||||||
|
&transfer_characteristics_);
|
||||||
|
MergeField("matrix coefficients", other.matrix_coefficients_,
|
||||||
|
&matrix_coefficients_);
|
||||||
|
|
||||||
if (codec_initialization_data_.empty() ||
|
if (codec_initialization_data_.empty() ||
|
||||||
!other.codec_initialization_data_.empty()) {
|
!other.codec_initialization_data_.empty()) {
|
||||||
|
|
|
@ -12,25 +12,118 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "packager/base/macros.h"
|
#include "packager/base/macros.h"
|
||||||
|
#include "packager/base/optional.h"
|
||||||
#include "packager/media/base/video_stream_info.h"
|
#include "packager/media/base/video_stream_info.h"
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
/// The below enums are from ffmpeg/libavutil/pixfmt.h.
|
||||||
|
/// Chromaticity coordinates of the source primaries.
|
||||||
|
enum AVColorPrimaries {
|
||||||
|
AVCOL_PRI_RESERVED0 = 0,
|
||||||
|
/// Also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
|
||||||
|
AVCOL_PRI_BT709 = 1,
|
||||||
|
AVCOL_PRI_UNSPECIFIED = 2,
|
||||||
|
AVCOL_PRI_RESERVED = 3,
|
||||||
|
/// Also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
|
||||||
|
AVCOL_PRI_BT470M = 4,
|
||||||
|
/// Also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
|
||||||
|
AVCOL_PRI_BT470BG = 5,
|
||||||
|
/// Also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
|
||||||
|
AVCOL_PRI_SMPTE170M = 6,
|
||||||
|
/// Functionally identical to above
|
||||||
|
AVCOL_PRI_SMPTE240M = 7,
|
||||||
|
/// Colour filters using Illuminant C
|
||||||
|
AVCOL_PRI_FILM = 8,
|
||||||
|
/// ITU-R BT2020
|
||||||
|
AVCOL_PRI_BT2020 = 9,
|
||||||
|
/// SMPTE ST 428-1 (CIE 1931 XYZ)
|
||||||
|
AVCOL_PRI_SMPTE428 = 10,
|
||||||
|
AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,
|
||||||
|
/// SMPTE ST 431-2 (2011)
|
||||||
|
AVCOL_PRI_SMPTE431 = 11,
|
||||||
|
/// SMPTE ST 432-1 D65 (2010)
|
||||||
|
AVCOL_PRI_SMPTE432 = 12,
|
||||||
|
///< Not part of ABI
|
||||||
|
AVCOL_PRI_NB
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Color Transfer Characteristic.
|
||||||
|
enum AVColorTransferCharacteristic {
|
||||||
|
AVCOL_TRC_RESERVED0 = 0,
|
||||||
|
/// Also ITU-R BT1361
|
||||||
|
AVCOL_TRC_BT709 = 1,
|
||||||
|
AVCOL_TRC_UNSPECIFIED = 2,
|
||||||
|
AVCOL_TRC_RESERVED = 3,
|
||||||
|
/// Also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
|
||||||
|
AVCOL_TRC_GAMMA22 = 4,
|
||||||
|
/// Also ITU-R BT470BG
|
||||||
|
AVCOL_TRC_GAMMA28 = 5,
|
||||||
|
/// Also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700
|
||||||
|
/// NTSC
|
||||||
|
AVCOL_TRC_SMPTE170M = 6,
|
||||||
|
AVCOL_TRC_SMPTE240M = 7,
|
||||||
|
/// "Linear transfer characteristics"
|
||||||
|
AVCOL_TRC_LINEAR = 8,
|
||||||
|
/// "Logarithmic transfer characteristic (100:1 range)"
|
||||||
|
AVCOL_TRC_LOG = 9,
|
||||||
|
/// "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
|
||||||
|
AVCOL_TRC_LOG_SQRT = 10,
|
||||||
|
/// IEC 61966-2-4
|
||||||
|
AVCOL_TRC_IEC61966_2_4 = 11,
|
||||||
|
/// ITU-R BT1361 Extended Colour Gamut
|
||||||
|
AVCOL_TRC_BT1361_ECG = 12,
|
||||||
|
/// IEC 61966-2-1 (sRGB or sYCC)
|
||||||
|
AVCOL_TRC_IEC61966_2_1 = 13,
|
||||||
|
/// ITU-R BT2020 for 10-bit system
|
||||||
|
AVCOL_TRC_BT2020_10 = 14,
|
||||||
|
/// ITU-R BT2020 for 12-bit system
|
||||||
|
AVCOL_TRC_BT2020_12 = 15,
|
||||||
|
/// SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
|
||||||
|
AVCOL_TRC_SMPTE2084 = 16,
|
||||||
|
AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084,
|
||||||
|
/// SMPTE ST 428-1
|
||||||
|
AVCOL_TRC_SMPTE428 = 17,
|
||||||
|
AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
|
||||||
|
/// ARIB STD-B67, known as "Hybrid log-gamma"
|
||||||
|
AVCOL_TRC_ARIB_STD_B67 = 18,
|
||||||
|
/// Not part of ABI
|
||||||
|
AVCOL_TRC_NB
|
||||||
|
};
|
||||||
|
|
||||||
|
/// YUV colorspace type (a.c.a matrix coefficients in 23001-8:2016).
|
||||||
|
enum AVColorSpace {
|
||||||
|
/// Order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
|
||||||
|
AVCOL_SPC_RGB = 0,
|
||||||
|
/// Also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
|
||||||
|
AVCOL_SPC_BT709 = 1,
|
||||||
|
AVCOL_SPC_UNSPECIFIED = 2,
|
||||||
|
AVCOL_SPC_RESERVED = 3,
|
||||||
|
/// FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
|
||||||
|
AVCOL_SPC_FCC = 4,
|
||||||
|
/// Also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM /
|
||||||
|
/// IEC 61966-2-4 xvYCC601
|
||||||
|
AVCOL_SPC_BT470BG = 5,
|
||||||
|
/// Also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
|
||||||
|
AVCOL_SPC_SMPTE170M = 6,
|
||||||
|
/// Functionally identical to above
|
||||||
|
AVCOL_SPC_SMPTE240M = 7,
|
||||||
|
/// Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
|
||||||
|
AVCOL_SPC_YCOCG = 8,
|
||||||
|
/// ITU-R BT2020 non-constant luminance system
|
||||||
|
AVCOL_SPC_BT2020_NCL = 9,
|
||||||
|
/// ITU-R BT2020 constant luminance system
|
||||||
|
AVCOL_SPC_BT2020_CL = 10,
|
||||||
|
/// SMPTE 2085, Y'D'zD'x
|
||||||
|
AVCOL_SPC_SMPTE2085 = 11,
|
||||||
|
/// Not part of ABI
|
||||||
|
AVCOL_SPC_NB
|
||||||
|
};
|
||||||
|
|
||||||
/// Class for parsing or writing VP codec configuration record.
|
/// Class for parsing or writing VP codec configuration record.
|
||||||
class VPCodecConfigurationRecord {
|
class VPCodecConfigurationRecord {
|
||||||
public:
|
public:
|
||||||
enum ColorSpace {
|
|
||||||
COLOR_SPACE_UNSPECIFIED = 0,
|
|
||||||
COLOR_SPACE_BT_601 = 1,
|
|
||||||
COLOR_SPACE_BT_709 = 2,
|
|
||||||
COLOR_SPACE_SMPTE_170 = 3,
|
|
||||||
COLOR_SPACE_SMPTE_240 = 4,
|
|
||||||
COLOR_SPACE_BT_2020_NON_CONSTANT_LUMINANCE = 5,
|
|
||||||
COLOR_SPACE_BT_2020_CONSTANT_LUMINANCE = 6,
|
|
||||||
COLOR_SPACE_SRGB = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ChromaSubsampling {
|
enum ChromaSubsampling {
|
||||||
CHROMA_420_VERTICAL = 0,
|
CHROMA_420_VERTICAL = 0,
|
||||||
CHROMA_420_COLLOCATED_WITH_LUMA = 1,
|
CHROMA_420_COLLOCATED_WITH_LUMA = 1,
|
||||||
|
@ -44,10 +137,11 @@ class VPCodecConfigurationRecord {
|
||||||
uint8_t profile,
|
uint8_t profile,
|
||||||
uint8_t level,
|
uint8_t level,
|
||||||
uint8_t bit_depth,
|
uint8_t bit_depth,
|
||||||
uint8_t color_space,
|
|
||||||
uint8_t chroma_subsampling,
|
uint8_t chroma_subsampling,
|
||||||
uint8_t transfer_function,
|
|
||||||
bool video_full_range_flag,
|
bool video_full_range_flag,
|
||||||
|
uint8_t color_primaries,
|
||||||
|
uint8_t transfer_characteristics,
|
||||||
|
uint8_t matrix_coefficients,
|
||||||
const std::vector<uint8_t>& codec_initialization_data);
|
const std::vector<uint8_t>& codec_initialization_data);
|
||||||
~VPCodecConfigurationRecord();
|
~VPCodecConfigurationRecord();
|
||||||
|
|
||||||
|
@ -74,57 +168,53 @@ class VPCodecConfigurationRecord {
|
||||||
// both |*this| and |other|, the values in |other| take precedence.
|
// both |*this| and |other|, the values in |other| take precedence.
|
||||||
void MergeFrom(const VPCodecConfigurationRecord& other);
|
void MergeFrom(const VPCodecConfigurationRecord& other);
|
||||||
|
|
||||||
void set_profile(uint8_t profile) {
|
void set_profile(uint8_t profile) { profile_ = profile; }
|
||||||
profile_ = profile;
|
void set_level(uint8_t level) { level_ = level; }
|
||||||
profile_is_set_ = true;
|
void set_bit_depth(uint8_t bit_depth) { bit_depth_ = bit_depth; }
|
||||||
}
|
|
||||||
void set_level(uint8_t level) {
|
|
||||||
level_ = level;
|
|
||||||
level_is_set_ = true;
|
|
||||||
}
|
|
||||||
void set_bit_depth(uint8_t bit_depth) {
|
|
||||||
bit_depth_ = bit_depth;
|
|
||||||
bit_depth_is_set_ = true;
|
|
||||||
}
|
|
||||||
void set_color_space(uint8_t color_space) {
|
|
||||||
color_space_ = color_space;
|
|
||||||
color_space_is_set_ = true;
|
|
||||||
}
|
|
||||||
void set_chroma_subsampling(uint8_t chroma_subsampling) {
|
void set_chroma_subsampling(uint8_t chroma_subsampling) {
|
||||||
chroma_subsampling_ = chroma_subsampling;
|
chroma_subsampling_ = chroma_subsampling;
|
||||||
chroma_subsampling_is_set_ = true;
|
|
||||||
}
|
|
||||||
void set_transfer_function(uint8_t transfer_function) {
|
|
||||||
transfer_function_ = transfer_function;
|
|
||||||
transfer_function_is_set_ = true;
|
|
||||||
}
|
}
|
||||||
void set_video_full_range_flag(bool video_full_range_flag) {
|
void set_video_full_range_flag(bool video_full_range_flag) {
|
||||||
video_full_range_flag_ = video_full_range_flag;
|
video_full_range_flag_ = video_full_range_flag;
|
||||||
}
|
}
|
||||||
|
void set_color_primaries(uint8_t color_primaries) {
|
||||||
|
color_primaries_ = color_primaries;
|
||||||
|
}
|
||||||
|
void set_transfer_characteristics(uint8_t transfer_characteristics) {
|
||||||
|
transfer_characteristics_ = transfer_characteristics;
|
||||||
|
}
|
||||||
|
void set_matrix_coefficients(uint8_t matrix_coefficients) {
|
||||||
|
matrix_coefficients_ = matrix_coefficients;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t profile() const { return profile_; }
|
uint8_t profile() const { return profile_.value_or(0); }
|
||||||
uint8_t level() const { return level_; }
|
uint8_t level() const { return level_.value_or(10); }
|
||||||
uint8_t bit_depth() const { return bit_depth_; }
|
uint8_t bit_depth() const { return bit_depth_.value_or(8); }
|
||||||
uint8_t color_space() const { return color_space_; }
|
uint8_t chroma_subsampling() const {
|
||||||
uint8_t chroma_subsampling() const { return chroma_subsampling_; }
|
return chroma_subsampling_.value_or(CHROMA_420_COLLOCATED_WITH_LUMA);
|
||||||
uint8_t transfer_function() const { return transfer_function_; }
|
}
|
||||||
bool video_full_range_flag() const { return video_full_range_flag_; }
|
bool video_full_range_flag() const {
|
||||||
|
return video_full_range_flag_.value_or(false);
|
||||||
|
}
|
||||||
|
uint8_t color_primaries() const {
|
||||||
|
return color_primaries_.value_or(AVCOL_PRI_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
uint8_t transfer_characteristics() const {
|
||||||
|
return transfer_characteristics_.value_or(AVCOL_TRC_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
uint8_t matrix_coefficients() const {
|
||||||
|
return matrix_coefficients_.value_or(AVCOL_SPC_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t profile_ = 0;
|
base::Optional<uint8_t> profile_;
|
||||||
uint8_t level_ = 0;
|
base::Optional<uint8_t> level_;
|
||||||
uint8_t bit_depth_ = 0;
|
base::Optional<uint8_t> bit_depth_;
|
||||||
uint8_t color_space_ = 0;
|
base::Optional<uint8_t> chroma_subsampling_;
|
||||||
uint8_t chroma_subsampling_ = 0;
|
base::Optional<bool> video_full_range_flag_;
|
||||||
uint8_t transfer_function_ = 0;
|
base::Optional<uint8_t> color_primaries_;
|
||||||
bool video_full_range_flag_ = false;
|
base::Optional<uint8_t> transfer_characteristics_;
|
||||||
bool profile_is_set_ = false;
|
base::Optional<uint8_t> matrix_coefficients_;
|
||||||
bool level_is_set_ = false;
|
|
||||||
bool bit_depth_is_set_ = false;
|
|
||||||
bool color_space_is_set_ = false;
|
|
||||||
bool chroma_subsampling_is_set_ = false;
|
|
||||||
bool transfer_function_is_set_ = false;
|
|
||||||
bool video_full_range_flag_is_set_ = false;
|
|
||||||
std::vector<uint8_t> codec_initialization_data_;
|
std::vector<uint8_t> codec_initialization_data_;
|
||||||
|
|
||||||
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
// Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler
|
||||||
|
|
|
@ -13,49 +13,49 @@ namespace media {
|
||||||
|
|
||||||
TEST(VPCodecConfigurationRecordTest, Parse) {
|
TEST(VPCodecConfigurationRecordTest, Parse) {
|
||||||
const uint8_t kVpCodecConfigurationData[] = {
|
const uint8_t kVpCodecConfigurationData[] = {
|
||||||
0x01, 0x00, 0xA2, 0x14, 0x00, 0x01, 0x00,
|
0x01, 0x14, 0xA2, 0x02, 0x03, 0x04, 0x00, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
VPCodecConfigurationRecord vp_config;
|
VPCodecConfigurationRecord vp_config;
|
||||||
ASSERT_TRUE(vp_config.ParseMP4(std::vector<uint8_t>(
|
ASSERT_TRUE(vp_config.ParseMP4(
|
||||||
kVpCodecConfigurationData,
|
std::vector<uint8_t>(std::begin(kVpCodecConfigurationData),
|
||||||
kVpCodecConfigurationData + arraysize(kVpCodecConfigurationData))));
|
std::end(kVpCodecConfigurationData))));
|
||||||
|
|
||||||
EXPECT_EQ(1u, vp_config.profile());
|
EXPECT_EQ(1u, vp_config.profile());
|
||||||
EXPECT_EQ(0u, vp_config.level());
|
EXPECT_EQ(20u, vp_config.level());
|
||||||
EXPECT_EQ(10u, vp_config.bit_depth());
|
EXPECT_EQ(10u, vp_config.bit_depth());
|
||||||
EXPECT_EQ(2u, vp_config.color_space());
|
|
||||||
EXPECT_EQ(1u, vp_config.chroma_subsampling());
|
EXPECT_EQ(1u, vp_config.chroma_subsampling());
|
||||||
EXPECT_EQ(2u, vp_config.transfer_function());
|
|
||||||
EXPECT_FALSE(vp_config.video_full_range_flag());
|
EXPECT_FALSE(vp_config.video_full_range_flag());
|
||||||
|
EXPECT_EQ(2u, vp_config.color_primaries());
|
||||||
|
EXPECT_EQ(3u, vp_config.transfer_characteristics());
|
||||||
|
EXPECT_EQ(4u, vp_config.matrix_coefficients());
|
||||||
|
|
||||||
EXPECT_EQ("vp09.01.00.10.02.01.02.00", vp_config.GetCodecString(kCodecVP9));
|
EXPECT_EQ("vp09.01.20.10.01.02.03.04.00",
|
||||||
|
vp_config.GetCodecString(kCodecVP9));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VPCodecConfigurationRecordTest, ParseWithInsufficientData) {
|
TEST(VPCodecConfigurationRecordTest, ParseWithInsufficientData) {
|
||||||
const uint8_t kVpCodecConfigurationData[] = {
|
const uint8_t kVpCodecConfigurationData[] = {
|
||||||
0x01, 0x00, 0xA2, 0x14,
|
0x01, 0x14, 0xA2, 0x02,
|
||||||
};
|
};
|
||||||
|
|
||||||
VPCodecConfigurationRecord vp_config;
|
VPCodecConfigurationRecord vp_config;
|
||||||
ASSERT_FALSE(vp_config.ParseMP4(std::vector<uint8_t>(
|
ASSERT_FALSE(vp_config.ParseMP4(
|
||||||
kVpCodecConfigurationData,
|
std::vector<uint8_t>(std::begin(kVpCodecConfigurationData),
|
||||||
kVpCodecConfigurationData + arraysize(kVpCodecConfigurationData))));
|
std::end(kVpCodecConfigurationData))));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VPCodecConfigurationRecordTest, WriteMP4) {
|
TEST(VPCodecConfigurationRecordTest, WriteMP4) {
|
||||||
const uint8_t kExpectedVpCodecConfigurationData[] = {
|
const uint8_t kExpectedVpCodecConfigurationData[] = {
|
||||||
0x02, 0x01, 0x80, 0x21, 0x00, 0x00,
|
0x02, 0x01, 0x85, 0x03, 0x04, 0x05, 0x00, 0x00,
|
||||||
};
|
};
|
||||||
VPCodecConfigurationRecord vp_config(0x02, 0x01, 0x08, 0x00, 0x02, 0x00, true,
|
VPCodecConfigurationRecord vp_config(0x02, 0x01, 0x08, 0x02, true, 0x03, 0x04,
|
||||||
std::vector<uint8_t>());
|
0x05, std::vector<uint8_t>());
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
vp_config.WriteMP4(&data);
|
vp_config.WriteMP4(&data);
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(std::vector<uint8_t>(std::begin(kExpectedVpCodecConfigurationData),
|
||||||
std::vector<uint8_t>(kExpectedVpCodecConfigurationData,
|
std::end(kExpectedVpCodecConfigurationData)),
|
||||||
kExpectedVpCodecConfigurationData +
|
|
||||||
arraysize(kExpectedVpCodecConfigurationData)),
|
|
||||||
data);
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,17 +64,15 @@ TEST(VPCodecConfigurationRecordTest, WriteWebM) {
|
||||||
0x01, 0x01, 0x02,
|
0x01, 0x01, 0x02,
|
||||||
0x02, 0x01, 0x01,
|
0x02, 0x01, 0x01,
|
||||||
0x03, 0x01, 0x08,
|
0x03, 0x01, 0x08,
|
||||||
0x04, 0x01, 0x03
|
0x04, 0x01, 0x02,
|
||||||
};
|
};
|
||||||
VPCodecConfigurationRecord vp_config(0x02, 0x01, 0x08, 0x00, 0x03, 0x00, true,
|
VPCodecConfigurationRecord vp_config(0x02, 0x01, 0x08, 0x02, true, 0x03, 0x04,
|
||||||
std::vector<uint8_t>());
|
0x05, std::vector<uint8_t>());
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
vp_config.WriteWebM(&data);
|
vp_config.WriteWebM(&data);
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(std::vector<uint8_t>(std::begin(kExpectedVpCodecConfigurationData),
|
||||||
std::vector<uint8_t>(kExpectedVpCodecConfigurationData,
|
std::end(kExpectedVpCodecConfigurationData)),
|
||||||
kExpectedVpCodecConfigurationData +
|
|
||||||
arraysize(kExpectedVpCodecConfigurationData)),
|
|
||||||
data);
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1446,9 +1446,12 @@ bool CodecConfiguration::ReadWriteInternal(BoxBuffer* buffer) {
|
||||||
// VPCodecConfiguration box inherits from FullBox instead of Box. The extra 4
|
// VPCodecConfiguration box inherits from FullBox instead of Box. The extra 4
|
||||||
// bytes are handled here.
|
// bytes are handled here.
|
||||||
if (box_type == FOURCC_vpcC) {
|
if (box_type == FOURCC_vpcC) {
|
||||||
uint32_t version_flags = 0;
|
// Only version 1 box is supported.
|
||||||
|
uint8_t vpcc_version = 1;
|
||||||
|
uint32_t version_flags = vpcc_version << 24;
|
||||||
RCHECK(buffer->ReadWriteUInt32(&version_flags));
|
RCHECK(buffer->ReadWriteUInt32(&version_flags));
|
||||||
RCHECK(version_flags == 0);
|
vpcc_version = version_flags >> 24;
|
||||||
|
RCHECK(vpcc_version == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->Reading()) {
|
if (buffer->Reading()) {
|
||||||
|
|
|
@ -821,7 +821,7 @@ TEST_F(WebMClusterParserTest, ParseVP8) {
|
||||||
ASSERT_EQ(2u, streams_from_init_event_.size());
|
ASSERT_EQ(2u, streams_from_init_event_.size());
|
||||||
EXPECT_EQ(kStreamAudio, streams_from_init_event_[0]->stream_type());
|
EXPECT_EQ(kStreamAudio, streams_from_init_event_[0]->stream_type());
|
||||||
EXPECT_EQ(kStreamVideo, streams_from_init_event_[1]->stream_type());
|
EXPECT_EQ(kStreamVideo, streams_from_init_event_[1]->stream_type());
|
||||||
EXPECT_EQ("vp08.01.00.08.01.01.00.00",
|
EXPECT_EQ("vp08.01.10.08.01.02.02.02.00",
|
||||||
streams_from_init_event_[1]->codec_string());
|
streams_from_init_event_[1]->codec_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ TEST_F(WebMClusterParserTest, ParseVP9) {
|
||||||
ASSERT_EQ(2u, streams_from_init_event_.size());
|
ASSERT_EQ(2u, streams_from_init_event_.size());
|
||||||
EXPECT_EQ(kStreamAudio, streams_from_init_event_[0]->stream_type());
|
EXPECT_EQ(kStreamAudio, streams_from_init_event_[0]->stream_type());
|
||||||
EXPECT_EQ(kStreamVideo, streams_from_init_event_[1]->stream_type());
|
EXPECT_EQ(kStreamVideo, streams_from_init_event_[1]->stream_type());
|
||||||
EXPECT_EQ("vp09.03.00.12.00.03.00.00",
|
EXPECT_EQ("vp09.03.10.12.03.02.02.02.00",
|
||||||
streams_from_init_event_[1]->codec_string());
|
streams_from_init_event_[1]->codec_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue