Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/mime_util_internal.h" | 5 #include "media/base/mime_util_internal.h" |
| 6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. | 142 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. |
| 143 // Level_idc represents the standard level represented as decimal number | 143 // Level_idc represents the standard level represented as decimal number |
| 144 // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2 | 144 // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2 |
| 145 return ((level_idc >= 10 && level_idc <= 13) || | 145 return ((level_idc >= 10 && level_idc <= 13) || |
| 146 (level_idc >= 20 && level_idc <= 22) || | 146 (level_idc >= 20 && level_idc <= 22) || |
| 147 (level_idc >= 30 && level_idc <= 32) || | 147 (level_idc >= 30 && level_idc <= 32) || |
| 148 (level_idc >= 40 && level_idc <= 42) || | 148 (level_idc >= 40 && level_idc <= 42) || |
| 149 (level_idc >= 50 && level_idc <= 51)); | 149 (level_idc >= 50 && level_idc <= 51)); |
| 150 } | 150 } |
| 151 | 151 |
| 152 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 153 // ISO/IEC FDIS 14496-15 standard section E.3 describes the syntax of codec ids | |
| 154 // reserved for HEVC. According to that spec HEVC codec id must start with | |
| 155 // either "hev1." or "hvc1.". We don't yet support full parsing of HEVC codec | |
| 156 // ids, but since no other codec id starts with those string we'll just treat | |
| 157 // any string starting with "hev1." or "hvc1." as valid HEVC codec ids. | |
| 158 // crbug.com/482761 | |
| 159 static bool ParseHEVCCodecID(const std::string& codec_id, | |
| 160 MimeUtil::Codec* codec, | |
| 161 bool* is_ambiguous) { | |
| 162 if (base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) || | |
| 163 base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) { | |
| 164 *codec = MimeUtil::HEVC_MAIN; | |
| 165 | |
| 166 // TODO(servolk): Full HEVC codec id parsing is not implemented yet (see | |
| 167 // crbug.com/482761). So treat HEVC codec ids as ambiguous for now. | |
| 168 *is_ambiguous = true; | |
| 169 | |
| 170 // TODO(servolk): Most HEVC codec ids are treated as ambiguous (see above), | |
| 171 // but we need to recognize at least one valid unambiguous HEVC codec id, | |
| 172 // which is added into kMP4VideoCodecsExpression. We need it to be | |
| 173 // unambiguous to avoid DCHECK(!is_ambiguous) in InitializeMimeTypeMaps. We | |
| 174 // also use these in unit tests (see | |
| 175 // content/browser/media/media_canplaytype_browsertest.cc). | |
| 176 // Remove this workaround after crbug.com/482761 is fixed. | |
| 177 if (codec_id == "hev1.1.6.L93.B0" || codec_id == "hvc1.1.6.L93.B0") { | |
| 178 *is_ambiguous = false; | |
| 179 } | |
| 180 | |
| 181 return true; | |
| 182 } | |
| 183 | |
| 184 return false; | |
| 185 } | |
| 186 #endif | |
| 187 | |
| 188 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { | 152 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
| 189 #if defined(OS_ANDROID) | 153 #if defined(OS_ANDROID) |
| 190 platform_info_.is_unified_media_pipeline_enabled = | 154 platform_info_.is_unified_media_pipeline_enabled = |
| 191 IsUnifiedMediaPipelineEnabled(); | 155 IsUnifiedMediaPipelineEnabled(); |
| 192 // When the unified media pipeline is enabled, we need support for both GPU | 156 // When the unified media pipeline is enabled, we need support for both GPU |
| 193 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). | 157 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). |
| 194 // When the Android pipeline is used, we only need access to MediaCodec. | 158 // When the Android pipeline is used, we only need access to MediaCodec. |
| 195 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); | 159 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); |
| 196 platform_info_.has_platform_vp8_decoder = | 160 platform_info_.has_platform_vp8_decoder = |
| 197 MediaCodecUtil::IsVp8DecoderAvailable(); | 161 MediaCodecUtil::IsVp8DecoderAvailable(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 CodecSet mp4_audio_codecs(aac); | 255 CodecSet mp4_audio_codecs(aac); |
| 292 mp4_audio_codecs.insert(MP3); | 256 mp4_audio_codecs.insert(MP3); |
| 293 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 257 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 294 mp4_audio_codecs.insert(AC3); | 258 mp4_audio_codecs.insert(AC3); |
| 295 mp4_audio_codecs.insert(EAC3); | 259 mp4_audio_codecs.insert(EAC3); |
| 296 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 260 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 297 | 261 |
| 298 CodecSet mp4_video_codecs; | 262 CodecSet mp4_video_codecs; |
| 299 mp4_video_codecs.insert(H264); | 263 mp4_video_codecs.insert(H264); |
| 300 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 264 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 301 mp4_video_codecs.insert(HEVC_MAIN); | 265 mp4_video_codecs.insert(HEVC); |
| 302 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) | 266 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 303 CodecSet mp4_codecs(mp4_audio_codecs); | 267 CodecSet mp4_codecs(mp4_audio_codecs); |
| 304 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); | 268 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); |
| 305 #endif // defined(USE_PROPRIETARY_CODECS) | 269 #endif // defined(USE_PROPRIETARY_CODECS) |
| 306 | 270 |
| 307 AddContainerWithCodecs("audio/wav", wav_codecs, false); | 271 AddContainerWithCodecs("audio/wav", wav_codecs, false); |
| 308 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); | 272 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); |
| 309 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); | 273 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); |
| 310 DCHECK(!webm_video_codecs.empty()); | 274 DCHECK(!webm_video_codecs.empty()); |
| 311 AddContainerWithCodecs("video/webm", webm_codecs, false); | 275 AddContainerWithCodecs("video/webm", webm_codecs, false); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 | 474 |
| 511 case H264: | 475 case H264: |
| 512 // The unified pipeline requires platform support for h264. | 476 // The unified pipeline requires platform support for h264. |
| 513 if (platform_info.is_unified_media_pipeline_enabled) | 477 if (platform_info.is_unified_media_pipeline_enabled) |
| 514 return platform_info.has_platform_decoders; | 478 return platform_info.has_platform_decoders; |
| 515 | 479 |
| 516 // When MediaPlayer or MediaCodec is used, h264 is always supported. | 480 // When MediaPlayer or MediaCodec is used, h264 is always supported. |
| 517 DCHECK(!is_encrypted || platform_info.has_platform_decoders); | 481 DCHECK(!is_encrypted || platform_info.has_platform_decoders); |
| 518 return true; | 482 return true; |
| 519 | 483 |
| 520 case HEVC_MAIN: | 484 case HEVC: |
| 521 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 485 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 522 if (platform_info.is_unified_media_pipeline_enabled && | 486 if (platform_info.is_unified_media_pipeline_enabled && |
| 523 !platform_info.has_platform_decoders) { | 487 !platform_info.has_platform_decoders) { |
| 524 return false; | 488 return false; |
| 525 } | 489 } |
| 526 | 490 |
| 527 #if defined(OS_ANDROID) | 491 #if defined(OS_ANDROID) |
| 528 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to | 492 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to |
| 529 // http://developer.android.com/reference/android/media/MediaFormat.html | 493 // http://developer.android.com/reference/android/media/MediaFormat.html |
| 530 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; | 494 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 string_to_codec_map_.find(codec_id); | 532 string_to_codec_map_.find(codec_id); |
| 569 if (itr != string_to_codec_map_.end()) { | 533 if (itr != string_to_codec_map_.end()) { |
| 570 *codec = itr->second.codec; | 534 *codec = itr->second.codec; |
| 571 *is_ambiguous = itr->second.is_ambiguous; | 535 *is_ambiguous = itr->second.is_ambiguous; |
| 572 return true; | 536 return true; |
| 573 } | 537 } |
| 574 | 538 |
| 575 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 539 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
| 576 // either H.264 or HEVC/H.265 codec ID because currently those are the only | 540 // either H.264 or HEVC/H.265 codec ID because currently those are the only |
| 577 // ones that are not added to the |string_to_codec_map_| and require parsing. | 541 // ones that are not added to the |string_to_codec_map_| and require parsing. |
| 578 | |
| 579 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 580 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { | |
| 581 return true; | |
| 582 } | |
| 583 #endif | |
| 584 | |
| 585 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 542 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| 586 uint8_t level_idc = 0; | 543 uint8_t level_idc = 0; |
| 544 | |
| 587 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { | 545 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { |
| 588 *codec = MimeUtil::H264; | 546 *codec = MimeUtil::H264; |
| 589 switch (profile) { | 547 switch (profile) { |
| 590 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder | 548 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder |
| 591 // which is not available on Android, or if FFMPEG is not used. | 549 // which is not available on Android, or if FFMPEG is not used. |
| 592 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) | 550 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) |
| 593 case H264PROFILE_HIGH10PROFILE: | 551 case H264PROFILE_HIGH10PROFILE: |
| 594 if (is_encrypted) { | 552 if (is_encrypted) { |
| 595 // FFmpeg is not generally used for encrypted videos, so we do not | 553 // FFmpeg is not generally used for encrypted videos, so we do not |
| 596 // know whether 10-bit is supported. | 554 // know whether 10-bit is supported. |
| 597 *is_ambiguous = true; | 555 *is_ambiguous = true; |
| 598 break; | 556 break; |
| 599 } | 557 } |
| 600 // Fall through. | 558 // Fall through. |
| 601 #endif | 559 #endif |
| 602 | 560 |
| 603 case H264PROFILE_BASELINE: | 561 case H264PROFILE_BASELINE: |
| 604 case H264PROFILE_MAIN: | 562 case H264PROFILE_MAIN: |
| 605 case H264PROFILE_HIGH: | 563 case H264PROFILE_HIGH: |
| 606 *is_ambiguous = !IsValidH264Level(level_idc); | 564 *is_ambiguous = !IsValidH264Level(level_idc); |
| 607 break; | 565 break; |
| 608 default: | 566 default: |
| 609 *is_ambiguous = true; | 567 *is_ambiguous = true; |
| 610 } | 568 } |
| 611 return true; | 569 return true; |
| 612 } | 570 } |
| 613 | 571 |
| 572 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 573 if (ParseHEVCCodecId(codec_id, &profile, &level_idc)) { | |
| 574 // TODO(servolk): Set |is_ambiguous| to false for now to make sure | |
| 575 // CanPlayType result is 'probably' and not 'maybe', since that's what unit | |
| 576 // tests expect. We'll need to add platform level checks to ensure that the | |
|
ddorwin
2016/04/07 20:29:46
What tests expect 'probably'? Can't we just update
servolk
2016/04/07 20:44:03
The MediaCanPlayTypeTest.CodecSupportTest_HEVCVari
ddorwin
2016/04/08 20:43:24
If there are profiles, level, etc. combinations th
servolk
2016/04/08 22:11:45
Done.
| |
| 577 // given combination of HEVC profile and level is actually supported. | |
| 578 *is_ambiguous = false; | |
| 579 *codec = MimeUtil::HEVC; | |
| 580 return true; | |
| 581 } | |
| 582 #endif | |
| 583 | |
| 614 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | 584 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; |
| 615 return false; | 585 return false; |
| 616 } | 586 } |
| 617 | 587 |
| 618 bool MimeUtil::IsCodecSupported(Codec codec, | 588 bool MimeUtil::IsCodecSupported(Codec codec, |
| 619 const std::string& mime_type_lower_case, | 589 const std::string& mime_type_lower_case, |
| 620 bool is_encrypted) const { | 590 bool is_encrypted) const { |
| 621 DCHECK_NE(codec, INVALID_CODEC); | 591 DCHECK_NE(codec, INVALID_CODEC); |
| 622 | 592 |
| 623 #if defined(OS_ANDROID) | 593 #if defined(OS_ANDROID) |
| 624 if (!IsCodecSupportedOnPlatform(codec, mime_type_lower_case, is_encrypted, | 594 if (!IsCodecSupportedOnPlatform(codec, mime_type_lower_case, is_encrypted, |
| 625 platform_info_)) { | 595 platform_info_)) { |
| 626 return false; | 596 return false; |
| 627 } | 597 } |
| 628 #endif | 598 #endif |
| 629 | 599 |
| 630 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); | 600 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); |
| 631 } | 601 } |
| 632 | 602 |
| 633 bool MimeUtil::IsCodecProprietary(Codec codec) const { | 603 bool MimeUtil::IsCodecProprietary(Codec codec) const { |
| 634 switch (codec) { | 604 switch (codec) { |
| 635 case INVALID_CODEC: | 605 case INVALID_CODEC: |
| 636 case AC3: | 606 case AC3: |
| 637 case EAC3: | 607 case EAC3: |
| 638 case MP3: | 608 case MP3: |
| 639 case MPEG2_AAC: | 609 case MPEG2_AAC: |
| 640 case MPEG4_AAC: | 610 case MPEG4_AAC: |
| 641 case H264: | 611 case H264: |
| 642 case HEVC_MAIN: | 612 case HEVC: |
| 643 return true; | 613 return true; |
| 644 | 614 |
| 645 case PCM: | 615 case PCM: |
| 646 case VORBIS: | 616 case VORBIS: |
| 647 case OPUS: | 617 case OPUS: |
| 648 case VP8: | 618 case VP8: |
| 649 case VP9: | 619 case VP9: |
| 650 case THEORA: | 620 case THEORA: |
| 651 return false; | 621 return false; |
| 652 } | 622 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 675 const std::string& mime_type_lower_case, | 645 const std::string& mime_type_lower_case, |
| 676 bool is_encrypted) const { | 646 bool is_encrypted) const { |
| 677 Codec default_codec = Codec::INVALID_CODEC; | 647 Codec default_codec = Codec::INVALID_CODEC; |
| 678 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 648 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 679 return false; | 649 return false; |
| 680 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 650 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 681 } | 651 } |
| 682 | 652 |
| 683 } // namespace internal | 653 } // namespace internal |
| 684 } // namespace media | 654 } // namespace media |
| OLD | NEW |