OLD | NEW |
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" |
11 | 11 |
12 namespace media { | 12 namespace media { |
13 | 13 |
14 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c | 14 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c |
15 std::string GetCodecName(VideoCodec codec) { | 15 std::string GetCodecName(VideoCodec codec) { |
16 switch (codec) { | 16 switch (codec) { |
17 case kUnknownVideoCodec: | 17 case kUnknownVideoCodec: |
18 return "unknown"; | 18 return "unknown"; |
19 case kCodecH264: | 19 case kCodecH264: |
20 return "h264"; | 20 return "h264"; |
21 case kCodecHEVC: | 21 case kCodecHEVC: |
22 return "hevc"; | 22 return "hevc"; |
| 23 case kCodecDolbyVision: |
| 24 return "dolbyvision"; |
23 case kCodecVC1: | 25 case kCodecVC1: |
24 return "vc1"; | 26 return "vc1"; |
25 case kCodecMPEG2: | 27 case kCodecMPEG2: |
26 return "mpeg2video"; | 28 return "mpeg2video"; |
27 case kCodecMPEG4: | 29 case kCodecMPEG4: |
28 return "mpeg4"; | 30 return "mpeg4"; |
29 case kCodecTheora: | 31 case kCodecTheora: |
30 return "theora"; | 32 return "theora"; |
31 case kCodecVP8: | 33 case kCodecVP8: |
32 return "vp8"; | 34 return "vp8"; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 case VP8PROFILE_ANY: | 74 case VP8PROFILE_ANY: |
73 return "vp8"; | 75 return "vp8"; |
74 case VP9PROFILE_PROFILE0: | 76 case VP9PROFILE_PROFILE0: |
75 return "vp9 profile0"; | 77 return "vp9 profile0"; |
76 case VP9PROFILE_PROFILE1: | 78 case VP9PROFILE_PROFILE1: |
77 return "vp9 profile1"; | 79 return "vp9 profile1"; |
78 case VP9PROFILE_PROFILE2: | 80 case VP9PROFILE_PROFILE2: |
79 return "vp9 profile2"; | 81 return "vp9 profile2"; |
80 case VP9PROFILE_PROFILE3: | 82 case VP9PROFILE_PROFILE3: |
81 return "vp9 profile3"; | 83 return "vp9 profile3"; |
| 84 case DOLBYVISION_PROFILE0: |
| 85 return "dolby vision profile 0"; |
| 86 case DOLBYVISION_PROFILE4: |
| 87 return "dolby vision profile 4"; |
| 88 case DOLBYVISION_PROFILE5: |
| 89 return "dolby vision profile 5"; |
| 90 case DOLBYVISION_PROFILE7: |
| 91 return "dolby vision profile 7"; |
82 } | 92 } |
83 NOTREACHED(); | 93 NOTREACHED(); |
84 return ""; | 94 return ""; |
85 } | 95 } |
86 | 96 |
87 bool ParseNewStyleVp9CodecID(const std::string& codec_id, | 97 bool ParseNewStyleVp9CodecID(const std::string& codec_id, |
88 VideoCodecProfile* profile, | 98 VideoCodecProfile* profile, |
89 uint8_t* level_idc) { | 99 uint8_t* level_idc) { |
90 std::vector<std::string> fields = base::SplitString( | 100 std::vector<std::string> fields = base::SplitString( |
91 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 101 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i]; | 422 DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i]; |
413 return false; | 423 return false; |
414 } | 424 } |
415 constraint_flags[i - 4] = constr_byte; | 425 constraint_flags[i - 4] = constr_byte; |
416 } | 426 } |
417 | 427 |
418 return true; | 428 return true; |
419 } | 429 } |
420 #endif | 430 #endif |
421 | 431 |
| 432 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) |
| 433 // The specification for Dolby Vision codec id strings can be found in Dolby |
| 434 // Vision streams within the MPEG-DASH format. |
| 435 bool ParseDolbyVisionCodecId(const std::string& codec_id, |
| 436 VideoCodecProfile* profile, |
| 437 uint8_t* level_idc) { |
| 438 if (!base::StartsWith(codec_id, "dvh1.", base::CompareCase::SENSITIVE) && |
| 439 !base::StartsWith(codec_id, "dvhe.", base::CompareCase::SENSITIVE) && |
| 440 !base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) && |
| 441 !base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE)) { |
| 442 return false; |
| 443 } |
| 444 |
| 445 const int kMaxDvCodecIdLength = 5 // FOURCC string |
| 446 + 1 // delimiting period |
| 447 + 2 // profile id as 2 digit string |
| 448 + 1 // delimiting period |
| 449 + 2; // level id as 2 digit string. |
| 450 |
| 451 if (codec_id.size() > kMaxDvCodecIdLength) { |
| 452 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")"; |
| 453 return false; |
| 454 } |
| 455 |
| 456 std::vector<std::string> elem = base::SplitString( |
| 457 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 458 DCHECK(elem[0] == "dvh1" || elem[0] == "dvhe" || elem[0] == "dva1" || |
| 459 elem[0] == "dvav"); |
| 460 |
| 461 if (elem.size() != 3) { |
| 462 DVLOG(4) << __func__ << ": invalid dolby vision codec id " << codec_id; |
| 463 return false; |
| 464 } |
| 465 |
| 466 unsigned profile_id = 0; |
| 467 if (!base::StringToUint(elem[1], &profile_id) || profile_id > 7) { |
| 468 DVLOG(4) << __func__ << ": invalid profile_id=" << elem[1]; |
| 469 return false; |
| 470 } |
| 471 |
| 472 // Only profiles 0, 4, 5 and 7 are valid. Profile 0 is encoded based on AVC |
| 473 // while profile 4, 5 and 7 are based on HEVC. |
| 474 switch (profile_id) { |
| 475 case 0: |
| 476 *profile = DOLBYVISION_PROFILE0; |
| 477 break; |
| 478 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 479 case 4: |
| 480 *profile = DOLBYVISION_PROFILE4; |
| 481 break; |
| 482 case 5: |
| 483 *profile = DOLBYVISION_PROFILE5; |
| 484 break; |
| 485 case 7: |
| 486 *profile = DOLBYVISION_PROFILE7; |
| 487 break; |
| 488 #endif |
| 489 default: |
| 490 DVLOG(4) << __func__ |
| 491 << ": depecrated and not supported profile_id=" << profile_id; |
| 492 return false; |
| 493 } |
| 494 |
| 495 unsigned level_id = 0; |
| 496 if (!base::StringToUint(elem[2], &level_id) || level_id > 9 || level_id < 1) { |
| 497 DVLOG(4) << __func__ << ": invalid level_id=" << elem[2]; |
| 498 return false; |
| 499 } |
| 500 |
| 501 *level_idc = level_id; |
| 502 |
| 503 return true; |
| 504 } |
| 505 #endif |
| 506 |
422 VideoCodec StringToVideoCodec(const std::string& codec_id) { | 507 VideoCodec StringToVideoCodec(const std::string& codec_id) { |
423 std::vector<std::string> elem = base::SplitString( | 508 std::vector<std::string> elem = base::SplitString( |
424 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 509 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
425 if (elem.empty()) | 510 if (elem.empty()) |
426 return kUnknownVideoCodec; | 511 return kUnknownVideoCodec; |
427 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 512 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
428 uint8_t level = 0; | 513 uint8_t level = 0; |
429 if (codec_id == "vp8" || codec_id == "vp8.0") | 514 if (codec_id == "vp8" || codec_id == "vp8.0") |
430 return kCodecVP8; | 515 return kCodecVP8; |
431 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level) || | 516 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level) || |
432 ParseLegacyVp9CodecID(codec_id, &profile, &level)) { | 517 ParseLegacyVp9CodecID(codec_id, &profile, &level)) { |
433 return kCodecVP9; | 518 return kCodecVP9; |
434 } | 519 } |
435 if (codec_id == "theora") | 520 if (codec_id == "theora") |
436 return kCodecTheora; | 521 return kCodecTheora; |
437 if (ParseAVCCodecId(codec_id, &profile, &level)) | 522 if (ParseAVCCodecId(codec_id, &profile, &level)) |
438 return kCodecH264; | 523 return kCodecH264; |
439 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 524 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
440 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level)) | 525 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile, &level)) |
441 return kCodecH264; | 526 return kCodecH264; |
442 #endif | 527 #endif |
443 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 528 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
444 if (ParseHEVCCodecId(codec_id, &profile, &level)) | 529 if (ParseHEVCCodecId(codec_id, &profile, &level)) |
445 return kCodecHEVC; | 530 return kCodecHEVC; |
446 #endif | 531 #endif |
| 532 #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) |
| 533 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) |
| 534 return kCodecDolbyVision; |
| 535 #endif |
447 return kUnknownVideoCodec; | 536 return kUnknownVideoCodec; |
448 } | 537 } |
449 | 538 |
450 } // namespace media | 539 } // namespace media |
OLD | NEW |