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" |
| 11 #include "media/base/media.h" | |
| 11 #include "media/media_features.h" | 12 #include "media/media_features.h" |
| 12 | 13 |
| 13 #if defined(OS_ANDROID) | 14 #if defined(OS_ANDROID) |
| 14 #include "base/android/build_info.h" | 15 #include "base/android/build_info.h" |
| 16 #include "media/base/android/media_codec_util.h" | |
| 15 #endif | 17 #endif |
| 16 | 18 |
| 17 namespace media { | 19 namespace media { |
| 18 namespace internal { | 20 namespace internal { |
| 19 | 21 |
| 20 enum MediaFormatType { COMMON, PROPRIETARY }; | 22 enum MediaFormatType { COMMON, PROPRIETARY }; |
| 21 | 23 |
| 22 struct MediaFormat { | 24 struct MediaFormat { |
| 23 const char* const mime_type; | 25 const char* const mime_type; |
| 24 MediaFormatType format_type; | 26 MediaFormatType format_type; |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 } | 312 } |
| 311 | 313 |
| 312 return true; | 314 return true; |
| 313 } | 315 } |
| 314 | 316 |
| 315 return false; | 317 return false; |
| 316 } | 318 } |
| 317 #endif | 319 #endif |
| 318 | 320 |
| 319 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { | 321 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
| 322 #if defined(OS_ANDROID) | |
| 323 platform_info_.has_platform_decoder = HasPlatformDecoderSupport(); | |
| 324 platform_info_.has_unified_media_pipeline = IsUnifiedMediaPipelineEnabled(); | |
| 325 platform_info_.has_opus = MediaCodecUtil::PlatformHasOpusSupport(); | |
| 326 platform_info_.has_vp8 = MediaCodecUtil::IsVp8Blacklisted(); | |
|
ddorwin
2016/02/17 21:18:39
!
ddorwin
2016/02/17 21:18:39
VP8 is different from Opus and VP9. The VP8 blackl
DaleCurtis
2016/02/18 03:58:09
Done and changed to has_encrypted_vp8 since that's
| |
| 327 platform_info_.has_vp9 = MediaCodecUtil::PlatformHasVp9Support(); | |
| 328 #endif | |
| 329 | |
| 320 InitializeMimeTypeMaps(); | 330 InitializeMimeTypeMaps(); |
| 321 } | 331 } |
| 322 | 332 |
| 323 SupportsType MimeUtil::AreSupportedCodecs( | 333 SupportsType MimeUtil::AreSupportedCodecs( |
| 324 const CodecSet& supported_codecs, | 334 const CodecSet& supported_codecs, |
| 325 const std::vector<std::string>& codecs) const { | 335 const std::vector<std::string>& codecs, |
| 336 const std::string& mime_type_lower_case, | |
| 337 bool is_encrypted) const { | |
| 326 DCHECK(!supported_codecs.empty()); | 338 DCHECK(!supported_codecs.empty()); |
| 327 DCHECK(!codecs.empty()); | 339 DCHECK(!codecs.empty()); |
| 328 | 340 |
| 329 SupportsType result = IsSupported; | 341 SupportsType result = IsSupported; |
| 330 for (size_t i = 0; i < codecs.size(); ++i) { | 342 for (size_t i = 0; i < codecs.size(); ++i) { |
| 331 bool is_ambiguous = true; | 343 bool is_ambiguous = true; |
| 332 Codec codec = INVALID_CODEC; | 344 Codec codec = INVALID_CODEC; |
| 333 if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) | 345 if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) |
| 334 return IsNotSupported; | 346 return IsNotSupported; |
| 335 | 347 |
| 336 if (!IsCodecSupported(codec) || | 348 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || |
| 337 supported_codecs.find(codec) == supported_codecs.end()) { | 349 supported_codecs.find(codec) == supported_codecs.end()) { |
| 338 return IsNotSupported; | 350 return IsNotSupported; |
| 339 } | 351 } |
| 340 | 352 |
| 341 if (is_ambiguous) | 353 if (is_ambiguous) |
| 342 result = MayBeSupported; | 354 result = MayBeSupported; |
| 343 } | 355 } |
| 344 | 356 |
| 345 return result; | 357 return result; |
| 346 } | 358 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 for (std::vector<std::string>::iterator it = codecs_out->begin(); | 415 for (std::vector<std::string>::iterator it = codecs_out->begin(); |
| 404 it != codecs_out->end(); ++it) { | 416 it != codecs_out->end(); ++it) { |
| 405 size_t found = it->find_first_of('.'); | 417 size_t found = it->find_first_of('.'); |
| 406 if (found != std::string::npos) | 418 if (found != std::string::npos) |
| 407 it->resize(found); | 419 it->resize(found); |
| 408 } | 420 } |
| 409 } | 421 } |
| 410 | 422 |
| 411 SupportsType MimeUtil::IsSupportedMediaFormat( | 423 SupportsType MimeUtil::IsSupportedMediaFormat( |
| 412 const std::string& mime_type, | 424 const std::string& mime_type, |
| 413 const std::vector<std::string>& codecs) const { | 425 const std::vector<std::string>& codecs, |
| 426 bool is_encrypted) const { | |
| 414 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); | 427 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); |
| 415 MediaFormatMappings::const_iterator it_media_format_map = | 428 MediaFormatMappings::const_iterator it_media_format_map = |
| 416 media_format_map_.find(mime_type_lower_case); | 429 media_format_map_.find(mime_type_lower_case); |
| 417 if (it_media_format_map == media_format_map_.end()) | 430 if (it_media_format_map == media_format_map_.end()) |
| 418 return IsNotSupported; | 431 return IsNotSupported; |
| 419 | 432 |
| 420 if (it_media_format_map->second.empty()) { | 433 if (it_media_format_map->second.empty()) { |
| 421 // We get here if the mimetype does not expect a codecs parameter. | 434 // We get here if the mimetype does not expect a codecs parameter. |
| 422 return (codecs.empty() && | 435 return (codecs.empty() && IsDefaultCodecSupportedLowerCase( |
| 423 IsDefaultCodecSupportedLowerCase(mime_type_lower_case)) | 436 mime_type_lower_case, is_encrypted)) |
| 424 ? IsSupported | 437 ? IsSupported |
| 425 : IsNotSupported; | 438 : IsNotSupported; |
| 426 } | 439 } |
| 427 | 440 |
| 428 if (codecs.empty()) { | 441 if (codecs.empty()) { |
| 429 // We get here if the mimetype expects to get a codecs parameter, | 442 // We get here if the mimetype expects to get a codecs parameter, |
| 430 // but didn't get one. If |mime_type_lower_case| does not have a default | 443 // but didn't get one. If |mime_type_lower_case| does not have a default |
| 431 // codec the best we can do is say "maybe" because we don't have enough | 444 // codec the best we can do is say "maybe" because we don't have enough |
| 432 // information. | 445 // information. |
| 433 Codec default_codec = INVALID_CODEC; | 446 Codec default_codec = INVALID_CODEC; |
| 434 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 447 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 435 return MayBeSupported; | 448 return MayBeSupported; |
| 436 | 449 |
| 437 return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported; | 450 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted) |
| 451 ? IsSupported | |
| 452 : IsNotSupported; | |
| 438 } | 453 } |
| 439 | 454 |
| 440 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 455 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
| 441 if (mime_type_lower_case == "video/mp2t") { | 456 if (mime_type_lower_case == "video/mp2t") { |
| 442 std::vector<std::string> codecs_to_check; | 457 std::vector<std::string> codecs_to_check; |
| 443 for (const auto& codec_id : codecs) { | 458 for (const auto& codec_id : codecs) { |
| 444 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); | 459 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); |
| 445 } | 460 } |
| 446 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check); | 461 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, |
| 462 mime_type_lower_case, is_encrypted); | |
| 447 } | 463 } |
| 448 #endif | 464 #endif |
| 449 | 465 |
| 450 return AreSupportedCodecs(it_media_format_map->second, codecs); | 466 return AreSupportedCodecs(it_media_format_map->second, codecs, |
| 467 mime_type_lower_case, is_encrypted); | |
| 451 } | 468 } |
| 452 | 469 |
| 453 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { | 470 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { |
| 454 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) | 471 for (size_t i = 0; i < arraysize(kFormatCodecMappings); ++i) |
| 455 if (kFormatCodecMappings[i].format_type == PROPRIETARY) | 472 if (kFormatCodecMappings[i].format_type == PROPRIETARY) |
| 456 media_format_map_.erase(kFormatCodecMappings[i].mime_type); | 473 media_format_map_.erase(kFormatCodecMappings[i].mime_type); |
| 457 allow_proprietary_codecs_ = false; | 474 allow_proprietary_codecs_ = false; |
| 458 } | 475 } |
| 459 | 476 |
| 477 void MimeUtil::SetPlatformCodecInfoForTests(const PlatformCodecInfo& info) { | |
|
ddorwin
2016/02/17 21:18:38
#ifdef
DaleCurtis
2016/02/18 03:58:08
See previous comment.
| |
| 478 platform_info_ = info; | |
| 479 } | |
| 480 | |
| 460 bool MimeUtil::StringToCodec(const std::string& codec_id, | 481 bool MimeUtil::StringToCodec(const std::string& codec_id, |
| 461 Codec* codec, | 482 Codec* codec, |
| 462 bool* is_ambiguous) const { | 483 bool* is_ambiguous) const { |
| 463 StringToCodecMappings::const_iterator itr = | 484 StringToCodecMappings::const_iterator itr = |
| 464 string_to_codec_map_.find(codec_id); | 485 string_to_codec_map_.find(codec_id); |
| 465 if (itr != string_to_codec_map_.end()) { | 486 if (itr != string_to_codec_map_.end()) { |
| 466 *codec = itr->second.codec; | 487 *codec = itr->second.codec; |
| 467 *is_ambiguous = itr->second.is_ambiguous; | 488 *is_ambiguous = itr->second.is_ambiguous; |
| 468 return true; | 489 return true; |
| 469 } | 490 } |
| 470 | 491 |
| 471 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 492 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
| 472 // either H.264 or HEVC/H.265 codec ID because currently those are the only | 493 // either H.264 or HEVC/H.265 codec ID because currently those are the only |
| 473 // ones that are not added to the |string_to_codec_map_| and require parsing. | 494 // ones that are not added to the |string_to_codec_map_| and require parsing. |
| 474 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 495 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 475 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { | 496 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { |
| 476 return true; | 497 return true; |
| 477 } | 498 } |
| 478 #endif | 499 #endif |
| 479 return ParseH264CodecID(codec_id, codec, is_ambiguous); | 500 return ParseH264CodecID(codec_id, codec, is_ambiguous); |
| 480 } | 501 } |
| 481 | 502 |
| 482 bool MimeUtil::IsCodecSupported(Codec codec) const { | 503 bool MimeUtil::IsCodecSupported(Codec codec, |
| 504 const std::string& mime_type_lower_case, | |
| 505 bool is_encrypted) const { | |
| 483 DCHECK_NE(codec, INVALID_CODEC); | 506 DCHECK_NE(codec, INVALID_CODEC); |
| 484 | 507 |
| 485 #if defined(OS_ANDROID) | 508 #if defined(OS_ANDROID) |
| 486 if (!IsCodecSupportedOnAndroid(codec)) | 509 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted)) |
| 487 return false; | 510 return false; |
| 488 #endif | 511 #endif |
| 489 | 512 |
| 490 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); | 513 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); |
| 491 } | 514 } |
| 492 | 515 |
| 493 bool MimeUtil::IsCodecProprietary(Codec codec) const { | 516 bool MimeUtil::IsCodecProprietary(Codec codec) const { |
| 494 switch (codec) { | 517 switch (codec) { |
| 495 case INVALID_CODEC: | 518 case INVALID_CODEC: |
| 496 case AC3: | 519 case AC3: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 } | 553 } |
| 531 | 554 |
| 532 if (mime_type_lower_case == "audio/aac") { | 555 if (mime_type_lower_case == "audio/aac") { |
| 533 *default_codec = MimeUtil::MPEG4_AAC_LC; | 556 *default_codec = MimeUtil::MPEG4_AAC_LC; |
| 534 return true; | 557 return true; |
| 535 } | 558 } |
| 536 | 559 |
| 537 return false; | 560 return false; |
| 538 } | 561 } |
| 539 | 562 |
| 540 bool MimeUtil::IsDefaultCodecSupportedLowerCase( | 563 bool MimeUtil::IsDefaultCodecSupportedLowerCase( |
|
ddorwin
2016/02/17 21:18:39
Unrelated to this CL:
These ...DefaultCodec...Lowe
DaleCurtis
2016/02/18 03:58:09
Acknowledged.
| |
| 541 const std::string& mime_type_lower_case) const { | 564 const std::string& mime_type_lower_case, |
| 565 bool is_encrypted) const { | |
| 542 Codec default_codec = Codec::INVALID_CODEC; | 566 Codec default_codec = Codec::INVALID_CODEC; |
| 543 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 567 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 544 return false; | 568 return false; |
| 545 return IsCodecSupported(default_codec); | 569 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 546 } | 570 } |
| 547 | 571 |
| 548 #if defined(OS_ANDROID) | 572 #if defined(OS_ANDROID) |
| 549 bool MimeUtil::IsCodecSupportedOnAndroid(Codec codec) const { | 573 bool MimeUtil::IsCodecSupportedOnAndroid( |
|
ddorwin
2016/02/17 21:18:38
Much simpler now. Thanks!
DaleCurtis
2016/02/18 03:58:09
Acknowledged.
| |
| 574 Codec codec, | |
| 575 const std::string& mime_type_lower_case, | |
| 576 bool is_encrypted) const { | |
| 577 // Encrypted block support is never available without platform decoders. | |
| 578 if (is_encrypted && !platform_info_.has_platform_decoder) | |
| 579 return false; | |
| 580 | |
| 581 // NOTE: We do not account for Media Source Extensions (MSE) within these | |
| 582 // checks since it has its own isTypeSupported() which will handle platform | |
| 583 // specific codec rejections. See http://crbug.com/587303. | |
| 584 | |
| 550 switch (codec) { | 585 switch (codec) { |
| 586 // The following codecs are never supported. | |
| 587 case AC3: | |
| 588 case EAC3: | |
| 551 case INVALID_CODEC: | 589 case INVALID_CODEC: |
| 590 case THEORA: | |
| 552 return false; | 591 return false; |
| 553 | 592 |
| 593 // The following codecs may be supported depending on platform abilities. | |
|
ddorwin
2016/02/17 21:18:38
nit: This comment appears to apply to these 6 code
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 554 case PCM: | 594 case PCM: |
| 555 case MP3: | 595 case MP3: |
|
ddorwin
2016/02/17 21:18:38
Note: The results for proprietary audio codecs are
DaleCurtis
2016/02/18 03:58:09
This is correct, but should be a temporary issue o
| |
| 556 case MPEG4_AAC_LC: | 596 case MPEG4_AAC_LC: |
| 557 case MPEG4_AAC_SBR_v1: | 597 case MPEG4_AAC_SBR_v1: |
| 558 case MPEG4_AAC_SBR_PS_v2: | 598 case MPEG4_AAC_SBR_PS_v2: |
| 559 case VORBIS: | 599 case VORBIS: |
| 600 // These codecs are always supported; via a platform decoder (when used | |
| 601 // with MSE/EME), a software decoder (the unified pipeline), or with | |
| 602 // MediaPlayer. | |
| 603 DCHECK(!is_encrypted || platform_info_.has_platform_decoder); | |
| 604 return true; | |
| 605 | |
| 560 case H264_BASELINE: | 606 case H264_BASELINE: |
|
ddorwin
2016/02/17 21:18:39
We should try to keep audio and video (especially
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 561 case H264_MAIN: | 607 case H264_MAIN: |
| 562 case H264_HIGH: | 608 case H264_HIGH: |
| 563 case VP8: | 609 // The unified pipeline requires platform support for h264. |
| 610 if (platform_info_.has_unified_media_pipeline) | |
| 611 return platform_info_.has_platform_decoder; | |
| 612 | |
| 613 // When MediaPlayer is used, h264 is always supported. | |
| 614 DCHECK(!is_encrypted || platform_info_.has_platform_decoder); | |
| 564 return true; | 615 return true; |
| 565 | 616 |
| 566 case AC3: | 617 case VP8: |
| 567 case EAC3: | 618 if (is_encrypted) |
|
ddorwin
2016/02/17 21:18:39
I wonder if we should swap the logic here to be mo
DaleCurtis
2016/02/18 03:58:09
This logic is not quite the same since MediaPlayer
| |
| 568 // TODO(servolk): Revisit this for AC3/EAC3 support on AndroidTV | 619 return platform_info_.has_vp8; |
| 569 return false; | 620 |
| 621 // MediaPlayer or the unified pipeline can always play vp8 via software. | |
|
ddorwin
2016/02/17 21:18:39
nit: This wording is ambiguous. MP does not use SW
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 622 return true; | |
|
ddorwin
2016/02/17 21:18:39
Note: This is not true for MSE and !has_unified_me
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 570 | 623 |
| 571 case MPEG2_AAC_LC: | 624 case MPEG2_AAC_LC: |
| 572 case MPEG2_AAC_MAIN: | 625 case MPEG2_AAC_MAIN: |
| 573 case MPEG2_AAC_SSR: | 626 case MPEG2_AAC_SSR: |
| 574 // MPEG-2 variants of AAC are not supported on Android. | 627 // MPEG-2 variants of AAC are not supported on Android unless the unified |
| 575 return false; | 628 // media pipeline can be used. These codecs will be decoded in software. |
| 629 return !is_encrypted && platform_info_.has_unified_media_pipeline; | |
| 576 | 630 |
| 577 case OPUS: | 631 case OPUS: |
| 578 // Opus is supported only in Lollipop+ (API Level 21). | 632 // If clear, the unified pipeline can always decode OPUS in software. |
| 579 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; | 633 if (!is_encrypted && platform_info_.has_unified_media_pipeline) |
| 634 return true; | |
| 635 | |
| 636 // Otherwise, platform support is required. | |
| 637 if (!platform_info_.has_opus) | |
| 638 return false; | |
| 639 | |
| 640 // Android does not support opus in ogg containers. | |
|
ddorwin
2016/02/17 21:18:38
"The Android platform..."?
"Android MediaPlayer...
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 641 if (base::EndsWith(mime_type_lower_case, "ogg", | |
| 642 base::CompareCase::SENSITIVE)) { | |
| 643 return false; | |
| 644 } | |
| 645 | |
| 646 DCHECK(!is_encrypted || platform_info_.has_platform_decoder); | |
|
ddorwin
2016/02/17 21:18:39
This is one place where the differences in the has
DaleCurtis
2016/02/18 03:58:09
Hopefully has_xxx vs supports_xxx helps this confu
| |
| 647 return true; | |
| 580 | 648 |
| 581 case HEVC_MAIN: | 649 case HEVC_MAIN: |
| 582 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 650 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 583 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to | 651 // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to |
| 584 // http://developer.android.com/reference/android/media/MediaFormat.html | 652 // http://developer.android.com/reference/android/media/MediaFormat.html |
| 585 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; | 653 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; |
| 586 #else | 654 #else |
| 587 return false; | 655 return false; |
| 588 #endif | 656 #endif |
| 589 | 657 |
| 590 case VP9: | 658 case VP9: { |
| 591 // VP9 is supported only in KitKat+ (API Level 19). | 659 // If clear, the unified pipeline can always decode VP9 in software. |
| 592 return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; | 660 if (!is_encrypted && platform_info_.has_unified_media_pipeline) |
| 661 return true; | |
| 593 | 662 |
| 594 case THEORA: | 663 // Otherwise, platform support is required. |
| 595 return false; | 664 if (!platform_info_.has_vp9) |
|
ddorwin
2016/02/17 21:18:39
At this point, can we just return the value of thi
DaleCurtis
2016/02/18 03:58:09
Done.
| |
| 665 return false; | |
| 666 | |
| 667 DCHECK(!is_encrypted || platform_info_.has_platform_decoder); | |
| 668 return true; | |
| 669 } | |
| 596 } | 670 } |
| 597 | 671 |
| 598 return false; | 672 return false; |
| 599 } | 673 } |
| 600 #endif | 674 #endif |
| 601 | 675 |
| 602 } // namespace internal | 676 } // namespace internal |
| 603 } // namespace media | 677 } // namespace media |
| OLD | NEW |