1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/formats/webm/webm_video_client.h"
6 
7 #include "media/base/media_util.h"
8 #include "media/base/mock_media_log.h"
9 #include "media/base/video_decoder_config.h"
10 #include "media/formats/webm/webm_constants.h"
11 
12 namespace media {
13 
14 namespace {
15 const gfx::Size kCodedSize(321, 243);
16 }
17 
18 static const struct CodecTestParams {
19   VideoCodecProfile profile;
20   const std::vector<uint8_t> codec_private;
21 } kCodecTestParams[] = {
22     {VP9PROFILE_PROFILE0, {}},
23     {VP9PROFILE_PROFILE2,
24      // Valid VP9 Profile 2 example, extracted out of a sample file at
25      // https://www.webmproject.org/vp9/levels/#test-bitstreams
26      {0x01, 0x01, 0x02, 0x02, 0x01, 0x0a, 0x3, 0x1, 0xa, 0x4, 0x1, 0x1}},
27     // Invalid VP9 CodecPrivate: too short.
28     {VP9PROFILE_PROFILE0, {0x01, 0x01}},
29     // Invalid VP9 CodecPrivate: wrong field id.
30     {VP9PROFILE_PROFILE0, {0x77, 0x01, 0x02}},
31     // Invalid VP9 CodecPrivate: wrong field length.
32     {VP9PROFILE_PROFILE0, {0x01, 0x75, 0x02}},
33     // Invalid VP9 CodecPrivate: wrong Profile (can't be > 3).
34     {VP9PROFILE_PROFILE0, {0x01, 0x01, 0x34}}};
35 
36 class WebMVideoClientTest : public testing::TestWithParam<CodecTestParams> {
37  public:
WebMVideoClientTest()38   WebMVideoClientTest() : webm_video_client_(&media_log_) {
39     // Simulate configuring width and height in the |webm_video_client_|.
40     webm_video_client_.OnUInt(kWebMIdPixelWidth, kCodedSize.width());
41     webm_video_client_.OnUInt(kWebMIdPixelHeight, kCodedSize.height());
42   }
43 
OnListStart(int id)44   WebMParserClient* OnListStart(int id) {
45     return webm_video_client_.OnListStart(id);
46   }
47 
OnListEnd(int id)48   void OnListEnd(int id) { webm_video_client_.OnListEnd(id); }
49 
50   testing::StrictMock<MockMediaLog> media_log_;
51   WebMVideoClient webm_video_client_;
52 
53   DISALLOW_COPY_AND_ASSIGN(WebMVideoClientTest);
54 };
55 
TEST_P(WebMVideoClientTest,AutodetectVp9Profile2NoDetection)56 TEST_P(WebMVideoClientTest, AutodetectVp9Profile2NoDetection) {
57   const bool has_valid_codec_private = GetParam().codec_private.size() > 3;
58 
59   auto* parser = OnListStart(kWebMIdColour);
60   // Set 8bit and SDR fields.
61   parser->OnUInt(kWebMIdBitsPerChannel, 8);
62   parser->OnUInt(kWebMIdTransferCharacteristics,
63                  static_cast<int64_t>(VideoColorSpace::TransferID::BT709));
64   OnListEnd(kWebMIdColour);
65 
66   VideoDecoderConfig config;
67   EXPECT_TRUE(webm_video_client_.InitializeConfig(
68       "V_VP9", GetParam().codec_private, EncryptionScheme(), &config));
69 
70   if (!has_valid_codec_private)
71     EXPECT_EQ(config.profile(), VP9PROFILE_PROFILE0);
72   else
73     EXPECT_EQ(config.profile(), GetParam().profile);
74 }
75 
TEST_P(WebMVideoClientTest,AutodetectVp9Profile2BitsPerChannel)76 TEST_P(WebMVideoClientTest, AutodetectVp9Profile2BitsPerChannel) {
77   const bool has_valid_codec_private = GetParam().codec_private.size() > 3;
78 
79   auto* parser = OnListStart(kWebMIdColour);
80   parser->OnUInt(kWebMIdBitsPerChannel, 10);
81   OnListEnd(kWebMIdColour);
82 
83   VideoDecoderConfig config;
84   EXPECT_TRUE(webm_video_client_.InitializeConfig(
85       "V_VP9", GetParam().codec_private, EncryptionScheme(), &config));
86 
87   if (!has_valid_codec_private)
88     EXPECT_EQ(config.profile(), VP9PROFILE_PROFILE2);
89   else
90     EXPECT_EQ(config.profile(), GetParam().profile);
91 }
92 
TEST_P(WebMVideoClientTest,AutodetectVp9Profile2HDRMetaData)93 TEST_P(WebMVideoClientTest, AutodetectVp9Profile2HDRMetaData) {
94   const bool has_valid_codec_private = GetParam().codec_private.size() > 3;
95 
96   auto* color_parser = OnListStart(kWebMIdColour);
97   auto* metadata_parser = color_parser->OnListStart(kWebMIdMasteringMetadata);
98   metadata_parser->OnFloat(kWebMIdPrimaryRChromaticityX, 1.0);
99   color_parser->OnListEnd(kWebMIdMasteringMetadata);
100   OnListEnd(kWebMIdColour);
101 
102   VideoDecoderConfig config;
103   EXPECT_TRUE(webm_video_client_.InitializeConfig(
104       "V_VP9", GetParam().codec_private, EncryptionScheme(), &config));
105 
106   if (!has_valid_codec_private)
107     EXPECT_EQ(config.profile(), VP9PROFILE_PROFILE2);
108   else
109     EXPECT_EQ(config.profile(), GetParam().profile);
110 }
111 
TEST_P(WebMVideoClientTest,AutodetectVp9Profile2HDRColorSpace)112 TEST_P(WebMVideoClientTest, AutodetectVp9Profile2HDRColorSpace) {
113   const bool has_valid_codec_private = GetParam().codec_private.size() > 3;
114 
115   auto* parser = OnListStart(kWebMIdColour);
116   parser->OnUInt(
117       kWebMIdTransferCharacteristics,
118       static_cast<int64_t>(VideoColorSpace::TransferID::SMPTEST2084));
119   OnListEnd(kWebMIdColour);
120 
121   VideoDecoderConfig config;
122   EXPECT_TRUE(webm_video_client_.InitializeConfig(
123       "V_VP9", GetParam().codec_private, EncryptionScheme(), &config));
124 
125   if (!has_valid_codec_private)
126     EXPECT_EQ(config.profile(), VP9PROFILE_PROFILE2);
127   else
128     EXPECT_EQ(config.profile(), GetParam().profile);
129 }
130 
TEST_P(WebMVideoClientTest,InitializeConfigVP9Profiles)131 TEST_P(WebMVideoClientTest, InitializeConfigVP9Profiles) {
132   const std::string kCodecId = "V_VP9";
133   const VideoCodecProfile profile = GetParam().profile;
134   const std::vector<uint8_t> codec_private = GetParam().codec_private;
135 
136   VideoDecoderConfig config;
137   EXPECT_TRUE(webm_video_client_.InitializeConfig(kCodecId, codec_private,
138                                                   EncryptionScheme(), &config));
139 
140   VideoDecoderConfig expected_config(
141       kCodecVP9, profile, VideoDecoderConfig::AlphaMode::kIsOpaque,
142       VideoColorSpace::REC709(), kNoTransformation, kCodedSize,
143       gfx::Rect(kCodedSize), kCodedSize, codec_private,
144       EncryptionScheme::kUnencrypted);
145 
146   EXPECT_TRUE(config.Matches(expected_config))
147       << "Config (" << config.AsHumanReadableString()
148       << ") does not match expected ("
149       << expected_config.AsHumanReadableString() << ")";
150 }
151 
152 INSTANTIATE_TEST_SUITE_P(All,
153                          WebMVideoClientTest,
154                          ::testing::ValuesIn(kCodecTestParams));
155 
156 }  // namespace media
157