OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/key_systems.h" | 5 #include "media/base/key_systems.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/containers/hash_tables.h" | 9 #include "base/containers/hash_tables.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 }; | 45 }; |
46 | 46 |
47 struct NamedCodec { | 47 struct NamedCodec { |
48 const char* name; | 48 const char* name; |
49 EmeCodec type; | 49 EmeCodec type; |
50 }; | 50 }; |
51 | 51 |
52 // Mapping between containers and their codecs. | 52 // Mapping between containers and their codecs. |
53 // Only audio codec can belong to a "audio/*" container. Both audio and video | 53 // Only audio codec can belong to a "audio/*" container. Both audio and video |
54 // codecs can belong to a "video/*" container. | 54 // codecs can belong to a "video/*" container. |
| 55 // TODO(sandersd): This definition only makes sense for prefixed EME. Change it |
| 56 // when prefixed EME is removed. http://crbug.com/249976 |
55 static NamedCodec kContainerToCodecMasks[] = { | 57 static NamedCodec kContainerToCodecMasks[] = { |
56 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL}, | 58 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL}, |
57 {"video/webm", EME_CODEC_WEBM_ALL}, | 59 {"video/webm", EME_CODEC_WEBM_ALL}, |
58 #if defined(USE_PROPRIETARY_CODECS) | 60 #if defined(USE_PROPRIETARY_CODECS) |
59 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL}, | 61 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL}, |
60 {"video/mp4", EME_CODEC_MP4_ALL} | 62 {"video/mp4", EME_CODEC_MP4_ALL} |
61 #endif // defined(USE_PROPRIETARY_CODECS) | 63 #endif // defined(USE_PROPRIETARY_CODECS) |
62 }; | 64 }; |
63 | 65 |
64 // Mapping between codec names and enum values. | 66 // Mapping between codec names and enum values. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 | 208 |
207 bool IsSupportedKeySystemWithInitDataType( | 209 bool IsSupportedKeySystemWithInitDataType( |
208 const std::string& key_system, | 210 const std::string& key_system, |
209 const std::string& init_data_type) const; | 211 const std::string& init_data_type) const; |
210 | 212 |
211 bool PrefixedIsSupportedKeySystemWithMediaMimeType( | 213 bool PrefixedIsSupportedKeySystemWithMediaMimeType( |
212 const std::string& mime_type, | 214 const std::string& mime_type, |
213 const std::vector<std::string>& codecs, | 215 const std::vector<std::string>& codecs, |
214 const std::string& key_system); | 216 const std::string& key_system); |
215 | 217 |
216 bool IsSupportedKeySystemWithMediaMimeType( | |
217 const std::string& mime_type, | |
218 const std::vector<std::string>& codecs, | |
219 const std::string& key_system) const; | |
220 | |
221 std::string GetKeySystemNameForUMA(const std::string& key_system) const; | 218 std::string GetKeySystemNameForUMA(const std::string& key_system) const; |
222 | 219 |
223 bool UseAesDecryptor(const std::string& concrete_key_system) const; | 220 bool UseAesDecryptor(const std::string& concrete_key_system) const; |
224 | 221 |
225 #if defined(ENABLE_PEPPER_CDMS) | 222 #if defined(ENABLE_PEPPER_CDMS) |
226 std::string GetPepperType(const std::string& concrete_key_system) const; | 223 std::string GetPepperType(const std::string& concrete_key_system) const; |
227 #endif | 224 #endif |
228 | 225 |
229 void AddContainerMask(const std::string& container, uint32 mask); | 226 void AddContainerMask(const std::string& container, uint32 mask); |
230 void AddCodecMask(const std::string& codec, uint32 mask); | 227 void AddCodecMask( |
| 228 EmeMediaType media_type, |
| 229 const std::string& codec, |
| 230 uint32 mask); |
231 | 231 |
232 // Implementation of KeySystems interface. | 232 // Implementation of KeySystems interface. |
233 bool IsSupportedKeySystem(const std::string& key_system) const override; | 233 bool IsSupportedKeySystem(const std::string& key_system) const override; |
234 | 234 |
235 bool IsSupportedCodecCombination( | 235 bool IsSupportedCodecCombination( |
236 const std::string& key_system, | 236 const std::string& key_system, |
237 EmeMediaType media_type, | 237 EmeMediaType media_type, |
238 const std::string& container_mime_type, | 238 const std::string& container_mime_type, |
239 const std::vector<std::string>& codecs) const override; | 239 const std::vector<std::string>& codecs) const override; |
240 | 240 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 // to represent its capabilities. | 308 // to represent its capabilities. |
309 ParentKeySystemMap parent_key_system_map_; | 309 ParentKeySystemMap parent_key_system_map_; |
310 | 310 |
311 KeySystemsSupportUMA key_systems_support_uma_; | 311 KeySystemsSupportUMA key_systems_support_uma_; |
312 | 312 |
313 InitDataTypesMap init_data_type_name_map_; | 313 InitDataTypesMap init_data_type_name_map_; |
314 ContainerCodecsMap container_to_codec_mask_map_; | 314 ContainerCodecsMap container_to_codec_mask_map_; |
315 CodecsMap codec_string_map_; | 315 CodecsMap codec_string_map_; |
316 KeySystemNameForUMAMap key_system_name_for_uma_map_; | 316 KeySystemNameForUMAMap key_system_name_for_uma_map_; |
317 | 317 |
| 318 SupportedCodecs audio_codec_mask_; |
| 319 SupportedCodecs video_codec_mask_; |
| 320 |
318 // Makes sure all methods are called from the same thread. | 321 // Makes sure all methods are called from the same thread. |
319 base::ThreadChecker thread_checker_; | 322 base::ThreadChecker thread_checker_; |
320 | 323 |
321 DISALLOW_COPY_AND_ASSIGN(KeySystemsImpl); | 324 DISALLOW_COPY_AND_ASSIGN(KeySystemsImpl); |
322 }; | 325 }; |
323 | 326 |
324 static base::LazyInstance<KeySystemsImpl> g_key_systems = | 327 static base::LazyInstance<KeySystemsImpl> g_key_systems = |
325 LAZY_INSTANCE_INITIALIZER; | 328 LAZY_INSTANCE_INITIALIZER; |
326 | 329 |
327 KeySystemsImpl& KeySystemsImpl::GetInstance() { | 330 KeySystemsImpl& KeySystemsImpl::GetInstance() { |
328 KeySystemsImpl& key_systems = g_key_systems.Get(); | 331 KeySystemsImpl& key_systems = g_key_systems.Get(); |
329 key_systems.UpdateIfNeeded(); | 332 key_systems.UpdateIfNeeded(); |
330 return key_systems; | 333 return key_systems; |
331 } | 334 } |
332 | 335 |
333 // Because we use a LazyInstance, the key systems info must be populated when | 336 // Because we use a LazyInstance, the key systems info must be populated when |
334 // the instance is lazily initiated. | 337 // the instance is lazily initiated. |
335 KeySystemsImpl::KeySystemsImpl() { | 338 KeySystemsImpl::KeySystemsImpl() : |
| 339 audio_codec_mask_(EME_CODEC_AUDIO_ALL), |
| 340 video_codec_mask_(EME_CODEC_VIDEO_ALL) { |
336 for (size_t i = 0; i < arraysize(kInitDataTypeNames); ++i) { | 341 for (size_t i = 0; i < arraysize(kInitDataTypeNames); ++i) { |
337 const std::string& name = kInitDataTypeNames[i].name; | 342 const std::string& name = kInitDataTypeNames[i].name; |
338 DCHECK(!init_data_type_name_map_.count(name)); | 343 DCHECK(!init_data_type_name_map_.count(name)); |
339 init_data_type_name_map_[name] = kInitDataTypeNames[i].type; | 344 init_data_type_name_map_[name] = kInitDataTypeNames[i].type; |
340 } | 345 } |
341 for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) { | 346 for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) { |
342 const std::string& name = kContainerToCodecMasks[i].name; | 347 const std::string& name = kContainerToCodecMasks[i].name; |
343 DCHECK(!container_to_codec_mask_map_.count(name)); | 348 DCHECK(!container_to_codec_mask_map_.count(name)); |
344 container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type; | 349 container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type; |
345 } | 350 } |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 SupportedCodecs key_system_supported_codecs) const { | 554 SupportedCodecs key_system_supported_codecs) const { |
550 DCHECK(thread_checker_.CalledOnValidThread()); | 555 DCHECK(thread_checker_.CalledOnValidThread()); |
551 DCHECK(!container.empty()); | 556 DCHECK(!container.empty()); |
552 DCHECK(!codecs.empty()); | 557 DCHECK(!codecs.empty()); |
553 DCHECK(IsSupportedContainer(container, key_system_supported_codecs)); | 558 DCHECK(IsSupportedContainer(container, key_system_supported_codecs)); |
554 | 559 |
555 SupportedCodecs container_supported_codecs = | 560 SupportedCodecs container_supported_codecs = |
556 GetCodecMaskForContainer(container); | 561 GetCodecMaskForContainer(container); |
557 | 562 |
558 for (size_t i = 0; i < codecs.size(); ++i) { | 563 for (size_t i = 0; i < codecs.size(); ++i) { |
559 // TODO(sandersd): This should fail for isTypeSupported(). | |
560 // http://crbug.com/417461 | |
561 if (codecs[i].empty()) | 564 if (codecs[i].empty()) |
562 continue; | 565 continue; |
563 | 566 |
564 EmeCodec codec = GetCodecForString(codecs[i]); | 567 EmeCodec codec = GetCodecForString(codecs[i]); |
565 | 568 |
566 // Unsupported codec. | 569 // Unsupported codec. |
567 if (!(codec & key_system_supported_codecs)) | 570 if (!(codec & key_system_supported_codecs)) |
568 return false; | 571 return false; |
569 | 572 |
570 // Unsupported codec/container combination, e.g. "video/webm" and "avc1". | 573 // Unsupported codec/container combination, e.g. "video/webm" and "avc1". |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 !IsSupportedContainerAndCodecs( | 631 !IsSupportedContainerAndCodecs( |
629 mime_type, codecs, key_system_supported_codecs)) { | 632 mime_type, codecs, key_system_supported_codecs)) { |
630 return false; | 633 return false; |
631 } | 634 } |
632 | 635 |
633 key_systems_support_uma_.ReportKeySystemSupport(key_system, true); | 636 key_systems_support_uma_.ReportKeySystemSupport(key_system, true); |
634 | 637 |
635 return true; | 638 return true; |
636 } | 639 } |
637 | 640 |
638 bool KeySystemsImpl::IsSupportedKeySystemWithMediaMimeType( | |
639 const std::string& mime_type, | |
640 const std::vector<std::string>& codecs, | |
641 const std::string& key_system) const { | |
642 DCHECK(thread_checker_.CalledOnValidThread()); | |
643 | |
644 KeySystemInfoMap::const_iterator key_system_iter = | |
645 concrete_key_system_map_.find(key_system); | |
646 if (key_system_iter == concrete_key_system_map_.end()) | |
647 return false; | |
648 | |
649 if (mime_type.empty()) { | |
650 DCHECK(codecs.empty()); | |
651 return true; | |
652 } | |
653 | |
654 SupportedCodecs key_system_supported_codecs = | |
655 key_system_iter->second.supported_codecs; | |
656 | |
657 if (!IsSupportedContainer(mime_type, key_system_supported_codecs)) | |
658 return false; | |
659 | |
660 if (!codecs.empty() && | |
661 !IsSupportedContainerAndCodecs( | |
662 mime_type, codecs, key_system_supported_codecs)) { | |
663 return false; | |
664 } | |
665 | |
666 return true; | |
667 } | |
668 | |
669 std::string KeySystemsImpl::GetKeySystemNameForUMA( | 641 std::string KeySystemsImpl::GetKeySystemNameForUMA( |
670 const std::string& key_system) const { | 642 const std::string& key_system) const { |
671 DCHECK(thread_checker_.CalledOnValidThread()); | 643 DCHECK(thread_checker_.CalledOnValidThread()); |
672 | 644 |
673 KeySystemNameForUMAMap::const_iterator iter = | 645 KeySystemNameForUMAMap::const_iterator iter = |
674 key_system_name_for_uma_map_.find(key_system); | 646 key_system_name_for_uma_map_.find(key_system); |
675 if (iter == key_system_name_for_uma_map_.end()) | 647 if (iter == key_system_name_for_uma_map_.end()) |
676 return kUnknownKeySystemNameForUMA; | 648 return kUnknownKeySystemNameForUMA; |
677 | 649 |
678 return iter->second; | 650 return iter->second; |
(...skipping 24 matching lines...) Expand all Loading... |
703 DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; | 675 DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; |
704 return std::string(); | 676 return std::string(); |
705 } | 677 } |
706 | 678 |
707 const std::string& type = key_system_iter->second.pepper_type; | 679 const std::string& type = key_system_iter->second.pepper_type; |
708 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based"; | 680 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based"; |
709 return type; | 681 return type; |
710 } | 682 } |
711 #endif | 683 #endif |
712 | 684 |
713 void KeySystemsImpl::AddContainerMask(const std::string& container, | 685 void KeySystemsImpl::AddContainerMask( |
714 uint32 mask) { | 686 const std::string& container, |
| 687 uint32 mask) { |
715 DCHECK(thread_checker_.CalledOnValidThread()); | 688 DCHECK(thread_checker_.CalledOnValidThread()); |
716 DCHECK(!container_to_codec_mask_map_.count(container)); | 689 DCHECK(!container_to_codec_mask_map_.count(container)); |
717 container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask); | 690 container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask); |
718 } | 691 } |
719 | 692 |
720 void KeySystemsImpl::AddCodecMask(const std::string& codec, uint32 mask) { | 693 void KeySystemsImpl::AddCodecMask( |
| 694 EmeMediaType media_type, |
| 695 const std::string& codec, |
| 696 uint32 mask) { |
721 DCHECK(thread_checker_.CalledOnValidThread()); | 697 DCHECK(thread_checker_.CalledOnValidThread()); |
722 DCHECK(!codec_string_map_.count(codec)); | 698 DCHECK(!codec_string_map_.count(codec)); |
723 codec_string_map_[codec] = static_cast<EmeCodec>(mask); | 699 codec_string_map_[codec] = static_cast<EmeCodec>(mask); |
| 700 if (media_type == EmeMediaType::AUDIO) { |
| 701 audio_codec_mask_ |= mask; |
| 702 } else { |
| 703 video_codec_mask_ |= mask; |
| 704 } |
724 } | 705 } |
725 | 706 |
726 bool KeySystemsImpl::IsSupportedKeySystem(const std::string& key_system) const { | 707 bool KeySystemsImpl::IsSupportedKeySystem(const std::string& key_system) const { |
727 DCHECK(thread_checker_.CalledOnValidThread()); | 708 DCHECK(thread_checker_.CalledOnValidThread()); |
728 return concrete_key_system_map_.count(key_system) != 0; | 709 return concrete_key_system_map_.count(key_system) != 0; |
729 } | 710 } |
730 | 711 |
731 // TODO(sandersd): Make sure that the codecs also match the |media_type|. | |
732 // http://crbug.com/457386 | |
733 bool KeySystemsImpl::IsSupportedCodecCombination( | 712 bool KeySystemsImpl::IsSupportedCodecCombination( |
734 const std::string& key_system, | 713 const std::string& key_system, |
735 EmeMediaType media_type, | 714 EmeMediaType media_type, |
736 const std::string& container_mime_type, | 715 const std::string& container_mime_type, |
737 const std::vector<std::string>& codecs) const { | 716 const std::vector<std::string>& codecs) const { |
| 717 DCHECK(thread_checker_.CalledOnValidThread()); |
| 718 |
738 // Make sure the container matches |media_type|. | 719 // Make sure the container matches |media_type|. |
| 720 SupportedCodecs media_type_codec_mask = EME_CODEC_NONE; |
739 switch (media_type) { | 721 switch (media_type) { |
740 case EmeMediaType::AUDIO: | 722 case EmeMediaType::AUDIO: |
741 if (!StartsWithASCII(container_mime_type, "audio/", true)) | 723 if (!StartsWithASCII(container_mime_type, "audio/", true)) |
742 return false; | 724 return false; |
| 725 media_type_codec_mask = audio_codec_mask_; |
743 break; | 726 break; |
744 case EmeMediaType::VIDEO: | 727 case EmeMediaType::VIDEO: |
745 if (!StartsWithASCII(container_mime_type, "video/", true)) | 728 if (!StartsWithASCII(container_mime_type, "video/", true)) |
746 return false; | 729 return false; |
| 730 media_type_codec_mask = video_codec_mask_; |
747 break; | 731 break; |
748 } | 732 } |
749 return IsSupportedKeySystemWithMediaMimeType( | 733 |
750 container_mime_type, codecs, key_system); | 734 // Look up the key system's supported codecs. |
| 735 KeySystemInfoMap::const_iterator key_system_iter = |
| 736 concrete_key_system_map_.find(key_system); |
| 737 if (key_system_iter == concrete_key_system_map_.end()) { |
| 738 NOTREACHED(); |
| 739 return false; |
| 740 } |
| 741 SupportedCodecs key_system_codec_mask = |
| 742 key_system_iter->second.supported_codecs; |
| 743 |
| 744 // Check that the container is supported by the key system. (This check is |
| 745 // necessary because |codecs| may be empty.) |
| 746 SupportedCodecs container_codec_mask = |
| 747 GetCodecMaskForContainer(container_mime_type) & media_type_codec_mask; |
| 748 if ((key_system_codec_mask & container_codec_mask) == 0) |
| 749 return false; |
| 750 |
| 751 // Check that the codecs are supported by the key system and container. |
| 752 for (size_t i = 0; i < codecs.size(); i++) { |
| 753 SupportedCodecs codec = GetCodecForString(codecs[i]); |
| 754 if ((codec & key_system_codec_mask & container_codec_mask) == 0) |
| 755 return false; |
| 756 } |
| 757 |
| 758 return true; |
751 } | 759 } |
752 | 760 |
753 EmeConfigRule KeySystemsImpl::GetRobustnessConfigRule( | 761 EmeConfigRule KeySystemsImpl::GetRobustnessConfigRule( |
754 const std::string& key_system, | 762 const std::string& key_system, |
755 EmeMediaType media_type, | 763 EmeMediaType media_type, |
756 const std::string& requested_robustness) const { | 764 const std::string& requested_robustness) const { |
757 DCHECK(thread_checker_.CalledOnValidThread()); | 765 DCHECK(thread_checker_.CalledOnValidThread()); |
758 | 766 |
759 EmeRobustness robustness = ConvertRobustness(requested_robustness); | 767 EmeRobustness robustness = ConvertRobustness(requested_robustness); |
760 if (robustness == EmeRobustness::INVALID) | 768 if (robustness == EmeRobustness::INVALID) |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 return true; | 983 return true; |
976 } | 984 } |
977 | 985 |
978 bool IsSupportedKeySystemWithInitDataType( | 986 bool IsSupportedKeySystemWithInitDataType( |
979 const std::string& key_system, | 987 const std::string& key_system, |
980 const std::string& init_data_type) { | 988 const std::string& init_data_type) { |
981 return KeySystemsImpl::GetInstance().IsSupportedKeySystemWithInitDataType( | 989 return KeySystemsImpl::GetInstance().IsSupportedKeySystemWithInitDataType( |
982 key_system, init_data_type); | 990 key_system, init_data_type); |
983 } | 991 } |
984 | 992 |
985 bool IsSupportedKeySystemWithMediaMimeType( | |
986 const std::string& mime_type, | |
987 const std::vector<std::string>& codecs, | |
988 const std::string& key_system) { | |
989 return KeySystemsImpl::GetInstance().IsSupportedKeySystemWithMediaMimeType( | |
990 mime_type, codecs, key_system); | |
991 } | |
992 | |
993 bool PrefixedIsSupportedKeySystemWithMediaMimeType( | 993 bool PrefixedIsSupportedKeySystemWithMediaMimeType( |
994 const std::string& mime_type, | 994 const std::string& mime_type, |
995 const std::vector<std::string>& codecs, | 995 const std::vector<std::string>& codecs, |
996 const std::string& key_system) { | 996 const std::string& key_system) { |
997 return KeySystemsImpl::GetInstance() | 997 return KeySystemsImpl::GetInstance() |
998 .PrefixedIsSupportedKeySystemWithMediaMimeType(mime_type, codecs, | 998 .PrefixedIsSupportedKeySystemWithMediaMimeType(mime_type, codecs, |
999 key_system); | 999 key_system); |
1000 } | 1000 } |
1001 | 1001 |
1002 std::string GetKeySystemNameForUMA(const std::string& key_system) { | 1002 std::string GetKeySystemNameForUMA(const std::string& key_system) { |
(...skipping 13 matching lines...) Expand all Loading... |
1016 // These two functions are for testing purpose only. The declaration in the | 1016 // These two functions are for testing purpose only. The declaration in the |
1017 // header file is guarded by "#if defined(UNIT_TEST)" so that they can be used | 1017 // header file is guarded by "#if defined(UNIT_TEST)" so that they can be used |
1018 // by tests but not non-test code. However, this .cc file is compiled as part of | 1018 // by tests but not non-test code. However, this .cc file is compiled as part of |
1019 // "media" where "UNIT_TEST" is not defined. So we need to specify | 1019 // "media" where "UNIT_TEST" is not defined. So we need to specify |
1020 // "MEDIA_EXPORT" here again so that they are visible to tests. | 1020 // "MEDIA_EXPORT" here again so that they are visible to tests. |
1021 | 1021 |
1022 MEDIA_EXPORT void AddContainerMask(const std::string& container, uint32 mask) { | 1022 MEDIA_EXPORT void AddContainerMask(const std::string& container, uint32 mask) { |
1023 KeySystemsImpl::GetInstance().AddContainerMask(container, mask); | 1023 KeySystemsImpl::GetInstance().AddContainerMask(container, mask); |
1024 } | 1024 } |
1025 | 1025 |
1026 MEDIA_EXPORT void AddCodecMask(const std::string& codec, uint32 mask) { | 1026 MEDIA_EXPORT void AddCodecMask( |
1027 KeySystemsImpl::GetInstance().AddCodecMask(codec, mask); | 1027 EmeMediaType media_type, |
| 1028 const std::string& codec, |
| 1029 uint32 mask) { |
| 1030 KeySystemsImpl::GetInstance().AddCodecMask(media_type, codec, mask); |
1028 } | 1031 } |
1029 | 1032 |
1030 } // namespace media | 1033 } // namespace media |
OLD | NEW |