[M120 Migration][MM][WebRTC] Add encoded video capture type support
[platform/framework/web/chromium-efl.git] / media / base / video_codecs.cc
1 // Copyright 2015 The Chromium Authors
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/base/video_codecs.h"
6
7 #include "base/logging.h"
8 #include "base/notreached.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "media/base/video_color_space.h"
15 #include "ui/gfx/color_space.h"
16
17 namespace media {
18
19 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c
20 // TODO(crbug.com/1357080): The returned strings are used by ChunkDemuxer in
21 // the code logic as well in tests. Merge with GetCodecNameForUMA() if possible.
22 std::string GetCodecName(VideoCodec codec) {
23   switch (codec) {
24     case VideoCodec::kUnknown:
25       return "unknown";
26     case VideoCodec::kH264:
27       return "h264";
28     case VideoCodec::kHEVC:
29       return "hevc";
30     case VideoCodec::kDolbyVision:
31       return "dolbyvision";
32     case VideoCodec::kVC1:
33       return "vc1";
34     case VideoCodec::kMPEG2:
35       return "mpeg2video";
36     case VideoCodec::kMPEG4:
37       return "mpeg4";
38     case VideoCodec::kTheora:
39       return "theora";
40     case VideoCodec::kVP8:
41       return "vp8";
42     case VideoCodec::kVP9:
43       return "vp9";
44     case VideoCodec::kAV1:
45       return "av1";
46 #if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT)
47     case VideoCodec::kMJPEG:
48       return "mjpeg";
49 #endif
50   }
51   NOTREACHED_NORETURN();
52 }
53
54 // Reported as part of some UMA names. NEVER change existing strings!
55 std::string GetCodecNameForUMA(VideoCodec codec) {
56   switch (codec) {
57     case VideoCodec::kUnknown:
58       return "Unknown";
59     case VideoCodec::kH264:
60       return "H264";
61     case VideoCodec::kHEVC:
62       return "HEVC";
63     case VideoCodec::kDolbyVision:
64       return "DolbyVision";
65     case VideoCodec::kVC1:
66       return "VC1";
67     case VideoCodec::kMPEG2:
68       return "MPEG2Video";
69     case VideoCodec::kMPEG4:
70       return "MPEG4";
71     case VideoCodec::kTheora:
72       return "Theora";
73     case VideoCodec::kVP8:
74       return "VP8";
75     case VideoCodec::kVP9:
76       return "VP9";
77     case VideoCodec::kAV1:
78       return "AV1";
79   }
80   NOTREACHED_NORETURN();
81 }
82
83 std::string GetProfileName(VideoCodecProfile profile) {
84   switch (profile) {
85     case VIDEO_CODEC_PROFILE_UNKNOWN:
86       return "unknown";
87     case H264PROFILE_BASELINE:
88       return "h264 baseline";
89     case H264PROFILE_MAIN:
90       return "h264 main";
91     case H264PROFILE_EXTENDED:
92       return "h264 extended";
93     case H264PROFILE_HIGH:
94       return "h264 high";
95     case H264PROFILE_HIGH10PROFILE:
96       return "h264 high 10";
97     case H264PROFILE_HIGH422PROFILE:
98       return "h264 high 4:2:2";
99     case H264PROFILE_HIGH444PREDICTIVEPROFILE:
100       return "h264 high 4:4:4 predictive";
101     case H264PROFILE_SCALABLEBASELINE:
102       return "h264 scalable baseline";
103     case H264PROFILE_SCALABLEHIGH:
104       return "h264 scalable high";
105     case H264PROFILE_STEREOHIGH:
106       return "h264 stereo high";
107     case H264PROFILE_MULTIVIEWHIGH:
108       return "h264 multiview high";
109     case HEVCPROFILE_MAIN:
110       return "hevc main";
111     case HEVCPROFILE_MAIN10:
112       return "hevc main 10";
113     case HEVCPROFILE_MAIN_STILL_PICTURE:
114       return "hevc main still-picture";
115     case HEVCPROFILE_REXT:
116       return "hevc range extensions";
117     case HEVCPROFILE_HIGH_THROUGHPUT:
118       return "hevc high throughput";
119     case HEVCPROFILE_MULTIVIEW_MAIN:
120       return "hevc multiview main";
121     case HEVCPROFILE_SCALABLE_MAIN:
122       return "hevc scalable main";
123     case HEVCPROFILE_3D_MAIN:
124       return "hevc 3d main";
125     case HEVCPROFILE_SCREEN_EXTENDED:
126       return "hevc screen extended";
127     case HEVCPROFILE_SCALABLE_REXT:
128       return "hevc scalable range extensions";
129     case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
130       return "hevc high throughput screen extended";
131     case VP8PROFILE_ANY:
132       return "vp8";
133     case VP9PROFILE_PROFILE0:
134       return "vp9 profile0";
135     case VP9PROFILE_PROFILE1:
136       return "vp9 profile1";
137     case VP9PROFILE_PROFILE2:
138       return "vp9 profile2";
139     case VP9PROFILE_PROFILE3:
140       return "vp9 profile3";
141     case DOLBYVISION_PROFILE0:
142       return "dolby vision profile 0";
143     case DOLBYVISION_PROFILE4:
144       return "dolby vision profile 4";
145     case DOLBYVISION_PROFILE5:
146       return "dolby vision profile 5";
147     case DOLBYVISION_PROFILE7:
148       return "dolby vision profile 7";
149     case DOLBYVISION_PROFILE8:
150       return "dolby vision profile 8";
151     case DOLBYVISION_PROFILE9:
152       return "dolby vision profile 9";
153     case THEORAPROFILE_ANY:
154       return "theora";
155     case AV1PROFILE_PROFILE_MAIN:
156       return "av1 profile main";
157     case AV1PROFILE_PROFILE_HIGH:
158       return "av1 profile high";
159     case AV1PROFILE_PROFILE_PRO:
160       return "av1 profile pro";
161     case VVCPROFILE_MAIN10:
162       return "vvc profile main10";
163     case VVCPROFILE_MAIN12:
164       return "vvc profile main12";
165     case VVCPROFILE_MAIN12_INTRA:
166       return "vvc profile main12 intra";
167     case VVCPROIFLE_MULTILAYER_MAIN10:
168       return "vvc profile multilayer main10";
169     case VVCPROFILE_MAIN10_444:
170       return "vvc profile main10 444";
171     case VVCPROFILE_MAIN12_444:
172       return "vvc profile main12 444";
173     case VVCPROFILE_MAIN16_444:
174       return "vvc profile main16 444";
175     case VVCPROFILE_MAIN12_444_INTRA:
176       return "vvc profile main12 444 intra";
177     case VVCPROFILE_MAIN16_444_INTRA:
178       return "vvc profile main16 444 intra";
179     case VVCPROFILE_MULTILAYER_MAIN10_444:
180       return "vvc profile multilayer main10 444";
181     case VVCPROFILE_MAIN10_STILL_PICTURE:
182       return "vvc profile main10 still picture";
183     case VVCPROFILE_MAIN12_STILL_PICTURE:
184       return "vvc profile main12 still picture";
185     case VVCPROFILE_MAIN10_444_STILL_PICTURE:
186       return "vvc profile main10 444 still picture";
187     case VVCPROFILE_MAIN12_444_STILL_PICTURE:
188       return "vvc profile main12 444 still picture";
189     case VVCPROFILE_MAIN16_444_STILL_PICTURE:
190       return "vvc profile main16 444 still picture";
191   }
192   NOTREACHED_NORETURN();
193 }
194
195 std::string BuildH264MimeSuffix(media::VideoCodecProfile profile,
196                                 uint8_t level) {
197   std::string profile_str;
198   switch (profile) {
199     case media::VideoCodecProfile::H264PROFILE_BASELINE:
200       profile_str = "42";
201       break;
202     case media::VideoCodecProfile::H264PROFILE_MAIN:
203       profile_str = "4d";
204       break;
205     case media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE:
206       profile_str = "53";
207       break;
208     case media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH:
209       profile_str = "56";
210       break;
211     case media::VideoCodecProfile::H264PROFILE_EXTENDED:
212       profile_str = "58";
213       break;
214     case media::VideoCodecProfile::H264PROFILE_HIGH:
215       profile_str = "64";
216       break;
217     case media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE:
218       profile_str = "6e";
219       break;
220     case media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH:
221       profile_str = "76";
222       break;
223     case media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE:
224       profile_str = "7a";
225       break;
226     case media::VideoCodecProfile::H264PROFILE_STEREOHIGH:
227       profile_str = "80";
228       break;
229     case media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE:
230       profile_str = "f4";
231       break;
232     default:
233       return "";
234   }
235
236   return base::StringPrintf(".%s%04x", profile_str.c_str(), level);
237 }
238
239 bool ParseNewStyleVp9CodecID(base::StringPiece codec_id,
240                              VideoCodecProfile* profile,
241                              uint8_t* level_idc,
242                              VideoColorSpace* color_space) {
243   // Initialize optional fields to their defaults.
244   *color_space = VideoColorSpace::REC709();
245
246   std::vector<std::string> fields = base::SplitString(
247       codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
248
249   // First four fields are mandatory. No more than 9 fields are expected.
250   if (fields.size() < 4 || fields.size() > 9) {
251     DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
252              << ")";
253     return false;
254   }
255
256   if (fields[0] != "vp09") {
257     DVLOG(3) << __func__ << " Invalid 4CC (" << fields[0] << ")";
258     return false;
259   }
260
261   std::vector<int> values;
262   for (size_t i = 1; i < fields.size(); ++i) {
263     // Missing value is not allowed.
264     if (fields[i] == "") {
265       DVLOG(3) << __func__ << " Invalid missing field (position:" << i << ")";
266       return false;
267     }
268     int value;
269     if (!base::StringToInt(fields[i], &value) || value < 0) {
270       DVLOG(3) << __func__ << " Invalid field value (" << value << ")";
271       return false;
272     }
273     values.push_back(value);
274   }
275
276   const int profile_idc = values[0];
277   switch (profile_idc) {
278     case 0:
279       *profile = VP9PROFILE_PROFILE0;
280       break;
281     case 1:
282       *profile = VP9PROFILE_PROFILE1;
283       break;
284     case 2:
285       *profile = VP9PROFILE_PROFILE2;
286       break;
287     case 3:
288       *profile = VP9PROFILE_PROFILE3;
289       break;
290     default:
291       DVLOG(3) << __func__ << " Invalid profile (" << profile_idc << ")";
292       return false;
293   }
294
295   *level_idc = values[1];
296   switch (*level_idc) {
297     case 10:
298     case 11:
299     case 20:
300     case 21:
301     case 30:
302     case 31:
303     case 40:
304     case 41:
305     case 50:
306     case 51:
307     case 52:
308     case 60:
309     case 61:
310     case 62:
311       break;
312     default:
313       DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
314       return false;
315   }
316
317   const int bit_depth = values[2];
318   if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
319     DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")";
320     return false;
321   }
322
323   if (values.size() < 4)
324     return true;
325   const int chroma_subsampling = values[3];
326   if (chroma_subsampling > 3) {
327     DVLOG(3) << __func__ << " Invalid chroma subsampling ("
328              << chroma_subsampling << ")";
329     return false;
330   }
331
332   if (values.size() < 5)
333     return true;
334   color_space->primaries = VideoColorSpace::GetPrimaryID(values[4]);
335   if (color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
336     DVLOG(3) << __func__ << " Invalid color primaries (" << values[4] << ")";
337     return false;
338   }
339
340   if (values.size() < 6)
341     return true;
342   color_space->transfer = VideoColorSpace::GetTransferID(values[5]);
343   if (color_space->transfer == VideoColorSpace::TransferID::INVALID) {
344     DVLOG(3) << __func__ << " Invalid transfer function (" << values[5] << ")";
345     return false;
346   }
347
348   if (values.size() < 7)
349     return true;
350   color_space->matrix = VideoColorSpace::GetMatrixID(values[6]);
351   if (color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
352     DVLOG(3) << __func__ << " Invalid matrix coefficients (" << values[6]
353              << ")";
354     return false;
355   }
356   if (color_space->matrix == VideoColorSpace::MatrixID::RGB &&
357       chroma_subsampling != 3) {
358     DVLOG(3) << __func__ << " Invalid combination of chroma_subsampling ("
359              << ") and matrix coefficients (" << values[6] << ")";
360   }
361
362   if (values.size() < 8)
363     return true;
364   const int video_full_range_flag = values[7];
365   if (video_full_range_flag > 1) {
366     DVLOG(3) << __func__ << " Invalid full range flag ("
367              << video_full_range_flag << ")";
368     return false;
369   }
370   color_space->range = video_full_range_flag == 1
371                            ? gfx::ColorSpace::RangeID::FULL
372                            : gfx::ColorSpace::RangeID::LIMITED;
373
374   return true;
375 }
376
377 bool ParseLegacyVp9CodecID(base::StringPiece codec_id,
378                            VideoCodecProfile* profile,
379                            uint8_t* level_idc) {
380   if (codec_id == "vp9" || codec_id == "vp9.0") {
381     // Profile is not included in the codec string. Consumers of parsed codec
382     // should handle by rejecting ambiguous string or resolving to a default
383     // profile.
384     *profile = VIDEO_CODEC_PROFILE_UNKNOWN;
385     // Use 0 to indicate unknown level.
386     *level_idc = 0;
387     return true;
388   }
389   return false;
390 }
391
392 #if BUILDFLAG(ENABLE_AV1_DECODER)
393 bool ParseAv1CodecId(base::StringPiece codec_id,
394                      VideoCodecProfile* profile,
395                      uint8_t* level_idc,
396                      VideoColorSpace* color_space) {
397   // The codecs parameter string for the AOM AV1 codec is as follows:
398   // See https://aomediacodec.github.io/av1-isobmff/#codecsparam.
399   //
400   // <sample entry4CC>.<profile>.<level><tier>.<bitDepth>.<monochrome>.
401   // <chromaSubsampling>.<colorPrimaries>.<transferCharacteristics>.
402   // <matrixCoefficients>.<videoFullRangeFlag>
403
404   std::vector<std::string> fields = base::SplitString(
405       codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
406
407   // The parameters sample entry 4CC, profile, level, tier, and bitDepth are all
408   // mandatory fields. If any of these fields are empty, or not within their
409   // allowed range, the processing device SHOULD treat it as an error.
410   if (fields.size() < 4 || fields.size() > 10) {
411     DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
412              << ")";
413     return false;
414   }
415
416   // All the other fields (including their leading '.') are optional, mutually
417   // inclusive (all or none) fields. If not specified then the values listed in
418   // the table below are assumed.
419   //
420   // mono_chrome              0
421   // chromaSubsampling        112 (4:2:0 colocated with luma (0,0))
422   // colorPrimaries           1 (ITU-R BT.709)
423   // transferCharacteristics  1 (ITU-R BT.709)
424   // matrixCoefficients       1 (ITU-R BT.709)
425   // videoFullRangeFlag       0 (studio swing representation)
426   *color_space = VideoColorSpace::REC709();
427
428   if (fields[0] != "av01") {
429     DVLOG(3) << __func__ << " Invalid AV1 4CC (" << fields[0] << ")";
430     return false;
431   }
432
433   // The level parameter value SHALL equal the first level value indicated by
434   // seq_level_idx in the Sequence Header. The tier parameter value SHALL be
435   // equal to M when the first seq_tier value in the Sequence Header is equal to
436   // 0, and H when it is equal to 1.
437   if (fields[2].size() != 3 || (fields[2][2] != 'M' && fields[2][2] != 'H')) {
438     DVLOG(3) << __func__ << " Invalid level+tier (" << fields[2] << ")";
439     return false;
440   }
441
442   // Since tier has been validated, strip the trailing tier indicator to allow
443   // int conversion below.
444   fields[2].resize(2);
445
446   // Fill with dummy values to ensure parallel indices with fields.
447   std::vector<int> values(fields.size(), 0);
448   for (size_t i = 1; i < fields.size(); ++i) {
449     if (fields[i].empty()) {
450       DVLOG(3) << __func__ << " Invalid empty field (position:" << i << ")";
451       return false;
452     }
453
454     if (!base::StringToInt(fields[i], &values[i]) || values[i] < 0) {
455       DVLOG(3) << __func__ << " Invalid field value (" << values[i] << ")";
456       return false;
457     }
458   }
459
460   // The profile parameter value, represented by a single digit decimal, SHALL
461   // equal the value of seq_profile in the Sequence Header.
462   const int profile_idc = fields[1].size() == 1 ? values[1] : -1;
463   switch (profile_idc) {
464     case 0:
465       *profile = AV1PROFILE_PROFILE_MAIN;
466       break;
467     case 1:
468       *profile = AV1PROFILE_PROFILE_HIGH;
469       break;
470     case 2:
471       *profile = AV1PROFILE_PROFILE_PRO;
472       break;
473     default:
474       DVLOG(3) << __func__ << " Invalid profile (" << fields[1] << ")";
475       return false;
476   }
477
478   // The level parameter value SHALL equal the first level value indicated by
479   // seq_level_idx in the Sequence Header. Note: We validate that this field has
480   // the required leading zeros above.
481   *level_idc = values[2];
482   if (*level_idc > 31) {
483     DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
484     return false;
485   }
486
487   // The bitDepth parameter value SHALL equal the value of BitDepth variable as
488   // defined in [AV1] derived from the Sequence Header. Leading zeros required.
489   const int bit_depth = values[3];
490   if (fields[3].size() != 2 ||
491       (bit_depth != 8 && bit_depth != 10 && bit_depth != 12)) {
492     DVLOG(3) << __func__ << " Invalid bit-depth (" << fields[3] << ")";
493     return false;
494   }
495
496   if (values.size() <= 4)
497     return true;
498
499   // The monochrome parameter value, represented by a single digit decimal,
500   // SHALL equal the value of mono_chrome in the Sequence Header.
501   const int monochrome = values[4];
502   if (fields[4].size() != 1 || monochrome > 1) {
503     DVLOG(3) << __func__ << " Invalid monochrome (" << fields[4] << ")";
504     return false;
505   }
506
507   if (values.size() <= 5)
508     return true;
509
510   // The chromaSubsampling parameter value, represented by a three-digit
511   // decimal, SHALL have its first digit equal to subsampling_x and its second
512   // digit equal to subsampling_y. If both subsampling_x and subsampling_y are
513   // set to 1, then the third digit SHALL be equal to chroma_sample_position,
514   // otherwise it SHALL be set to 0.
515   if (fields[5].size() != 3) {
516     DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
517     return false;
518   }
519
520   const char subsampling_x = fields[5][0];
521   const char subsampling_y = fields[5][1];
522   const char chroma_sample_position = fields[5][2];
523   if ((subsampling_x < '0' || subsampling_x > '1') ||
524       (subsampling_y < '0' || subsampling_y > '1') ||
525       (chroma_sample_position < '0' || chroma_sample_position > '3')) {
526     DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
527     return false;
528   }
529
530   if (((subsampling_x == '0' || subsampling_y == '0') &&
531        chroma_sample_position != '0')) {
532     DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
533     return false;
534   }
535
536   if (values.size() <= 6)
537     return true;
538
539   // The colorPrimaries, transferCharacteristics, matrixCoefficients and
540   // videoFullRangeFlag parameter values SHALL equal the value of matching
541   // fields in the Sequence Header, if color_description_present_flag is set to
542   // 1, otherwise they SHOULD not be set, defaulting to the values below. The
543   // videoFullRangeFlag is represented by a single digit.
544   color_space->primaries = VideoColorSpace::GetPrimaryID(values[6]);
545   if (fields[6].size() != 2 ||
546       color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
547     DVLOG(3) << __func__ << " Invalid color primaries (" << fields[6] << ")";
548     return false;
549   }
550
551   if (values.size() <= 7)
552     return true;
553
554   color_space->transfer = VideoColorSpace::GetTransferID(values[7]);
555   if (fields[7].size() != 2 ||
556       color_space->transfer == VideoColorSpace::TransferID::INVALID) {
557     DVLOG(3) << __func__ << " Invalid transfer function (" << fields[7] << ")";
558     return false;
559   }
560
561   if (values.size() <= 8)
562     return true;
563
564   color_space->matrix = VideoColorSpace::GetMatrixID(values[8]);
565   if (fields[8].size() != 2 ||
566       color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
567     // TODO(dalecurtis): AV1 allows a few matrices we don't support yet.
568     // https://crbug.com/854290
569     if (values[8] == 12 || values[8] == 13 || values[8] == 14) {
570       DVLOG(3) << __func__ << " Unsupported matrix coefficients (" << fields[8]
571                << ")";
572     } else {
573       DVLOG(3) << __func__ << " Invalid matrix coefficients (" << fields[8]
574                << ")";
575     }
576     return false;
577   }
578
579   if (values.size() <= 9)
580     return true;
581
582   const int video_full_range_flag = values[9];
583   if (fields[9].size() != 1 || video_full_range_flag > 1) {
584     DVLOG(3) << __func__ << " Invalid full range flag (" << fields[9] << ")";
585     return false;
586   }
587   color_space->range = video_full_range_flag == 1
588                            ? gfx::ColorSpace::RangeID::FULL
589                            : gfx::ColorSpace::RangeID::LIMITED;
590
591   return true;
592 }
593 #endif  // BUILDFLAG(ENABLE_AV1_DECODER)
594
595 bool ParseAVCCodecId(base::StringPiece codec_id,
596                      VideoCodecProfile* profile,
597                      uint8_t* level_idc) {
598   // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits
599   if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) &&
600       !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) {
601     return false;
602   }
603   uint32_t elem = 0;
604   if (codec_id.size() != 11 ||
605       !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) {
606     DVLOG(4) << __func__ << ": invalid avc codec id (" << codec_id << ")";
607     return false;
608   }
609
610   uint8_t level_byte = elem & 0xFF;
611   uint8_t constraints_byte = (elem >> 8) & 0xFF;
612   uint8_t profile_idc = (elem >> 16) & 0xFF;
613
614   // Check that the lower two bits of |constraints_byte| are zero (those are
615   // reserved and must be zero according to ISO IEC 14496-10).
616   if (constraints_byte & 3) {
617     DVLOG(4) << __func__ << ": non-zero reserved bits in codec id " << codec_id;
618     return false;
619   }
620
621   VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
622   // profile_idc values for each profile are taken from ISO IEC 14496-10 and
623   // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
624   switch (profile_idc) {
625     case 66:
626       out_profile = H264PROFILE_BASELINE;
627       break;
628     case 77:
629       out_profile = H264PROFILE_MAIN;
630       break;
631     case 83:
632       out_profile = H264PROFILE_SCALABLEBASELINE;
633       break;
634     case 86:
635       out_profile = H264PROFILE_SCALABLEHIGH;
636       break;
637     case 88:
638       out_profile = H264PROFILE_EXTENDED;
639       break;
640     case 100:
641       out_profile = H264PROFILE_HIGH;
642       break;
643     case 110:
644       out_profile = H264PROFILE_HIGH10PROFILE;
645       break;
646     case 118:
647       out_profile = H264PROFILE_MULTIVIEWHIGH;
648       break;
649     case 122:
650       out_profile = H264PROFILE_HIGH422PROFILE;
651       break;
652     case 128:
653       out_profile = H264PROFILE_STEREOHIGH;
654       break;
655     case 244:
656       out_profile = H264PROFILE_HIGH444PREDICTIVEPROFILE;
657       break;
658     default:
659       DVLOG(1) << "Warning: unrecognized AVC/H.264 profile " << profile_idc;
660       return false;
661   }
662
663   // TODO(servolk): Take into account also constraint set flags 3 through 5.
664   uint8_t constraint_set0_flag = (constraints_byte >> 7) & 1;
665   uint8_t constraint_set1_flag = (constraints_byte >> 6) & 1;
666   uint8_t constraint_set2_flag = (constraints_byte >> 5) & 1;
667   if (constraint_set2_flag && out_profile > H264PROFILE_EXTENDED) {
668     out_profile = H264PROFILE_EXTENDED;
669   }
670   if (constraint_set1_flag && out_profile > H264PROFILE_MAIN) {
671     out_profile = H264PROFILE_MAIN;
672   }
673   if (constraint_set0_flag && out_profile > H264PROFILE_BASELINE) {
674     out_profile = H264PROFILE_BASELINE;
675   }
676
677   if (level_idc)
678     *level_idc = level_byte;
679
680   if (profile)
681     *profile = out_profile;
682
683   return true;
684 }
685
686 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
687 std::string TranslateLegacyAvc1CodecIds(base::StringPiece codec_id) {
688   // Special handling for old, pre-RFC 6381 format avc1 strings, which are still
689   // being used by some HLS apps to preserve backward compatibility with older
690   // iOS devices. The old format was avc1.<profile>.<level>
691   // Where <profile> is H.264 profile_idc encoded as a decimal number, i.e.
692   // 66 is baseline profile (0x42)
693   // 77 is main profile (0x4d)
694   // 100 is high profile (0x64)
695   // And <level> is H.264 level multiplied by 10, also encoded as decimal number
696   // E.g. <level> 31 corresponds to H.264 level 3.1
697   // See, for example, http://qtdevseed.apple.com/qadrift/testcases/tc-0133.php
698   uint32_t level_start = 0;
699   std::string result;
700   if (base::StartsWith(codec_id, "avc1.66.", base::CompareCase::SENSITIVE)) {
701     level_start = 8;
702     result = "avc1.4200";
703   } else if (base::StartsWith(codec_id, "avc1.77.",
704                               base::CompareCase::SENSITIVE)) {
705     level_start = 8;
706     result = "avc1.4D00";
707   } else if (base::StartsWith(codec_id, "avc1.100.",
708                               base::CompareCase::SENSITIVE)) {
709     level_start = 9;
710     result = "avc1.6400";
711   }
712
713   uint32_t level = 0;
714   if (level_start > 0 &&
715       base::StringToUint(codec_id.substr(level_start), &level) && level < 256) {
716     // This is a valid legacy avc1 codec id - return the codec id translated
717     // into RFC 6381 format.
718     base::AppendHexEncodedByte(static_cast<uint8_t>(level), result);
719     return result;
720   }
721
722   // This is not a valid legacy avc1 codec id - return the original codec id.
723   return std::string(codec_id);
724 }
725 #endif
726
727 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
728 // The specification for HEVC codec id strings can be found in ISO IEC 14496-15
729 // dated 2012 or newer in the Annex E.3
730 bool ParseHEVCCodecId(base::StringPiece codec_id,
731                       VideoCodecProfile* profile,
732                       uint8_t* level_idc) {
733   if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) &&
734       !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) {
735     return false;
736   }
737
738   // HEVC codec id consists of:
739   const int kMaxHevcCodecIdLength =
740       5 +  // 'hev1.' or 'hvc1.' prefix (5 chars)
741       4 +  // profile, e.g. '.A12' (max 4 chars)
742       9 +  // profile_compatibility, dot + 32-bit hex number (max 9 chars)
743       5 +  // tier and level, e.g. '.H120' (max 5 chars)
744       18;  // up to 6 constraint bytes, bytes are dot-separated and hex-encoded.
745
746   if (codec_id.size() > kMaxHevcCodecIdLength) {
747     DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
748     return false;
749   }
750
751   std::vector<std::string> elem = base::SplitString(
752       codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
753   DCHECK(elem[0] == "hev1" || elem[0] == "hvc1");
754
755   if (elem.size() < 4) {
756     DVLOG(4) << __func__ << ": invalid HEVC codec id " << codec_id;
757     return false;
758   }
759
760   uint8_t general_profile_space = 0;
761   if (elem[1].size() > 0 &&
762       (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) {
763     general_profile_space = 1 + (elem[1][0] - 'A');
764     elem[1].erase(0, 1);
765   }
766   DCHECK(general_profile_space >= 0 && general_profile_space <= 3);
767
768   unsigned general_profile_idc = 0;
769   if (!base::StringToUint(elem[1], &general_profile_idc) ||
770       general_profile_idc > 0x1f) {
771     DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
772     return false;
773   }
774
775   uint32_t general_profile_compatibility_flags = 0;
776   if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) {
777     DVLOG(4) << __func__
778              << ": invalid general_profile_compatibility_flags=" << elem[2];
779     return false;
780   }
781
782   VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
783   // Spec A.3.8
784   if (general_profile_idc == 11 ||
785       (general_profile_compatibility_flags & 2048)) {
786     out_profile = HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED;
787   }
788   // Spec H.11.1.2
789   if (general_profile_idc == 10 ||
790       (general_profile_compatibility_flags & 1024)) {
791     out_profile = HEVCPROFILE_SCALABLE_REXT;
792   }
793   // Spec A.3.7
794   if (general_profile_idc == 9 || (general_profile_compatibility_flags & 512)) {
795     out_profile = HEVCPROFILE_SCREEN_EXTENDED;
796   }
797   // Spec I.11.1.1
798   if (general_profile_idc == 8 || (general_profile_compatibility_flags & 256)) {
799     out_profile = HEVCPROFILE_3D_MAIN;
800   }
801   // Spec H.11.1.1
802   if (general_profile_idc == 7 || (general_profile_compatibility_flags & 128)) {
803     out_profile = HEVCPROFILE_SCALABLE_MAIN;
804   }
805   // Spec G.11.1.1
806   if (general_profile_idc == 6 || (general_profile_compatibility_flags & 64)) {
807     out_profile = HEVCPROFILE_MULTIVIEW_MAIN;
808   }
809   // Spec A.3.6
810   if (general_profile_idc == 5 || (general_profile_compatibility_flags & 32)) {
811     out_profile = HEVCPROFILE_HIGH_THROUGHPUT;
812   }
813   // Spec A.3.5
814   if (general_profile_idc == 4 || (general_profile_compatibility_flags & 16)) {
815     out_profile = HEVCPROFILE_REXT;
816   }
817   // Spec A.3.3
818   // NOTICE: Do not change the order of below sections
819   if (general_profile_idc == 2 || (general_profile_compatibility_flags & 4)) {
820     out_profile = HEVCPROFILE_MAIN10;
821   }
822   // Spec A.3.2
823   // When general_profile_compatibility_flag[1] is equal to 1,
824   // general_profile_compatibility_flag[2] should be equal to 1 as well.
825   if (general_profile_idc == 1 || (general_profile_compatibility_flags & 2)) {
826     out_profile = HEVCPROFILE_MAIN;
827   }
828   // Spec A.3.4
829   // When general_profile_compatibility_flag[3] is equal to 1,
830   // general_profile_compatibility_flag[1] and
831   // general_profile_compatibility_flag[2] should be equal to 1 as well.
832   if (general_profile_idc == 3 || (general_profile_compatibility_flags & 8)) {
833     out_profile = HEVCPROFILE_MAIN_STILL_PICTURE;
834   }
835
836   if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
837     DVLOG(1) << "Warning: unrecognized HEVC/H.265 general_profile_idc: "
838              << general_profile_idc << ", general_profile_compatibility_flags: "
839              << general_profile_compatibility_flags;
840     return false;
841   }
842
843   if (profile)
844     *profile = out_profile;
845
846   uint8_t general_tier_flag;
847   if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) {
848     general_tier_flag = (elem[3][0] == 'L') ? 0 : 1;
849     elem[3].erase(0, 1);
850   } else {
851     DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[3];
852     return false;
853   }
854   DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
855
856   unsigned general_level_idc = 0;
857   if (!base::StringToUint(elem[3], &general_level_idc) ||
858       general_level_idc > 0xff) {
859     DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[3];
860     return false;
861   }
862
863   if (level_idc)
864     *level_idc = static_cast<uint8_t>(general_level_idc);
865
866   uint8_t constraint_flags[6];
867   memset(constraint_flags, 0, sizeof(constraint_flags));
868
869   if (elem.size() > 10) {
870     DVLOG(4) << __func__ << ": unexpected number of trailing bytes in HEVC "
871              << "codec id " << codec_id;
872     return false;
873   }
874   for (size_t i = 4; i < elem.size(); ++i) {
875     unsigned constr_byte = 0;
876     if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) {
877       DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i];
878       return false;
879     }
880     constraint_flags[i - 4] = constr_byte;
881   }
882
883   return true;
884 }
885 #endif
886
887 #if BUILDFLAG(ENABLE_PLATFORM_VVC)
888 // The specification for VVC codec id strings can be found in ISO/IEC 14496-15
889 // 2022, annex E.6.
890 // In detail it would be:
891 // <sample entry FourCC>    ("vvi1: if config is inband, or "vvc1" otherwise.)
892 // .<general_profile_idc>   (base10)
893 // .<general_tier_flag>     ("L" or "H")
894 // <op_level_idc>           (base10. <= general_level_idc in SPS)
895 // .C<ptl_frame_only_constraint_flag><ptl_multi_layer_enabled_flag> (optional)
896 // <general_constraint_info)  (base32 with "=" might be omitted.)
897 // .S<general_sub_profile_idc1>  (Optional, base32 with "=" might be omitted.)
898 // <+general_sub_profile_
899 // .O<ols_idx>+<max_tid>   (Optional, base10 OlsIdx & MaxTid)
900 bool ParseVVCCodecId(base::StringPiece codec_id,
901                      VideoCodecProfile* profile,
902                      uint8_t* level_idc) {
903   if (!base::StartsWith(codec_id, "vvc1.", base::CompareCase::SENSITIVE) &&
904       !base::StartsWith(codec_id, "vvi1.", base::CompareCase::SENSITIVE)) {
905     return false;
906   }
907
908   std::vector<std::string> elem = base::SplitString(
909       codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
910   DCHECK(elem[0] == "vvc1" || elem[0] == "vvi1");
911
912   if (elem.size() < 3 || elem.size() > 6) {
913     DVLOG(4) << __func__ << ": invalid VVC codec id " << codec_id;
914     return false;
915   }
916
917   for (auto& item : elem) {
918     if (item.size() < 1 ||
919         ((item[0] == 'C' || item[0] == 'S' || item[0] == 'O') &&
920          item.size() < 2)) {
921       DVLOG(4) << __func__ << ": subelement of VVC codec id invalid.";
922       return false;
923     }
924     if (item[0] == 'O' && item.back() == '+') {
925       DVLOG(4) << __func__ << ": invalid OlxIdx and MaxTid string.";
926       return false;
927     }
928   }
929
930   unsigned general_profile_idc = 0;
931   if (!base::StringToUint(elem[1], &general_profile_idc) ||
932       general_profile_idc > 0x63) {
933     DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
934     return false;
935   }
936
937   VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
938   switch (general_profile_idc) {
939     case 99:  // Spec A.3.5
940       out_profile = VVCPROFILE_MAIN16_444_STILL_PICTURE;
941       break;
942     case 98:  // Spec A.3.5
943       out_profile = VVCPROFILE_MAIN12_444_STILL_PICTURE;
944       break;
945     case 97:  // Spec A.3.2
946       out_profile = VVCPROFILE_MAIN10_444_STILL_PICTURE;
947       break;
948     case 66:  // Spec A.3.5
949       out_profile = VVCPROFILE_MAIN12_STILL_PICTURE;
950       break;
951     case 65:  // Spec A.3.1
952       out_profile = VVCPROFILE_MAIN10_STILL_PICTURE;
953       break;
954     case 49:  // Spec A.3.4
955       out_profile = VVCPROFILE_MULTILAYER_MAIN10_444;
956       break;
957     case 43:  // Spec A.3.5
958       out_profile = VVCPROFILE_MAIN16_444_INTRA;
959       break;
960     case 42:  // Spec A.3.5
961       out_profile = VVCPROFILE_MAIN12_444_INTRA;
962       break;
963     case 35:  // Spec A.3.5
964       out_profile = VVCPROFILE_MAIN16_444;
965       break;
966     case 34:  // Spec A.3.5
967       out_profile = VVCPROFILE_MAIN12_444;
968       break;
969     case 33:  // Spec A.3.2
970       out_profile = VVCPROFILE_MAIN10_444;
971       break;
972     case 17:  // Spec A.3.3
973       out_profile = VVCPROIFLE_MULTILAYER_MAIN10;
974       break;
975     case 10:  // Spec A.3.5
976       out_profile = VVCPROFILE_MAIN12_INTRA;
977       break;
978     case 2:  // Spec A.3.5
979       out_profile = VVCPROFILE_MAIN12;
980       break;
981     case 1:  // Spec A.3.1
982       out_profile = VVCPROFILE_MAIN10;
983       break;
984     default:
985       break;
986   }
987
988   if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
989     DVLOG(1) << "Warning: unrecognized VVC/H.266 general_profile_idc: "
990              << general_profile_idc;
991     return false;
992   }
993
994   if (profile) {
995     *profile = out_profile;
996   }
997
998   uint8_t general_tier_flag;
999   if (elem[2][0] == 'L' || elem[2][0] == 'H') {
1000     general_tier_flag = (elem[2][0] == 'L') ? 0 : 1;
1001     elem[2].erase(0, 1);
1002   } else {
1003     DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[2];
1004     return false;
1005   }
1006   DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
1007
1008   unsigned general_level_idc = 0;
1009   if (!base::StringToUint(elem[2], &general_level_idc) ||
1010       general_level_idc > 0xff) {
1011     DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[2];
1012     return false;
1013   }
1014
1015   if (level_idc) {
1016     *level_idc = static_cast<uint8_t>(general_level_idc);
1017   }
1018
1019   // C-string, if existing, should proceed S-string and O-string.
1020   // Similarly, S-string should proceed O-string.
1021   bool trailing_valid = true;
1022   if (elem.size() == 4) {
1023     if (elem[3][0] != 'C' && elem[3][0] != 'S' && elem[3][0] != 'O') {
1024       trailing_valid = false;
1025     }
1026   } else if (elem.size() == 5) {
1027     if (!((elem[3][0] == 'C' && elem[4][0] == 'S') ||
1028           (elem[3][0] == 'C' && elem[4][0] == 'O') ||
1029           (elem[3][0] == 'S' && elem[4][0] == 'O'))) {
1030       trailing_valid = false;
1031     }
1032   } else if (elem.size() == 6) {
1033     if (elem[3][0] != 'C' || elem[4][0] != 'S' || elem[5][0] != 'O') {
1034       trailing_valid = false;
1035     }
1036   }
1037
1038   if (!trailing_valid) {
1039     DVLOG(4) << __func__ << ": invalid traing codec string.";
1040     return false;
1041   }
1042
1043   return true;
1044 }
1045 #endif
1046
1047 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1048 bool IsDolbyVisionAVCCodecId(base::StringPiece codec_id) {
1049   return base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) ||
1050          base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE);
1051 }
1052
1053 bool IsDolbyVisionHEVCCodecId(base::StringPiece codec_id) {
1054   return base::StartsWith(codec_id, "dvh1.", base::CompareCase::SENSITIVE) ||
1055          base::StartsWith(codec_id, "dvhe.", base::CompareCase::SENSITIVE);
1056 }
1057
1058 // The specification for Dolby Vision codec id strings can be found in Dolby
1059 // Vision streams within the MPEG-DASH format:
1060 // https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolbyvisioninmpegdashspecification_v2_0_public_20190107.pdf
1061 bool ParseDolbyVisionCodecId(base::StringPiece codec_id,
1062                              VideoCodecProfile* profile,
1063                              uint8_t* level_idc) {
1064   if (!IsDolbyVisionAVCCodecId(codec_id) &&
1065       !IsDolbyVisionHEVCCodecId(codec_id)) {
1066     return false;
1067   }
1068
1069   const int kMaxDvCodecIdLength = 5     // FOURCC string
1070                                   + 1   // delimiting period
1071                                   + 2   // profile id as 2 digit string
1072                                   + 1   // delimiting period
1073                                   + 2;  // level id as 2 digit string.
1074
1075   if (codec_id.size() > kMaxDvCodecIdLength) {
1076     DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
1077     return false;
1078   }
1079
1080   std::vector<std::string> elem = base::SplitString(
1081       codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1082   DCHECK(elem[0] == "dvh1" || elem[0] == "dvhe" || elem[0] == "dva1" ||
1083          elem[0] == "dvav");
1084
1085   if (elem.size() != 3) {
1086     DVLOG(4) << __func__ << ": invalid dolby vision codec id " << codec_id;
1087     return false;
1088   }
1089
1090   // Profile string should be two digits.
1091   unsigned profile_id = 0;
1092   if (elem[1].size() != 2 || !base::StringToUint(elem[1], &profile_id) ||
1093       profile_id > 9) {
1094     DVLOG(4) << __func__ << ": invalid format or profile_id=" << elem[1];
1095     return false;
1096   }
1097
1098   // Only profiles 0, 4, 5, 7, 8 and 9 are valid. Profile 0 and 9 are encoded
1099   // based on AVC while profile 4, 5, 7 and 8 are based on HEVC.
1100   switch (profile_id) {
1101     case 0:
1102     case 9:
1103       if (!IsDolbyVisionAVCCodecId(codec_id)) {
1104         DVLOG(4) << __func__
1105                  << ": codec id is mismatched with profile_id=" << profile_id;
1106         return false;
1107       }
1108       if (profile_id == 0)
1109         *profile = DOLBYVISION_PROFILE0;
1110       else if (profile_id == 9)
1111         *profile = DOLBYVISION_PROFILE9;
1112       break;
1113 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1114     case 4:
1115     case 5:
1116     case 7:
1117     case 8:
1118       if (!IsDolbyVisionHEVCCodecId(codec_id)) {
1119         DVLOG(4) << __func__
1120                  << ": codec id is mismatched with profile_id=" << profile_id;
1121         return false;
1122       }
1123       if (profile_id == 4)
1124         *profile = DOLBYVISION_PROFILE4;
1125       else if (profile_id == 5)
1126         *profile = DOLBYVISION_PROFILE5;
1127       else if (profile_id == 7)
1128         *profile = DOLBYVISION_PROFILE7;
1129       else if (profile_id == 8)
1130         *profile = DOLBYVISION_PROFILE8;
1131       break;
1132 #endif
1133     default:
1134       DVLOG(4) << __func__
1135                << ": depecrated and not supported profile_id=" << profile_id;
1136       return false;
1137   }
1138
1139   // Level string should be two digits.
1140   unsigned level_id = 0;
1141   if (elem[2].size() != 2 || !base::StringToUint(elem[2], &level_id) ||
1142       level_id > 13 || level_id < 1) {
1143     DVLOG(4) << __func__ << ": invalid format level_id=" << elem[2];
1144     return false;
1145   }
1146
1147   *level_idc = level_id;
1148
1149   return true;
1150 }
1151 #endif
1152
1153 VideoCodec StringToVideoCodec(base::StringPiece codec_id) {
1154   VideoCodec codec = VideoCodec::kUnknown;
1155   VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
1156   uint8_t level = 0;
1157   VideoColorSpace color_space;
1158   ParseCodec(codec_id, codec, profile, level, color_space);
1159   return codec;
1160 }
1161
1162 void ParseCodec(base::StringPiece codec_id,
1163                 VideoCodec& codec,
1164                 VideoCodecProfile& profile,
1165                 uint8_t& level,
1166                 VideoColorSpace& color_space) {
1167   std::vector<std::string> elem = base::SplitString(
1168       codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1169   if (elem.empty()) {
1170     codec = VideoCodec::kUnknown;
1171     return;
1172   }
1173
1174   if (codec_id == "vp8" || codec_id == "vp8.0") {
1175     codec = VideoCodec::kVP8;
1176     return;
1177   }
1178   if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &color_space) ||
1179       ParseLegacyVp9CodecID(codec_id, &profile, &level)) {
1180     codec = VideoCodec::kVP9;
1181     return;
1182   }
1183
1184 #if BUILDFLAG(ENABLE_AV1_DECODER)
1185   if (ParseAv1CodecId(codec_id, &profile, &level, &color_space)) {
1186     codec = VideoCodec::kAV1;
1187     return;
1188   }
1189 #endif
1190
1191   if (codec_id == "theora") {
1192     codec = VideoCodec::kTheora;
1193     return;
1194   }
1195   if (ParseAVCCodecId(codec_id, &profile, &level)) {
1196     codec = VideoCodec::kH264;
1197     return;
1198   }
1199 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
1200   if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile,
1201                       &level)) {
1202     codec = VideoCodec::kH264;
1203     return;
1204   }
1205 #endif
1206 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1207   if (ParseHEVCCodecId(codec_id, &profile, &level)) {
1208     codec = VideoCodec::kHEVC;
1209     return;
1210   }
1211 #endif
1212 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1213   if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) {
1214     codec = VideoCodec::kDolbyVision;
1215     return;
1216   }
1217 #endif
1218   codec = VideoCodec::kUnknown;
1219 }
1220
1221 VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) {
1222   switch (profile) {
1223     case VIDEO_CODEC_PROFILE_UNKNOWN:
1224       return VideoCodec::kUnknown;
1225     case H264PROFILE_BASELINE:
1226     case H264PROFILE_MAIN:
1227     case H264PROFILE_EXTENDED:
1228     case H264PROFILE_HIGH:
1229     case H264PROFILE_HIGH10PROFILE:
1230     case H264PROFILE_HIGH422PROFILE:
1231     case H264PROFILE_HIGH444PREDICTIVEPROFILE:
1232     case H264PROFILE_SCALABLEBASELINE:
1233     case H264PROFILE_SCALABLEHIGH:
1234     case H264PROFILE_STEREOHIGH:
1235     case H264PROFILE_MULTIVIEWHIGH:
1236       return VideoCodec::kH264;
1237     case HEVCPROFILE_MAIN:
1238     case HEVCPROFILE_MAIN10:
1239     case HEVCPROFILE_MAIN_STILL_PICTURE:
1240     case HEVCPROFILE_REXT:
1241     case HEVCPROFILE_HIGH_THROUGHPUT:
1242     case HEVCPROFILE_MULTIVIEW_MAIN:
1243     case HEVCPROFILE_SCALABLE_MAIN:
1244     case HEVCPROFILE_3D_MAIN:
1245     case HEVCPROFILE_SCREEN_EXTENDED:
1246     case HEVCPROFILE_SCALABLE_REXT:
1247     case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
1248       return VideoCodec::kHEVC;
1249     case VP8PROFILE_ANY:
1250       return VideoCodec::kVP8;
1251     case VP9PROFILE_PROFILE0:
1252     case VP9PROFILE_PROFILE1:
1253     case VP9PROFILE_PROFILE2:
1254     case VP9PROFILE_PROFILE3:
1255       return VideoCodec::kVP9;
1256     case DOLBYVISION_PROFILE0:
1257     case DOLBYVISION_PROFILE4:
1258     case DOLBYVISION_PROFILE5:
1259     case DOLBYVISION_PROFILE7:
1260     case DOLBYVISION_PROFILE8:
1261     case DOLBYVISION_PROFILE9:
1262       return VideoCodec::kDolbyVision;
1263     case THEORAPROFILE_ANY:
1264       return VideoCodec::kTheora;
1265     case AV1PROFILE_PROFILE_MAIN:
1266     case AV1PROFILE_PROFILE_HIGH:
1267     case AV1PROFILE_PROFILE_PRO:
1268       return VideoCodec::kAV1;
1269     // TODO(crbugs.com/1417910): Update to VideoCodec::kVVC when
1270     // the production VVC decoder is enabled and corresponding
1271     // enum is allowed to be added.
1272     case VVCPROFILE_MAIN10:
1273     case VVCPROFILE_MAIN12:
1274     case VVCPROFILE_MAIN12_INTRA:
1275     case VVCPROIFLE_MULTILAYER_MAIN10:
1276     case VVCPROFILE_MAIN10_444:
1277     case VVCPROFILE_MAIN12_444:
1278     case VVCPROFILE_MAIN16_444:
1279     case VVCPROFILE_MAIN12_444_INTRA:
1280     case VVCPROFILE_MAIN16_444_INTRA:
1281     case VVCPROFILE_MULTILAYER_MAIN10_444:
1282     case VVCPROFILE_MAIN10_STILL_PICTURE:
1283     case VVCPROFILE_MAIN12_STILL_PICTURE:
1284     case VVCPROFILE_MAIN10_444_STILL_PICTURE:
1285     case VVCPROFILE_MAIN12_444_STILL_PICTURE:
1286     case VVCPROFILE_MAIN16_444_STILL_PICTURE:
1287       return VideoCodec::kUnknown;
1288   }
1289 }
1290
1291 std::ostream& operator<<(std::ostream& os, const VideoCodec& codec) {
1292   return os << GetCodecName(codec);
1293 }
1294
1295 }  // namespace media