Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: content/renderer/media/crypto/key_systems.cc

Issue 557723003: Implement Chromium side of MediaKeys.isTypeSupported(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Requested changes. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/renderer/media/crypto/key_systems.h" 5 #include "content/renderer/media/crypto/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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/threading/thread_checker.h" 13 #include "base/threading/thread_checker.h"
14 #include "base/time/time.h" 14 #include "base/time/time.h"
15 #include "content/public/common/content_client.h" 15 #include "content/public/common/content_client.h"
16 #include "content/public/common/eme_codec.h" 16 #include "content/public/common/eme_constants.h"
17 #include "content/public/renderer/content_renderer_client.h" 17 #include "content/public/renderer/content_renderer_client.h"
18 #include "content/public/renderer/key_system_info.h" 18 #include "content/public/renderer/key_system_info.h"
19 #include "content/renderer/media/crypto/key_systems_support_uma.h" 19 #include "content/renderer/media/crypto/key_systems_support_uma.h"
20 20
21 #if defined(OS_ANDROID) 21 #if defined(OS_ANDROID)
22 #include "media/base/android/media_codec_bridge.h" 22 #include "media/base/android/media_codec_bridge.h"
23 #endif 23 #endif
24 24
25 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. 25 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
26 26
27 namespace content { 27 namespace content {
28 28
29 const char kClearKeyKeySystem[] = "org.w3.clearkey"; 29 const char kClearKeyKeySystem[] = "org.w3.clearkey";
30 const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey"; 30 const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey";
31 const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey"; 31 const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey";
32 32
33 struct CodecMask { 33 struct NamedInitDataType {
34 const char* type; 34 const char* name;
35 EmeCodec mask; 35 EmeInitDataType type;
36 }; 36 };
37 37
38 // Mapping between container types and the masks of associated codecs. 38 // Mapping between initialization data types names and enum values.
ddorwin 2014/09/23 22:48:16 Add a comment to update IsSaneInitDataTypeWithCont
sandersd (OOO until July 31) 2014/09/24 22:22:34 Done.
39 static NamedInitDataType kInitDataTypes[] = {
40 {"cenc", EME_INIT_DATA_TYPE_CENC},
ddorwin 2014/09/23 22:48:16 ifdef - this will fail to compile. Also, remove th
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
41 {"webm", EME_INIT_DATA_TYPE_WEBM},
ddorwin 2014/09/23 22:48:17 ditto on swapping order
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
42 };
43
44 struct NamedCodec {
45 const char* name;
46 EmeCodec type;
47 };
48
49 // Mapping between containers and their codecs.
39 // Only audio codec can belong to a "audio/*" container. Both audio and video 50 // Only audio codec can belong to a "audio/*" container. Both audio and video
40 // codecs can belong to a "video/*" container. 51 // codecs can belong to a "video/*" container.
41 CodecMask kContainerCodecMasks[] = { 52 static NamedCodec kContainerCodecs[] = {
42 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL}, 53 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL},
43 {"video/webm", EME_CODEC_WEBM_ALL}, 54 {"video/webm", EME_CODEC_WEBM_ALL},
44 #if defined(USE_PROPRIETARY_CODECS) 55 #if defined(USE_PROPRIETARY_CODECS)
45 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL}, 56 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL},
46 {"video/mp4", EME_CODEC_MP4_ALL} 57 {"video/mp4", EME_CODEC_MP4_ALL}
47 #endif // defined(USE_PROPRIETARY_CODECS) 58 #endif // defined(USE_PROPRIETARY_CODECS)
48 }; 59 };
49 60
50 // Mapping between codec types and their masks. 61 // Mapping between codec names and enum values.
51 CodecMask kCodecMasks[] = { 62 static NamedCodec kCodecs[] = {
52 {"vorbis", EME_CODEC_WEBM_VORBIS}, 63 {"vorbis", EME_CODEC_WEBM_VORBIS},
53 {"vp8", EME_CODEC_WEBM_VP8}, 64 {"vp8", EME_CODEC_WEBM_VP8},
54 {"vp8.0", EME_CODEC_WEBM_VP8}, 65 {"vp8.0", EME_CODEC_WEBM_VP8},
55 {"vp9", EME_CODEC_WEBM_VP9}, 66 {"vp9", EME_CODEC_WEBM_VP9},
56 {"vp9.0", EME_CODEC_WEBM_VP9}, 67 {"vp9.0", EME_CODEC_WEBM_VP9},
57 #if defined(USE_PROPRIETARY_CODECS) 68 #if defined(USE_PROPRIETARY_CODECS)
58 {"mp4a", EME_CODEC_MP4_AAC}, 69 {"mp4a", EME_CODEC_MP4_AAC},
59 {"avc1", EME_CODEC_MP4_AVC1}, 70 {"avc1", EME_CODEC_MP4_AVC1},
60 {"avc3", EME_CODEC_MP4_AVC1} 71 {"avc3", EME_CODEC_MP4_AVC1}
61 #endif // defined(USE_PROPRIETARY_CODECS) 72 #endif // defined(USE_PROPRIETARY_CODECS)
62 }; 73 };
63 74
64 static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { 75 static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
65 KeySystemInfo info(kClearKeyKeySystem); 76 KeySystemInfo info(kClearKeyKeySystem);
66 77
67 // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec: 78 // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec:
68 // http://developer.android.com/guide/appendix/media-formats.html 79 // http://developer.android.com/guide/appendix/media-formats.html
69 // VP9 support is device dependent. 80 // VP9 support is device dependent.
70 81
82 info.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM;
71 info.supported_codecs = EME_CODEC_WEBM_ALL; 83 info.supported_codecs = EME_CODEC_WEBM_ALL;
72 84
73 #if defined(OS_ANDROID) 85 #if defined(OS_ANDROID)
74 // Temporarily disable VP9 support for Android. 86 // Temporarily disable VP9 support for Android.
75 // TODO(xhwang): Use mime_util.h to query VP9 support on Android. 87 // TODO(xhwang): Use mime_util.h to query VP9 support on Android.
76 info.supported_codecs &= ~EME_CODEC_WEBM_VP9; 88 info.supported_codecs &= ~EME_CODEC_WEBM_VP9;
77 #endif // defined(OS_ANDROID) 89 #endif // defined(OS_ANDROID)
78 90
79 #if defined(USE_PROPRIETARY_CODECS) 91 #if defined(USE_PROPRIETARY_CODECS)
92 info.supported_init_data_types |= EME_INIT_DATA_TYPE_CENC;
80 info.supported_codecs |= EME_CODEC_MP4_ALL; 93 info.supported_codecs |= EME_CODEC_MP4_ALL;
81 #endif // defined(USE_PROPRIETARY_CODECS) 94 #endif // defined(USE_PROPRIETARY_CODECS)
82 95
83 info.use_aes_decryptor = true; 96 info.use_aes_decryptor = true;
84 97
85 concrete_key_systems->push_back(info); 98 concrete_key_systems->push_back(info);
86 } 99 }
87 100
88 class KeySystems { 101 class KeySystems {
89 public: 102 public:
90 static KeySystems& GetInstance(); 103 static KeySystems& GetInstance();
91 104
92 void UpdateIfNeeded(); 105 void UpdateIfNeeded();
93 106
94 bool IsConcreteSupportedKeySystem(const std::string& key_system); 107 bool IsConcreteSupportedKeySystem(const std::string& key_system);
95 108
109 bool IsSupportedKeySystem(const std::string& key_system);
110
111 bool IsSupportedKeySystemWithInitDataType(
112 const std::string& key_system,
113 const std::string& init_data_type);
114
96 bool IsSupportedKeySystemWithMediaMimeType( 115 bool IsSupportedKeySystemWithMediaMimeType(
97 const std::string& mime_type, 116 const std::string& mime_type,
98 const std::vector<std::string>& codecs, 117 const std::vector<std::string>& codecs,
99 const std::string& key_system); 118 const std::string& key_system);
100 119
101 bool UseAesDecryptor(const std::string& concrete_key_system); 120 bool UseAesDecryptor(const std::string& concrete_key_system);
102 121
103 #if defined(ENABLE_PEPPER_CDMS) 122 #if defined(ENABLE_PEPPER_CDMS)
104 std::string GetPepperType(const std::string& concrete_key_system); 123 std::string GetPepperType(const std::string& concrete_key_system);
105 #endif 124 #endif
106 125
107 void AddContainerMask(const std::string& container, uint32 mask); 126 void AddContainerMask(const std::string& container, uint32 mask);
108 void AddCodecMask(const std::string& codec, uint32 mask); 127 void AddCodecMask(const std::string& codec, uint32 mask);
109 128
110 private: 129 private:
111 void UpdateSupportedKeySystems(); 130 void UpdateSupportedKeySystems();
112 131
113 void AddConcreteSupportedKeySystems( 132 void AddConcreteSupportedKeySystems(
114 const std::vector<KeySystemInfo>& concrete_key_systems); 133 const std::vector<KeySystemInfo>& concrete_key_systems);
115 134
116 void AddConcreteSupportedKeySystem( 135 void AddConcreteSupportedKeySystem(
117 const std::string& key_system, 136 const std::string& key_system,
118 bool use_aes_decryptor, 137 bool use_aes_decryptor,
119 #if defined(ENABLE_PEPPER_CDMS) 138 #if defined(ENABLE_PEPPER_CDMS)
120 const std::string& pepper_type, 139 const std::string& pepper_type,
121 #endif 140 #endif
141 SupportedInitDataTypes supported_init_data_types,
122 SupportedCodecs supported_codecs, 142 SupportedCodecs supported_codecs,
123 const std::string& parent_key_system); 143 const std::string& parent_key_system);
124 144
125 friend struct base::DefaultLazyInstanceTraits<KeySystems>; 145 friend struct base::DefaultLazyInstanceTraits<KeySystems>;
126 146
127 struct KeySystemProperties { 147 struct KeySystemProperties {
128 KeySystemProperties() 148 KeySystemProperties()
129 : use_aes_decryptor(false), supported_codecs(EME_CODEC_NONE) {} 149 : use_aes_decryptor(false), supported_codecs(EME_CODEC_NONE) {}
130 150
131 bool use_aes_decryptor; 151 bool use_aes_decryptor;
132 #if defined(ENABLE_PEPPER_CDMS) 152 #if defined(ENABLE_PEPPER_CDMS)
133 std::string pepper_type; 153 std::string pepper_type;
134 #endif 154 #endif
155 SupportedInitDataTypes supported_init_data_types;
135 SupportedCodecs supported_codecs; 156 SupportedCodecs supported_codecs;
136 }; 157 };
137 158
ddorwin 2014/09/23 22:48:16 Is there a reason you removed the typedefs? They w
sandersd (OOO until July 31) 2014/09/24 22:22:34 Only one of them was used more than once in the co
138 typedef base::hash_map<std::string, KeySystemProperties>
139 KeySystemPropertiesMap;
140 typedef base::hash_map<std::string, std::string> ParentKeySystemMap;
141 typedef base::hash_map<std::string, EmeCodec> CodecMaskMap;
142
143 KeySystems(); 159 KeySystems();
144 ~KeySystems() {} 160 ~KeySystems() {}
145 161
162 EmeInitDataType LookupInitDataType(const std::string& init_data_type) const;
ddorwin 2014/09/23 22:48:16 nit: GetInitDataTypeForString()?
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
163 SupportedCodecs LookupContainer(const std::string& container) const;
ddorwin 2014/09/23 22:48:16 In the future, it'd be nice to have a container en
ddorwin 2014/09/23 22:48:17 Is this more GetCodecsMaskForContainer()?
sandersd (OOO until July 31) 2014/09/24 22:22:34 Done.
sandersd (OOO until July 31) 2014/09/24 22:22:34 Done.
164 EmeCodec LookupCodec(const std::string& codec) const;
ddorwin 2014/09/23 22:48:17 nit: GetCodecForString() or ConvertStringToCodec()
sandersd (OOO until July 31) 2014/09/24 22:22:34 Done.
165
166 const std::string& GetConcreteKeySystem(const std::string& key_system) const;
ddorwin 2014/09/23 22:48:17 nit: ...Name
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
167
146 // Returns whether a |container| type is supported by checking 168 // Returns whether a |container| type is supported by checking
147 // |key_system_supported_codecs|. 169 // |key_system_supported_codecs|.
148 // TODO(xhwang): Update this to actually check initDataType support. 170 // TODO(xhwang): Update this to actually check initDataType support.
149 bool IsSupportedContainer(const std::string& container, 171 bool IsSupportedContainer(const std::string& container,
150 SupportedCodecs key_system_supported_codecs) const; 172 SupportedCodecs key_system_supported_codecs) const;
151 173
152 // Returns true if all |codecs| are supported in |container| by checking 174 // Returns true if all |codecs| are supported in |container| by checking
153 // |key_system_supported_codecs|. 175 // |key_system_supported_codecs|.
154 bool IsSupportedContainerAndCodecs( 176 bool IsSupportedContainerAndCodecs(
155 const std::string& container, 177 const std::string& container,
156 const std::vector<std::string>& codecs, 178 const std::vector<std::string>& codecs,
157 SupportedCodecs key_system_supported_codecs) const; 179 SupportedCodecs key_system_supported_codecs) const;
158 180
159 // Map from key system string to capabilities. 181 // Map from key system string to capabilities.
160 KeySystemPropertiesMap concrete_key_system_map_; 182 base::hash_map<std::string, KeySystemProperties> concrete_key_system_map_;
161 183
162 // Map from parent key system to the concrete key system that should be used 184 // Map from parent key system to the concrete key system that should be used
163 // to represent its capabilities. 185 // to represent its capabilities.
164 ParentKeySystemMap parent_key_system_map_; 186 base::hash_map<std::string, std::string> parent_key_system_map_;
165 187
166 KeySystemsSupportUMA key_systems_support_uma_; 188 KeySystemsSupportUMA key_systems_support_uma_;
167 189
168 CodecMaskMap container_codec_masks_; 190 base::hash_map<std::string, SupportedCodecs> container_codecs_;
ddorwin 2014/09/23 22:48:16 container_to_codecs_map_?
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
169 CodecMaskMap codec_masks_; 191 base::hash_map<std::string, EmeCodec> codecs_;
ddorwin 2014/09/23 22:48:17 codec_string_map_?
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
192 base::hash_map<std::string, EmeInitDataType> init_data_types_;
ddorwin 2014/09/23 22:48:16 ...map_
ddorwin 2014/09/23 22:48:17 make this one first.
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
170 193
171 bool needs_update_; 194 bool needs_update_;
172 base::Time last_update_time_; 195 base::Time last_update_time_;
173 196
174 // Makes sure all methods are called from the same thread. 197 // Makes sure all methods are called from the same thread.
175 base::ThreadChecker thread_checker_; 198 base::ThreadChecker thread_checker_;
176 199
177 DISALLOW_COPY_AND_ASSIGN(KeySystems); 200 DISALLOW_COPY_AND_ASSIGN(KeySystems);
178 }; 201 };
179 202
180 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER; 203 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
181 204
182 KeySystems& KeySystems::GetInstance() { 205 KeySystems& KeySystems::GetInstance() {
183 KeySystems& key_systems = g_key_systems.Get(); 206 KeySystems& key_systems = g_key_systems.Get();
184 key_systems.UpdateIfNeeded(); 207 key_systems.UpdateIfNeeded();
185 return key_systems; 208 return key_systems;
186 } 209 }
187 210
188 // Because we use a LazyInstance, the key systems info must be populated when 211 // Because we use a LazyInstance, the key systems info must be populated when
189 // the instance is lazily initiated. 212 // the instance is lazily initiated.
190 KeySystems::KeySystems() : needs_update_(true) { 213 KeySystems::KeySystems() : needs_update_(true) {
191 // Build container and codec masks for quick look up. 214 for (size_t i = 0; i < arraysize(kContainerCodecs); ++i) {
ddorwin 2014/09/23 22:48:17 You might be able to use a template function. Howe
sandersd (OOO until July 31) 2014/09/24 22:22:33 Sounds good, I've mentioned that in the bug for re
192 for (size_t i = 0; i < arraysize(kContainerCodecMasks); ++i) { 215 const std::string& name = kContainerCodecs[i].name;
193 const CodecMask& container_codec_mask = kContainerCodecMasks[i]; 216 DCHECK(container_codecs_.find(name) == container_codecs_.end());
194 DCHECK(container_codec_masks_.find(container_codec_mask.type) == 217 container_codecs_[name] = kContainerCodecs[i].type;
195 container_codec_masks_.end());
196 container_codec_masks_[container_codec_mask.type] =
197 container_codec_mask.mask;
198 } 218 }
199 for (size_t i = 0; i < arraysize(kCodecMasks); ++i) { 219 for (size_t i = 0; i < arraysize(kCodecs); ++i) {
200 const CodecMask& codec_mask = kCodecMasks[i]; 220 const std::string& name = kCodecs[i].name;
201 DCHECK(codec_masks_.find(codec_mask.type) == codec_masks_.end()); 221 DCHECK(codecs_.find(name) == codecs_.end());
202 codec_masks_[codec_mask.type] = codec_mask.mask; 222 codecs_[name] = kCodecs[i].type;
223 }
224 for (size_t i = 0; i < arraysize(kInitDataTypes); ++i) {
ddorwin 2014/09/23 22:48:16 move to line 214
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
225 const std::string& name = kInitDataTypes[i].name;
226 DCHECK(init_data_types_.find(name) == init_data_types_.end());
227 init_data_types_[name] = kInitDataTypes[i].type;
203 } 228 }
204 229
205 UpdateSupportedKeySystems(); 230 UpdateSupportedKeySystems();
206 231
207 #if defined(WIDEVINE_CDM_AVAILABLE) 232 #if defined(WIDEVINE_CDM_AVAILABLE)
208 key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem); 233 key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem);
209 #endif // defined(WIDEVINE_CDM_AVAILABLE) 234 #endif // defined(WIDEVINE_CDM_AVAILABLE)
210 } 235 }
211 236
237 EmeInitDataType KeySystems::LookupInitDataType(
238 const std::string& init_data_type) const {
239 base::hash_map<std::string, EmeInitDataType>::const_iterator iter =
240 init_data_types_.find(init_data_type);
241 if (iter != init_data_types_.end())
242 return iter->second;
243 return EME_INIT_DATA_TYPE_NONE;
244 }
245
246 SupportedCodecs KeySystems::LookupContainer(
247 const std::string& container) const {
248 base::hash_map<std::string, SupportedCodecs>::const_iterator iter =
249 container_codecs_.find(container);
250 if (iter != container_codecs_.end())
251 return iter->second;
252 return EME_CODEC_NONE;
253 }
254
255 EmeCodec KeySystems::LookupCodec(const std::string& codec) const {
256 base::hash_map<std::string, EmeCodec>::const_iterator iter =
257 codecs_.find(codec);
258 if (iter != codecs_.end())
259 return iter->second;
260 return EME_CODEC_NONE;
261 }
262
263 const std::string& KeySystems::GetConcreteKeySystem(
264 const std::string& key_system) const {
265 base::hash_map<std::string, std::string>::const_iterator iter =
266 parent_key_system_map_.find(key_system);
267 if (iter != parent_key_system_map_.end())
268 return iter->second;
269 return key_system;
270 }
271
212 void KeySystems::UpdateIfNeeded() { 272 void KeySystems::UpdateIfNeeded() {
213 #if defined(WIDEVINE_CDM_AVAILABLE) 273 #if defined(WIDEVINE_CDM_AVAILABLE)
214 DCHECK(thread_checker_.CalledOnValidThread()); 274 DCHECK(thread_checker_.CalledOnValidThread());
215 if (!needs_update_) 275 if (!needs_update_)
216 return; 276 return;
217 277
218 // The update could involve a sync IPC to the browser process. Use a minimum 278 // The update could involve a sync IPC to the browser process. Use a minimum
219 // update interval to avoid unnecessary frequent IPC to the browser. 279 // update interval to avoid unnecessary frequent IPC to the browser.
220 static const int kMinUpdateIntervalInSeconds = 1; 280 static const int kMinUpdateIntervalInSeconds = 1;
221 base::Time now = base::Time::Now(); 281 base::Time now = base::Time::Now();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 DCHECK(parent_key_system_map_.empty()); 317 DCHECK(parent_key_system_map_.empty());
258 318
259 for (size_t i = 0; i < concrete_key_systems.size(); ++i) { 319 for (size_t i = 0; i < concrete_key_systems.size(); ++i) {
260 const KeySystemInfo& key_system_info = concrete_key_systems[i]; 320 const KeySystemInfo& key_system_info = concrete_key_systems[i];
261 AddConcreteSupportedKeySystem(key_system_info.key_system, 321 AddConcreteSupportedKeySystem(key_system_info.key_system,
262 key_system_info.use_aes_decryptor, 322 key_system_info.use_aes_decryptor,
263 #if defined(ENABLE_PEPPER_CDMS) 323 #if defined(ENABLE_PEPPER_CDMS)
264 key_system_info.pepper_type, 324 key_system_info.pepper_type,
265 #endif 325 #endif
266 key_system_info.supported_codecs, 326 key_system_info.supported_codecs,
327 key_system_info.supported_init_data_types,
267 key_system_info.parent_key_system); 328 key_system_info.parent_key_system);
268 } 329 }
269 } 330 }
270 331
271 void KeySystems::AddConcreteSupportedKeySystem( 332 void KeySystems::AddConcreteSupportedKeySystem(
272 const std::string& concrete_key_system, 333 const std::string& concrete_key_system,
273 bool use_aes_decryptor, 334 bool use_aes_decryptor,
274 #if defined(ENABLE_PEPPER_CDMS) 335 #if defined(ENABLE_PEPPER_CDMS)
275 const std::string& pepper_type, 336 const std::string& pepper_type,
276 #endif 337 #endif
277 SupportedCodecs supported_codecs, 338 SupportedCodecs supported_codecs,
339 SupportedInitDataTypes supported_init_data_types,
ddorwin 2014/09/23 22:48:16 move up
sandersd (OOO until July 31) 2014/09/24 22:22:34 Alright, now I'm sad that the compiler didn't warn
ddorwin 2014/09/27 00:41:24 The danger of using masks!
278 const std::string& parent_key_system) { 340 const std::string& parent_key_system) {
279 DCHECK(thread_checker_.CalledOnValidThread()); 341 DCHECK(thread_checker_.CalledOnValidThread());
280 DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system)) 342 DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system))
281 << "Key system '" << concrete_key_system << "' already registered"; 343 << "Key system '" << concrete_key_system << "' already registered";
282 DCHECK(parent_key_system_map_.find(concrete_key_system) == 344 DCHECK(parent_key_system_map_.find(concrete_key_system) ==
283 parent_key_system_map_.end()) 345 parent_key_system_map_.end())
284 << "'" << concrete_key_system << " is already registered as a parent"; 346 << "'" << concrete_key_system << " is already registered as a parent";
285 347
286 KeySystemProperties properties; 348 KeySystemProperties properties;
287 properties.use_aes_decryptor = use_aes_decryptor; 349 properties.use_aes_decryptor = use_aes_decryptor;
288 #if defined(ENABLE_PEPPER_CDMS) 350 #if defined(ENABLE_PEPPER_CDMS)
289 DCHECK_EQ(use_aes_decryptor, pepper_type.empty()); 351 DCHECK_EQ(use_aes_decryptor, pepper_type.empty());
290 properties.pepper_type = pepper_type; 352 properties.pepper_type = pepper_type;
291 #endif 353 #endif
292 354
293 properties.supported_codecs = supported_codecs; 355 properties.supported_codecs = supported_codecs;
356 properties.supported_init_data_types = supported_init_data_types;
ddorwin 2014/09/23 22:48:17 ditto
sandersd (OOO until July 31) 2014/09/24 22:22:34 Done.
294 357
295 concrete_key_system_map_[concrete_key_system] = properties; 358 concrete_key_system_map_[concrete_key_system] = properties;
296 359
297 if (!parent_key_system.empty()) { 360 if (!parent_key_system.empty()) {
298 DCHECK(!IsConcreteSupportedKeySystem(parent_key_system)) 361 DCHECK(!IsConcreteSupportedKeySystem(parent_key_system))
299 << "Parent '" << parent_key_system << "' already registered concrete"; 362 << "Parent '" << parent_key_system << "' already registered concrete";
300 DCHECK(parent_key_system_map_.find(parent_key_system) == 363 DCHECK(parent_key_system_map_.find(parent_key_system) ==
301 parent_key_system_map_.end()) 364 parent_key_system_map_.end())
302 << "Parent '" << parent_key_system << "' already registered"; 365 << "Parent '" << parent_key_system << "' already registered";
303 parent_key_system_map_[parent_key_system] = concrete_key_system; 366 parent_key_system_map_[parent_key_system] = concrete_key_system;
304 } 367 }
305 } 368 }
306 369
307 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) { 370 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
308 DCHECK(thread_checker_.CalledOnValidThread()); 371 DCHECK(thread_checker_.CalledOnValidThread());
309 return concrete_key_system_map_.find(key_system) != 372 return concrete_key_system_map_.count(key_system);
310 concrete_key_system_map_.end();
311 } 373 }
312 374
313 bool KeySystems::IsSupportedContainer( 375 bool KeySystems::IsSupportedContainer(
314 const std::string& container, 376 const std::string& container,
315 SupportedCodecs key_system_supported_codecs) const { 377 SupportedCodecs key_system_supported_codecs) const {
316 DCHECK(thread_checker_.CalledOnValidThread()); 378 DCHECK(thread_checker_.CalledOnValidThread());
317 DCHECK(!container.empty()); 379 DCHECK(!container.empty());
318 380
319 // When checking container support for EME, "audio/foo" should be treated the 381 // When checking container support for EME, "audio/foo" should be treated the
320 // same as "video/foo". Convert the |container| to achieve this. 382 // same as "video/foo". Convert the |container| to achieve this.
321 // TODO(xhwang): Replace this with real checks against supported initDataTypes 383 // TODO(xhwang): Replace this with real checks against supported initDataTypes
322 // combined with supported demuxers. 384 // combined with supported demuxers.
323 std::string canonical_container = container; 385 std::string canonical_container = container;
324 if (container.find("audio/") == 0) 386 if (container.find("audio/") == 0)
ddorwin 2014/09/23 22:48:16 Note: If we also use enums for container types in
sandersd (OOO until July 31) 2014/09/24 22:22:33 Yes, we'll need both to be able to keep doing the
325 canonical_container.replace(0, 6, "video/"); 387 canonical_container.replace(0, 6, "video/");
326 388
327 CodecMaskMap::const_iterator container_iter =
328 container_codec_masks_.find(canonical_container);
329 // Unrecognized container.
330 if (container_iter == container_codec_masks_.end())
331 return false;
332
333 EmeCodec container_codec_mask = container_iter->second;
334 // A container is supported iif at least one codec in that container is 389 // A container is supported iif at least one codec in that container is
335 // supported. 390 // supported.
336 return (container_codec_mask & key_system_supported_codecs) != 0; 391 SupportedCodecs supported_codecs = LookupContainer(canonical_container);
392 return (supported_codecs & key_system_supported_codecs) != 0;
337 } 393 }
338 394
339 bool KeySystems::IsSupportedContainerAndCodecs( 395 bool KeySystems::IsSupportedContainerAndCodecs(
340 const std::string& container, 396 const std::string& container,
341 const std::vector<std::string>& codecs, 397 const std::vector<std::string>& codecs,
342 SupportedCodecs key_system_supported_codecs) const { 398 SupportedCodecs key_system_supported_codecs) const {
343 DCHECK(thread_checker_.CalledOnValidThread()); 399 DCHECK(thread_checker_.CalledOnValidThread());
344 DCHECK(!container.empty()); 400 DCHECK(!container.empty());
345 DCHECK(!codecs.empty()); 401 DCHECK(!codecs.empty());
346 DCHECK(IsSupportedContainer(container, key_system_supported_codecs)); 402 DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
347 403
348 CodecMaskMap::const_iterator container_iter = 404 SupportedCodecs container_supported_codecs = LookupContainer(container);
349 container_codec_masks_.find(container);
350 EmeCodec container_codec_mask = container_iter->second;
351 405
352 for (size_t i = 0; i < codecs.size(); ++i) { 406 for (size_t i = 0; i < codecs.size(); ++i) {
353 const std::string& codec = codecs[i]; 407 EmeCodec codec = LookupCodec(codecs[i]);
ddorwin 2014/09/23 22:48:16 The "codec.empty()" logic was for a specific reaso
xhwang 2014/09/29 21:27:17 Yeah, see the CL description of https://codereview
sandersd (OOO until July 31) 2014/09/29 21:38:48 Acknowledged. (There is a bug reference comment no
354 if (codec.empty())
355 continue;
356 CodecMaskMap::const_iterator codec_iter = codec_masks_.find(codec);
357 if (codec_iter == codec_masks_.end()) // Unrecognized codec.
358 return false;
359 408
360 EmeCodec codec_mask = codec_iter->second; 409 // Unsupported codec.
361 if (!(codec_mask & key_system_supported_codecs)) // Unsupported codec. 410 if (!(codec & key_system_supported_codecs))
362 return false; 411 return false;
363 412
364 // Unsupported codec/container combination, e.g. "video/webm" and "avc1". 413 // Unsupported codec/container combination, e.g. "video/webm" and "avc1".
365 if (!(codec_mask & container_codec_mask)) 414 if (!(codec & container_supported_codecs))
366 return false; 415 return false;
367 } 416 }
368 417
369 return true; 418 return true;
370 } 419 }
371 420
421 bool KeySystems::IsSupportedKeySystem(const std::string& key_system) {
422 DCHECK(thread_checker_.CalledOnValidThread());
423 return (concrete_key_system_map_.count(key_system) ||
424 parent_key_system_map_.count(key_system));
425 }
426
427 bool KeySystems::IsSupportedKeySystemWithInitDataType(
428 const std::string& key_system,
429 const std::string& init_data_type) {
430 DCHECK(thread_checker_.CalledOnValidThread());
431
432 // If |key_system| is a parent key system, use its concrete child.
433 const std::string& concrete_key_system = GetConcreteKeySystem(key_system);
434
435 // Locate |concrete_key_system|.
436 base::hash_map<std::string, KeySystemProperties>::const_iterator
437 key_system_iter = concrete_key_system_map_.find(concrete_key_system);
438 if (key_system_iter == concrete_key_system_map_.end())
439 return false;
440
441 // Check |init_data_type| and |key_system| x |init_data_type|.
442 const KeySystemProperties& properties = key_system_iter->second;
443 EmeInitDataType eme_init_data_type = LookupInitDataType(init_data_type);
444 return properties.supported_init_data_types & eme_init_data_type;
445 }
446
447 // TODO(sandersd): Remove if possible, otherwise reorganize in the same order as
ddorwin 2014/09/23 22:48:16 See comments below. canPlayType() calls this direc
sandersd (OOO until July 31) 2014/09/24 22:22:33 Done.
448 // IsKeySystemSupportedWithInitDataType().
372 bool KeySystems::IsSupportedKeySystemWithMediaMimeType( 449 bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
373 const std::string& mime_type, 450 const std::string& mime_type,
374 const std::vector<std::string>& codecs, 451 const std::vector<std::string>& codecs,
375 const std::string& key_system) { 452 const std::string& key_system) {
376 DCHECK(thread_checker_.CalledOnValidThread()); 453 DCHECK(thread_checker_.CalledOnValidThread());
377 454
378 // If |key_system| is a parent key_system, use its concrete child. 455 // If |key_system| is a parent key system, use its concrete child.
379 // Otherwise, use |key_system|. 456 const std::string& concrete_key_system = GetConcreteKeySystem(key_system);
380 std::string concrete_key_system;
381 ParentKeySystemMap::iterator parent_key_system_iter =
382 parent_key_system_map_.find(key_system);
383 if (parent_key_system_iter != parent_key_system_map_.end())
384 concrete_key_system = parent_key_system_iter->second;
385 else
386 concrete_key_system = key_system;
387 457
388 bool has_type = !mime_type.empty(); 458 bool has_type = !mime_type.empty();
389 459
390 key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type); 460 key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type);
ddorwin 2014/09/23 22:48:17 We now have some paths, including the function abo
xhwang 2014/09/29 21:27:17 I checked the current UMA stats (under Counts) and
sandersd (OOO until July 31) 2014/09/29 21:38:48 Acknowledged.
391 461
392 // Check key system support. 462 // Check key system support.
393 KeySystemPropertiesMap::const_iterator key_system_iter = 463 base::hash_map<std::string, KeySystemProperties>::const_iterator
394 concrete_key_system_map_.find(concrete_key_system); 464 key_system_iter = concrete_key_system_map_.find(concrete_key_system);
395 if (key_system_iter == concrete_key_system_map_.end()) 465 if (key_system_iter == concrete_key_system_map_.end())
396 return false; 466 return false;
397 467
398 key_systems_support_uma_.ReportKeySystemSupport(key_system, false); 468 key_systems_support_uma_.ReportKeySystemSupport(key_system, false);
399 469
400 if (!has_type) { 470 if (!has_type) {
ddorwin 2014/09/23 22:48:17 Note: The canPlayType() flow would always end up h
ddorwin 2014/09/27 00:41:24 +xhwang
xhwang 2014/09/29 21:27:17 Acknowledged.
401 DCHECK(codecs.empty()); 471 DCHECK(codecs.empty());
402 return true; 472 return true;
403 } 473 }
404 474
405 SupportedCodecs key_system_supported_codecs = 475 SupportedCodecs key_system_supported_codecs =
406 key_system_iter->second.supported_codecs; 476 key_system_iter->second.supported_codecs;
407 477
408 if (!IsSupportedContainer(mime_type, key_system_supported_codecs)) 478 if (!IsSupportedContainer(mime_type, key_system_supported_codecs))
409 return false; 479 return false;
410 480
411 if (!codecs.empty() && 481 if (!codecs.empty() &&
412 !IsSupportedContainerAndCodecs( 482 !IsSupportedContainerAndCodecs(
413 mime_type, codecs, key_system_supported_codecs)) { 483 mime_type, codecs, key_system_supported_codecs)) {
414 return false; 484 return false;
415 } 485 }
416 486
417 key_systems_support_uma_.ReportKeySystemSupport(key_system, true); 487 key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
418 return true; 488 return true;
419 } 489 }
420 490
421 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) { 491 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
422 DCHECK(thread_checker_.CalledOnValidThread()); 492 DCHECK(thread_checker_.CalledOnValidThread());
423 493
424 KeySystemPropertiesMap::iterator key_system_iter = 494 base::hash_map<std::string, KeySystemProperties>::const_iterator
425 concrete_key_system_map_.find(concrete_key_system); 495 key_system_iter = concrete_key_system_map_.find(concrete_key_system);
426 if (key_system_iter == concrete_key_system_map_.end()) { 496 if (key_system_iter == concrete_key_system_map_.end()) {
427 DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; 497 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
428 return false; 498 return false;
429 } 499 }
430 500
431 return key_system_iter->second.use_aes_decryptor; 501 return key_system_iter->second.use_aes_decryptor;
432 } 502 }
433 503
434 #if defined(ENABLE_PEPPER_CDMS) 504 #if defined(ENABLE_PEPPER_CDMS)
435 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) { 505 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
436 DCHECK(thread_checker_.CalledOnValidThread()); 506 DCHECK(thread_checker_.CalledOnValidThread());
437 507
438 KeySystemPropertiesMap::iterator key_system_iter = 508 base::hash_map<std::string, KeySystemProperties>::const_iterator
439 concrete_key_system_map_.find(concrete_key_system); 509 key_system_iter = concrete_key_system_map_.find(concrete_key_system);
440 if (key_system_iter == concrete_key_system_map_.end()) { 510 if (key_system_iter == concrete_key_system_map_.end()) {
441 DLOG(FATAL) << concrete_key_system << " is not a known concrete system"; 511 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
442 return std::string(); 512 return std::string();
443 } 513 }
444 514
445 const std::string& type = key_system_iter->second.pepper_type; 515 const std::string& type = key_system_iter->second.pepper_type;
446 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based"; 516 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based";
447 return type; 517 return type;
448 } 518 }
449 #endif 519 #endif
450 520
451 void KeySystems::AddContainerMask(const std::string& container, uint32 mask) { 521 void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
452 DCHECK(thread_checker_.CalledOnValidThread()); 522 DCHECK(thread_checker_.CalledOnValidThread());
453 DCHECK(container_codec_masks_.find(container) == 523 DCHECK(container_codecs_.find(container) == container_codecs_.end());
454 container_codec_masks_.end());
455 524
456 container_codec_masks_[container] = static_cast<EmeCodec>(mask); 525 container_codecs_[container] = static_cast<EmeCodec>(mask);
457 } 526 }
458 527
459 void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) { 528 void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) {
460 DCHECK(thread_checker_.CalledOnValidThread()); 529 DCHECK(thread_checker_.CalledOnValidThread());
461 DCHECK(codec_masks_.find(codec) == codec_masks_.end()); 530 DCHECK(codecs_.find(codec) == codecs_.end());
462 531
463 codec_masks_[codec] = static_cast<EmeCodec>(mask); 532 codecs_[codec] = static_cast<EmeCodec>(mask);
464 } 533 }
465 534
466 //------------------------------------------------------------------------------ 535 //------------------------------------------------------------------------------
467 536
468 std::string GetUnprefixedKeySystemName(const std::string& key_system) { 537 std::string GetUnprefixedKeySystemName(const std::string& key_system) {
469 if (key_system == kClearKeyKeySystem) 538 if (key_system == kClearKeyKeySystem)
470 return kUnsupportedClearKeyKeySystem; 539 return kUnsupportedClearKeyKeySystem;
471 540
472 if (key_system == kPrefixedClearKeyKeySystem) 541 if (key_system == kPrefixedClearKeyKeySystem)
473 return kClearKeyKeySystem; 542 return kClearKeyKeySystem;
474 543
475 return key_system; 544 return key_system;
476 } 545 }
477 546
478 std::string GetPrefixedKeySystemName(const std::string& key_system) { 547 std::string GetPrefixedKeySystemName(const std::string& key_system) {
479 DCHECK_NE(key_system, kPrefixedClearKeyKeySystem); 548 DCHECK_NE(key_system, kPrefixedClearKeyKeySystem);
480 549
481 if (key_system == kClearKeyKeySystem) 550 if (key_system == kClearKeyKeySystem)
482 return kPrefixedClearKeyKeySystem; 551 return kPrefixedClearKeyKeySystem;
483 552
484 return key_system; 553 return key_system;
485 } 554 }
486 555
556 bool IsSaneInitDataTypeWithContainer(
557 const std::string& init_data_type,
558 const std::string& container) {
559 if (init_data_type == "cenc") {
560 return container != "audio/webm" && container != "video/webm";
ddorwin 2014/09/23 22:48:17 Why not positive checks? This is actually wrong if
sandersd (OOO until July 31) 2014/09/24 22:22:34 I was assuming the goal was to exclude bad combina
561 } else if (init_data_type == "webm") {
562 return container != "audio/mp4" && container != "video/mp4";
563 } else {
564 return true;
ddorwin 2014/09/23 22:48:17 Related to enums, it would be nice to be able to h
sandersd (OOO until July 31) 2014/09/24 22:22:33 Sounds reasonable, I've just added the NOTREACHED
565 }
566 }
567
487 bool IsConcreteSupportedKeySystem(const std::string& key_system) { 568 bool IsConcreteSupportedKeySystem(const std::string& key_system) {
488 return KeySystems::GetInstance().IsConcreteSupportedKeySystem(key_system); 569 return KeySystems::GetInstance().IsConcreteSupportedKeySystem(key_system);
489 } 570 }
490 571
572 bool IsSupportedKeySystem(const std::string& key_system) {
ddorwin 2014/09/23 22:48:16 Related to UMAs, if someone refactored the code su
sandersd (OOO until July 31) 2014/09/24 22:22:34 I added a comment to the implementation.
573 return KeySystems::GetInstance().IsSupportedKeySystem(key_system);
574 }
575
576 bool IsSupportedKeySystemWithInitDataType(
577 const std::string& key_system,
578 const std::string& init_data_type) {
579 return KeySystems::GetInstance().IsSupportedKeySystemWithInitDataType(
580 key_system, init_data_type);
581 }
582
491 bool IsSupportedKeySystemWithMediaMimeType( 583 bool IsSupportedKeySystemWithMediaMimeType(
492 const std::string& mime_type, 584 const std::string& mime_type,
493 const std::vector<std::string>& codecs, 585 const std::vector<std::string>& codecs,
494 const std::string& key_system) { 586 const std::string& key_system) {
495 return KeySystems::GetInstance().IsSupportedKeySystemWithMediaMimeType( 587 return KeySystems::GetInstance().IsSupportedKeySystemWithMediaMimeType(
496 mime_type, codecs, key_system); 588 mime_type, codecs, key_system);
497 } 589 }
498 590
499 std::string KeySystemNameForUMA(const std::string& key_system) { 591 std::string KeySystemNameForUMA(const std::string& key_system) {
500 if (key_system == kClearKeyKeySystem) 592 if (key_system == kClearKeyKeySystem)
(...skipping 24 matching lines...) Expand all
525 CONTENT_EXPORT void AddContainerMask(const std::string& container, 617 CONTENT_EXPORT void AddContainerMask(const std::string& container,
526 uint32 mask) { 618 uint32 mask) {
527 KeySystems::GetInstance().AddContainerMask(container, mask); 619 KeySystems::GetInstance().AddContainerMask(container, mask);
528 } 620 }
529 621
530 CONTENT_EXPORT void AddCodecMask(const std::string& codec, uint32 mask) { 622 CONTENT_EXPORT void AddCodecMask(const std::string& codec, uint32 mask) {
531 KeySystems::GetInstance().AddCodecMask(codec, mask); 623 KeySystems::GetInstance().AddCodecMask(codec, mask);
532 } 624 }
533 625
534 } // namespace content 626 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698