Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: media/base/video_codecs.cc

Issue 2723833002: WebM support for new multipart VP9 string. (Closed)
Patch Set: Put parsing behind a flag (--enable-hdr-output OR --enable-new-vp9-codec-string) Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/base/video_codecs.h" 5 #include "media/base/video_codecs.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 return "dolby vision profile 4"; 87 return "dolby vision profile 4";
88 case DOLBYVISION_PROFILE5: 88 case DOLBYVISION_PROFILE5:
89 return "dolby vision profile 5"; 89 return "dolby vision profile 5";
90 case DOLBYVISION_PROFILE7: 90 case DOLBYVISION_PROFILE7:
91 return "dolby vision profile 7"; 91 return "dolby vision profile 7";
92 } 92 }
93 NOTREACHED(); 93 NOTREACHED();
94 return ""; 94 return "";
95 } 95 }
96 96
97 bool ParseVp9Eotf(const int value, gfx::ColorSpace::TransferID* eotf) {
98 switch (value) {
99 case 1:
100 *eotf = gfx::ColorSpace::TransferID::BT709;
101 break;
102 case 2:
103 // "2" is interpreted as "Unspecified"
104 *eotf = gfx::ColorSpace::TransferID::INVALID;
105 break;
106 case 4:
107 *eotf = gfx::ColorSpace::TransferID::GAMMA22;
108 break;
109 case 5:
110 *eotf = gfx::ColorSpace::TransferID::GAMMA28;
111 break;
112 case 6:
113 *eotf = gfx::ColorSpace::TransferID::SMPTE170M;
114 break;
115 case 7:
116 *eotf = gfx::ColorSpace::TransferID::SMPTE240M;
117 break;
118 case 8:
119 *eotf = gfx::ColorSpace::TransferID::LINEAR;
120 break;
121 case 9:
122 *eotf = gfx::ColorSpace::TransferID::LOG;
123 break;
124 case 10:
125 *eotf = gfx::ColorSpace::TransferID::LOG_SQRT;
126 break;
127 case 11:
128 *eotf = gfx::ColorSpace::TransferID::IEC61966_2_4;
129 break;
130 case 12:
131 *eotf = gfx::ColorSpace::TransferID::BT1361_ECG;
132 break;
133 case 13:
134 *eotf = gfx::ColorSpace::TransferID::IEC61966_2_1;
135 break;
136 case 14:
137 *eotf = gfx::ColorSpace::TransferID::BT2020_10;
138 break;
139 case 15:
140 *eotf = gfx::ColorSpace::TransferID::BT2020_12;
141 break;
142 case 16:
143 *eotf = gfx::ColorSpace::TransferID::SMPTEST2084;
144 break;
145 case 17:
146 *eotf = gfx::ColorSpace::TransferID::SMPTEST428_1;
147 break;
148 default:
149 // Includes reserved values of 0, 3, 18 - 255.
150 *eotf = gfx::ColorSpace::TransferID::INVALID;
151 return false;
152 }
153
154 return true;
155 }
156
97 bool ParseNewStyleVp9CodecID(const std::string& codec_id, 157 bool ParseNewStyleVp9CodecID(const std::string& codec_id,
98 VideoCodecProfile* profile, 158 VideoCodecProfile* profile,
99 uint8_t* level_idc) { 159 uint8_t* level_idc,
160 gfx::ColorSpace::TransferID* eotf) {
161 // Initialize optional fields to their defaults.
162 *eotf = gfx::ColorSpace::TransferID::BT709;
163
100 std::vector<std::string> fields = base::SplitString( 164 std::vector<std::string> fields = base::SplitString(
101 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); 165 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
102 166
103 // TODO(kqyang): The spec specifies 8 fields. We do not allow missing or extra 167 // First four fields are mandatory. No more than 9 fields are expected.
104 // fields. See crbug.com/667834. 168 if (fields.size() < 4 || fields.size() > 9) {
105 if (fields.size() != 8) 169 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
170 << ")";
106 return false; 171 return false;
172 }
107 173
108 if (fields[0] != "vp09") 174 if (fields[0] != "vp09") {
175 DVLOG(3) << __func__ << " Invalid 4CC (" << fields[0] << ")";
109 return false; 176 return false;
177 }
110 178
111 std::vector<int> values; 179 std::vector<int> values;
112 for (size_t i = 1; i < fields.size(); ++i) { 180 for (size_t i = 1; i < fields.size(); ++i) {
113 // Missing value is not allowed. 181 // Missing value is not allowed.
114 if (fields[i] == "") 182 if (fields[i] == "") {
183 DVLOG(3) << __func__ << " Invalid missing field (position:" << i << ")";
115 return false; 184 return false;
185 }
116 int value; 186 int value;
117 if (!base::StringToInt(fields[i], &value)) 187 if (!base::StringToInt(fields[i], &value) || value < 0) {
188 DVLOG(3) << __func__ << " Invalid field value (" << value << ")";
118 return false; 189 return false;
119 if (value < 0) 190 }
120 return false;
121 values.push_back(value); 191 values.push_back(value);
122 } 192 }
123 193
124 const int profile_idc = values[0]; 194 const int profile_idc = values[0];
125 switch (profile_idc) { 195 switch (profile_idc) {
126 case 0: 196 case 0:
127 *profile = VP9PROFILE_PROFILE0; 197 *profile = VP9PROFILE_PROFILE0;
128 break; 198 break;
129 case 1: 199 case 1:
130 *profile = VP9PROFILE_PROFILE1; 200 *profile = VP9PROFILE_PROFILE1;
131 break; 201 break;
132 case 2: 202 case 2:
133 *profile = VP9PROFILE_PROFILE2; 203 *profile = VP9PROFILE_PROFILE2;
134 break; 204 break;
135 case 3: 205 case 3:
136 *profile = VP9PROFILE_PROFILE3; 206 *profile = VP9PROFILE_PROFILE3;
137 break; 207 break;
138 default: 208 default:
209 DVLOG(3) << __func__ << " Invalid profile (" << profile_idc << ")";
139 return false; 210 return false;
140 } 211 }
141 212
142 *level_idc = values[1]; 213 *level_idc = values[1];
143 // TODO(kqyang): Check if |level_idc| is valid. See crbug.com/667834. 214 switch (*level_idc) {
215 case 1:
216 case 11:
217 case 2:
218 case 21:
219 case 3:
220 case 31:
221 case 4:
222 case 41:
223 case 5:
224 case 51:
225 case 52:
226 case 6:
227 case 61:
228 case 62:
229 break;
230 default:
231 DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
232 return false;
233 }
144 234
145 const int bit_depth = values[2]; 235 const int bit_depth = values[2];
146 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) 236 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
237 DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")";
147 return false; 238 return false;
239 }
148 240
149 const int color_space = values[3]; 241 if (values.size() < 4)
150 if (color_space > 7) 242 return true;
243 const int color_primaries = values[3];
244 // TODO(chcunningham): parse and bubble up color primaries, described in ISO
245 // 23001-8:2016 Table 2.
246 if (color_primaries > 22) {
247 DVLOG(3) << __func__ << " Invalid color primaries (" << color_primaries
248 << ")";
151 return false; 249 return false;
250 }
152 251
153 const int chroma_subsampling = values[4]; 252 // Described in ISO 23001-8:2016 Table 3.
154 if (chroma_subsampling > 3) 253 if (values.size() < 5)
254 return true;
255 if (!ParseVp9Eotf(values[4], eotf)) {
256 DVLOG(3) << __func__ << " Invalid transfer function (" << values[4] << ")";
155 return false; 257 return false;
258 }
156 259
157 const int transfer_function = values[5]; 260 // TODO(chcunningham): Parse and bubble up the following fields. For now just
158 if (transfer_function > 1) 261 // doing basic validation.
262
263 if (values.size() < 6)
264 return true;
265 const int matrix_coefficients = values[5];
266 if (matrix_coefficients > 11) {
267 DVLOG(3) << __func__ << " Invalid matrix coefficients ("
268 << matrix_coefficients << ")";
159 return false; 269 return false;
270 }
160 271
272 if (values.size() < 7)
273 return true;
161 const int video_full_range_flag = values[6]; 274 const int video_full_range_flag = values[6];
162 if (video_full_range_flag > 1) 275 if (video_full_range_flag > 1) {
276 DVLOG(3) << __func__ << " Invalid full range flag ("
277 << video_full_range_flag << ")";
163 return false; 278 return false;
279 }
280
281 if (values.size() < 8)
282 return true;
283 const int chroma_subsampling = values[7];
284 if (chroma_subsampling > 3 ||
285 (chroma_subsampling != 3 && matrix_coefficients == 0)) {
286 DVLOG(3) << __func__ << " Invalid chroma subsampling ("
287 << chroma_subsampling << ")";
288 return false;
289 }
164 290
165 return true; 291 return true;
166 } 292 }
167 293
168 bool ParseLegacyVp9CodecID(const std::string& codec_id, 294 bool ParseLegacyVp9CodecID(const std::string& codec_id,
169 VideoCodecProfile* profile, 295 VideoCodecProfile* profile,
170 uint8_t* level_idc) { 296 uint8_t* level_idc) {
171 if (codec_id == "vp9" || codec_id == "vp9.0") { 297 if (codec_id == "vp9" || codec_id == "vp9.0") {
172 // Profile is not included in the codec string. Assuming profile 0 to be 298 // Profile is not included in the codec string. Assuming profile 0 to be
173 // backward compatible. 299 // backward compatible.
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 651
526 return true; 652 return true;
527 } 653 }
528 #endif 654 #endif
529 655
530 VideoCodec StringToVideoCodec(const std::string& codec_id) { 656 VideoCodec StringToVideoCodec(const std::string& codec_id) {
531 std::vector<std::string> elem = base::SplitString( 657 std::vector<std::string> elem = base::SplitString(
532 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 658 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
533 if (elem.empty()) 659 if (elem.empty())
534 return kUnknownVideoCodec; 660 return kUnknownVideoCodec;
661
535 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; 662 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
536 uint8_t level = 0; 663 uint8_t level = 0;
664 gfx::ColorSpace::TransferID eotf = gfx::ColorSpace::TransferID::INVALID;
665
537 if (codec_id == "vp8" || codec_id == "vp8.0") 666 if (codec_id == "vp8" || codec_id == "vp8.0")
538 return kCodecVP8; 667 return kCodecVP8;
539 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level) || 668 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &eotf) ||
540 ParseLegacyVp9CodecID(codec_id, &profile, &level)) { 669 ParseLegacyVp9CodecID(codec_id, &profile, &level)) {
541 return kCodecVP9; 670 return kCodecVP9;
542 } 671 }
543 if (codec_id == "theora") 672 if (codec_id == "theora")
544 return kCodecTheora; 673 return kCodecTheora;
545 if (ParseAVCCodecId(codec_id, &profile, &level)) 674 if (ParseAVCCodecId(codec_id, &profile, &level))
546 return kCodecH264; 675 return kCodecH264;
547 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) 676 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
548 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level)) 677 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level))
549 return kCodecH264; 678 return kCodecH264;
550 #endif 679 #endif
551 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) 680 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
552 if (ParseHEVCCodecId(codec_id, &profile, &level)) 681 if (ParseHEVCCodecId(codec_id, &profile, &level))
553 return kCodecHEVC; 682 return kCodecHEVC;
554 #endif 683 #endif
555 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) 684 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING)
556 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) 685 if (ParseDolbyVisionCodecId(codec_id, &profile, &level))
557 return kCodecDolbyVision; 686 return kCodecDolbyVision;
558 #endif 687 #endif
559 return kUnknownVideoCodec; 688 return kUnknownVideoCodec;
560 } 689 }
561 690
562 } // namespace media 691 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698