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 |