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