Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / media / base / key_systems.cc
blobf97660c309eb700ac3c74b346e59ad7f647742ee
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
3 // found in the LICENSE file.
5 #include "media/base/key_systems.h"
7 #include <string>
9 #include "base/containers/hash_tables.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/thread_checker.h"
14 #include "base/time/time.h"
15 #include "media/base/eme_constants.h"
16 #include "media/base/key_system_info.h"
17 #include "media/base/key_systems_support_uma.h"
18 #include "media/base/media_client.h"
20 namespace media {
22 const char kClearKeyKeySystem[] = "org.w3.clearkey";
23 const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey";
24 const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey";
26 // These names are used by UMA. Do not change them!
27 const char kClearKeyKeySystemNameForUMA[] = "ClearKey";
28 const char kUnknownKeySystemNameForUMA[] = "Unknown";
30 struct NamedInitDataType {
31 const char* name;
32 EmeInitDataType type;
35 // Mapping between initialization data types names and enum values. When adding
36 // entries, make sure to update IsSaneInitDataTypeWithContainer().
37 static NamedInitDataType kInitDataTypeNames[] = {
38 {"webm", EME_INIT_DATA_TYPE_WEBM},
39 #if defined(USE_PROPRIETARY_CODECS)
40 {"cenc", EME_INIT_DATA_TYPE_CENC}
41 #endif // defined(USE_PROPRIETARY_CODECS)
44 struct NamedCodec {
45 const char* name;
46 EmeCodec type;
49 // Mapping between containers and their codecs.
50 // Only audio codec can belong to a "audio/*" container. Both audio and video
51 // codecs can belong to a "video/*" container.
52 static NamedCodec kContainerToCodecMasks[] = {
53 {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL},
54 {"video/webm", EME_CODEC_WEBM_ALL},
55 #if defined(USE_PROPRIETARY_CODECS)
56 {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL},
57 {"video/mp4", EME_CODEC_MP4_ALL}
58 #endif // defined(USE_PROPRIETARY_CODECS)
61 // Mapping between codec names and enum values.
62 static NamedCodec kCodecStrings[] = {
63 {"opus", EME_CODEC_WEBM_OPUS},
64 {"vorbis", EME_CODEC_WEBM_VORBIS},
65 {"vp8", EME_CODEC_WEBM_VP8},
66 {"vp8.0", EME_CODEC_WEBM_VP8},
67 {"vp9", EME_CODEC_WEBM_VP9},
68 {"vp9.0", EME_CODEC_WEBM_VP9},
69 #if defined(USE_PROPRIETARY_CODECS)
70 {"mp4a", EME_CODEC_MP4_AAC},
71 {"avc1", EME_CODEC_MP4_AVC1},
72 {"avc3", EME_CODEC_MP4_AVC1}
73 #endif // defined(USE_PROPRIETARY_CODECS)
76 static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
77 KeySystemInfo info(kClearKeyKeySystem);
79 // On Android, Vorbis, VP8, AAC and AVC1 are supported in MediaCodec:
80 // http://developer.android.com/guide/appendix/media-formats.html
81 // VP9 support is device dependent.
83 info.supported_init_data_types = EME_INIT_DATA_TYPE_WEBM;
84 info.supported_codecs = EME_CODEC_WEBM_ALL;
86 #if defined(OS_ANDROID)
87 // Temporarily disable VP9 support for Android.
88 // TODO(xhwang): Use mime_util.h to query VP9 support on Android.
89 info.supported_codecs &= ~EME_CODEC_WEBM_VP9;
91 // Opus is not supported on Android yet. http://crbug.com/318436.
92 // TODO(sandersd): Check for platform support to set this bit.
93 info.supported_codecs &= ~EME_CODEC_WEBM_OPUS;
94 #endif // defined(OS_ANDROID)
96 #if defined(USE_PROPRIETARY_CODECS)
97 info.supported_init_data_types |= EME_INIT_DATA_TYPE_CENC;
98 info.supported_codecs |= EME_CODEC_MP4_ALL;
99 #endif // defined(USE_PROPRIETARY_CODECS)
101 info.use_aes_decryptor = true;
103 concrete_key_systems->push_back(info);
106 class KeySystems {
107 public:
108 static KeySystems& GetInstance();
110 void UpdateIfNeeded();
112 bool IsConcreteSupportedKeySystem(const std::string& key_system);
114 bool IsSupportedKeySystem(const std::string& key_system);
116 bool IsSupportedKeySystemWithInitDataType(
117 const std::string& key_system,
118 const std::string& init_data_type);
120 bool IsSupportedKeySystemWithMediaMimeType(
121 const std::string& mime_type,
122 const std::vector<std::string>& codecs,
123 const std::string& key_system);
125 std::string GetKeySystemNameForUMA(const std::string& key_system) const;
127 bool UseAesDecryptor(const std::string& concrete_key_system);
129 #if defined(ENABLE_PEPPER_CDMS)
130 std::string GetPepperType(const std::string& concrete_key_system);
131 #endif
133 void AddContainerMask(const std::string& container, uint32 mask);
134 void AddCodecMask(const std::string& codec, uint32 mask);
136 private:
137 void InitializeUMAInfo();
139 void UpdateSupportedKeySystems();
141 void AddConcreteSupportedKeySystems(
142 const std::vector<KeySystemInfo>& concrete_key_systems);
144 void AddConcreteSupportedKeySystem(
145 const std::string& key_system,
146 bool use_aes_decryptor,
147 #if defined(ENABLE_PEPPER_CDMS)
148 const std::string& pepper_type,
149 #endif
150 SupportedInitDataTypes supported_init_data_types,
151 SupportedCodecs supported_codecs,
152 const std::string& parent_key_system);
154 friend struct base::DefaultLazyInstanceTraits<KeySystems>;
156 struct KeySystemProperties {
157 KeySystemProperties()
158 : use_aes_decryptor(false), supported_codecs(EME_CODEC_NONE) {}
160 bool use_aes_decryptor;
161 #if defined(ENABLE_PEPPER_CDMS)
162 std::string pepper_type;
163 #endif
164 SupportedInitDataTypes supported_init_data_types;
165 SupportedCodecs supported_codecs;
168 typedef base::hash_map<std::string, KeySystemProperties>
169 KeySystemPropertiesMap;
170 typedef base::hash_map<std::string, std::string> ParentKeySystemMap;
171 typedef base::hash_map<std::string, SupportedCodecs> ContainerCodecsMap;
172 typedef base::hash_map<std::string, EmeCodec> CodecsMap;
173 typedef base::hash_map<std::string, EmeInitDataType> InitDataTypesMap;
174 typedef base::hash_map<std::string, std::string> KeySystemNameForUMAMap;
176 KeySystems();
177 ~KeySystems() {}
179 EmeInitDataType GetInitDataTypeForName(
180 const std::string& init_data_type) const;
181 // TODO(sandersd): Separate container enum from codec mask value.
182 // http://crbug.com/417440
183 SupportedCodecs GetCodecMaskForContainer(
184 const std::string& container) const;
185 EmeCodec GetCodecForString(const std::string& codec) const;
187 const std::string& GetConcreteKeySystemName(
188 const std::string& key_system) const;
190 // Returns whether a |container| type is supported by checking
191 // |key_system_supported_codecs|.
192 // TODO(xhwang): Update this to actually check initDataType support.
193 bool IsSupportedContainer(const std::string& container,
194 SupportedCodecs key_system_supported_codecs) const;
196 // Returns true if all |codecs| are supported in |container| by checking
197 // |key_system_supported_codecs|.
198 bool IsSupportedContainerAndCodecs(
199 const std::string& container,
200 const std::vector<std::string>& codecs,
201 SupportedCodecs key_system_supported_codecs) const;
203 // Map from key system string to capabilities.
204 KeySystemPropertiesMap concrete_key_system_map_;
206 // Map from parent key system to the concrete key system that should be used
207 // to represent its capabilities.
208 ParentKeySystemMap parent_key_system_map_;
210 KeySystemsSupportUMA key_systems_support_uma_;
212 InitDataTypesMap init_data_type_name_map_;
213 ContainerCodecsMap container_to_codec_mask_map_;
214 CodecsMap codec_string_map_;
215 KeySystemNameForUMAMap key_system_name_for_uma_map_;
217 // Makes sure all methods are called from the same thread.
218 base::ThreadChecker thread_checker_;
220 DISALLOW_COPY_AND_ASSIGN(KeySystems);
223 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
225 KeySystems& KeySystems::GetInstance() {
226 KeySystems& key_systems = g_key_systems.Get();
227 key_systems.UpdateIfNeeded();
228 return key_systems;
231 // Because we use a LazyInstance, the key systems info must be populated when
232 // the instance is lazily initiated.
233 KeySystems::KeySystems() {
234 for (size_t i = 0; i < arraysize(kInitDataTypeNames); ++i) {
235 const std::string& name = kInitDataTypeNames[i].name;
236 DCHECK(!init_data_type_name_map_.count(name));
237 init_data_type_name_map_[name] = kInitDataTypeNames[i].type;
239 for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) {
240 const std::string& name = kContainerToCodecMasks[i].name;
241 DCHECK(!container_to_codec_mask_map_.count(name));
242 container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type;
244 for (size_t i = 0; i < arraysize(kCodecStrings); ++i) {
245 const std::string& name = kCodecStrings[i].name;
246 DCHECK(!codec_string_map_.count(name));
247 codec_string_map_[name] = kCodecStrings[i].type;
250 InitializeUMAInfo();
252 // Always update supported key systems during construction.
253 UpdateSupportedKeySystems();
256 EmeInitDataType KeySystems::GetInitDataTypeForName(
257 const std::string& init_data_type) const {
258 InitDataTypesMap::const_iterator iter =
259 init_data_type_name_map_.find(init_data_type);
260 if (iter != init_data_type_name_map_.end())
261 return iter->second;
262 return EME_INIT_DATA_TYPE_NONE;
265 SupportedCodecs KeySystems::GetCodecMaskForContainer(
266 const std::string& container) const {
267 ContainerCodecsMap::const_iterator iter =
268 container_to_codec_mask_map_.find(container);
269 if (iter != container_to_codec_mask_map_.end())
270 return iter->second;
271 return EME_CODEC_NONE;
274 EmeCodec KeySystems::GetCodecForString(const std::string& codec) const {
275 CodecsMap::const_iterator iter = codec_string_map_.find(codec);
276 if (iter != codec_string_map_.end())
277 return iter->second;
278 return EME_CODEC_NONE;
281 const std::string& KeySystems::GetConcreteKeySystemName(
282 const std::string& key_system) const {
283 ParentKeySystemMap::const_iterator iter =
284 parent_key_system_map_.find(key_system);
285 if (iter != parent_key_system_map_.end())
286 return iter->second;
287 return key_system;
290 void KeySystems::InitializeUMAInfo() {
291 DCHECK(thread_checker_.CalledOnValidThread());
292 DCHECK(key_system_name_for_uma_map_.empty());
294 std::vector<KeySystemInfoForUMA> key_systems_info_for_uma;
295 if (GetMediaClient())
296 GetMediaClient()->AddKeySystemsInfoForUMA(&key_systems_info_for_uma);
298 for (const KeySystemInfoForUMA& info : key_systems_info_for_uma) {
299 key_system_name_for_uma_map_[info.key_system] =
300 info.key_system_name_for_uma;
301 if (info.reports_key_system_support_to_uma)
302 key_systems_support_uma_.AddKeySystemToReport(info.key_system);
305 // Clear Key is always supported.
306 key_system_name_for_uma_map_[kClearKeyKeySystem] =
307 kClearKeyKeySystemNameForUMA;
310 void KeySystems::UpdateIfNeeded() {
311 if (GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded())
312 UpdateSupportedKeySystems();
315 void KeySystems::UpdateSupportedKeySystems() {
316 DCHECK(thread_checker_.CalledOnValidThread());
317 concrete_key_system_map_.clear();
318 parent_key_system_map_.clear();
320 // Build KeySystemInfo.
321 std::vector<KeySystemInfo> key_systems_info;
323 // Add key systems supported by the MediaClient implementation.
324 if (GetMediaClient())
325 GetMediaClient()->AddSupportedKeySystems(&key_systems_info);
327 // Clear Key is always supported.
328 AddClearKey(&key_systems_info);
330 AddConcreteSupportedKeySystems(key_systems_info);
333 void KeySystems::AddConcreteSupportedKeySystems(
334 const std::vector<KeySystemInfo>& concrete_key_systems) {
335 DCHECK(thread_checker_.CalledOnValidThread());
336 DCHECK(concrete_key_system_map_.empty());
337 DCHECK(parent_key_system_map_.empty());
339 for (size_t i = 0; i < concrete_key_systems.size(); ++i) {
340 const KeySystemInfo& key_system_info = concrete_key_systems[i];
341 AddConcreteSupportedKeySystem(key_system_info.key_system,
342 key_system_info.use_aes_decryptor,
343 #if defined(ENABLE_PEPPER_CDMS)
344 key_system_info.pepper_type,
345 #endif
346 key_system_info.supported_init_data_types,
347 key_system_info.supported_codecs,
348 key_system_info.parent_key_system);
352 void KeySystems::AddConcreteSupportedKeySystem(
353 const std::string& concrete_key_system,
354 bool use_aes_decryptor,
355 #if defined(ENABLE_PEPPER_CDMS)
356 const std::string& pepper_type,
357 #endif
358 SupportedInitDataTypes supported_init_data_types,
359 SupportedCodecs supported_codecs,
360 const std::string& parent_key_system) {
361 DCHECK(thread_checker_.CalledOnValidThread());
362 DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system))
363 << "Key system '" << concrete_key_system << "' already registered";
364 DCHECK(!parent_key_system_map_.count(concrete_key_system))
365 << "'" << concrete_key_system << " is already registered as a parent";
367 KeySystemProperties properties;
368 properties.use_aes_decryptor = use_aes_decryptor;
369 #if defined(ENABLE_PEPPER_CDMS)
370 DCHECK_EQ(use_aes_decryptor, pepper_type.empty());
371 properties.pepper_type = pepper_type;
372 #endif
374 properties.supported_init_data_types = supported_init_data_types;
375 properties.supported_codecs = supported_codecs;
377 concrete_key_system_map_[concrete_key_system] = properties;
379 if (!parent_key_system.empty()) {
380 DCHECK(!IsConcreteSupportedKeySystem(parent_key_system))
381 << "Parent '" << parent_key_system << "' already registered concrete";
382 DCHECK(!parent_key_system_map_.count(parent_key_system))
383 << "Parent '" << parent_key_system << "' already registered";
384 parent_key_system_map_[parent_key_system] = concrete_key_system;
388 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
389 DCHECK(thread_checker_.CalledOnValidThread());
390 return concrete_key_system_map_.count(key_system) != 0;
393 bool KeySystems::IsSupportedContainer(
394 const std::string& container,
395 SupportedCodecs key_system_supported_codecs) const {
396 DCHECK(thread_checker_.CalledOnValidThread());
397 DCHECK(!container.empty());
399 // When checking container support for EME, "audio/foo" should be treated the
400 // same as "video/foo". Convert the |container| to achieve this.
401 // TODO(xhwang): Replace this with real checks against supported initDataTypes
402 // combined with supported demuxers.
403 std::string canonical_container = container;
404 if (container.find("audio/") == 0)
405 canonical_container.replace(0, 6, "video/");
407 // A container is supported iif at least one codec in that container is
408 // supported.
409 SupportedCodecs supported_codecs =
410 GetCodecMaskForContainer(canonical_container);
411 return (supported_codecs & key_system_supported_codecs) != 0;
414 bool KeySystems::IsSupportedContainerAndCodecs(
415 const std::string& container,
416 const std::vector<std::string>& codecs,
417 SupportedCodecs key_system_supported_codecs) const {
418 DCHECK(thread_checker_.CalledOnValidThread());
419 DCHECK(!container.empty());
420 DCHECK(!codecs.empty());
421 DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
423 SupportedCodecs container_supported_codecs =
424 GetCodecMaskForContainer(container);
426 for (size_t i = 0; i < codecs.size(); ++i) {
427 // TODO(sandersd): This should fail for isTypeSupported().
428 // http://crbug.com/417461
429 if (codecs[i].empty())
430 continue;
432 EmeCodec codec = GetCodecForString(codecs[i]);
434 // Unsupported codec.
435 if (!(codec & key_system_supported_codecs))
436 return false;
438 // Unsupported codec/container combination, e.g. "video/webm" and "avc1".
439 if (!(codec & container_supported_codecs))
440 return false;
443 return true;
446 bool KeySystems::IsSupportedKeySystem(const std::string& key_system) {
447 DCHECK(thread_checker_.CalledOnValidThread());
448 return (concrete_key_system_map_.count(key_system) ||
449 parent_key_system_map_.count(key_system));
452 bool KeySystems::IsSupportedKeySystemWithInitDataType(
453 const std::string& key_system,
454 const std::string& init_data_type) {
455 DCHECK(thread_checker_.CalledOnValidThread());
457 // If |key_system| is a parent key system, use its concrete child.
458 const std::string& concrete_key_system = GetConcreteKeySystemName(key_system);
460 // Locate |concrete_key_system|.
461 KeySystemPropertiesMap::const_iterator key_system_iter =
462 concrete_key_system_map_.find(concrete_key_system);
463 if (key_system_iter == concrete_key_system_map_.end())
464 return false;
466 // Check |init_data_type| and |key_system| x |init_data_type|.
467 const KeySystemProperties& properties = key_system_iter->second;
468 EmeInitDataType eme_init_data_type = GetInitDataTypeForName(init_data_type);
469 return (properties.supported_init_data_types & eme_init_data_type) != 0;
472 // TODO(sandersd): Reorganize to be more similar to
473 // IsKeySystemSupportedWithInitDataType(). Note that a fork may still be
474 // required; http://crbug.com/417461.
475 bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
476 const std::string& mime_type,
477 const std::vector<std::string>& codecs,
478 const std::string& key_system) {
479 DCHECK(thread_checker_.CalledOnValidThread());
481 // If |key_system| is a parent key system, use its concrete child.
482 const std::string& concrete_key_system = GetConcreteKeySystemName(key_system);
484 bool has_type = !mime_type.empty();
486 key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type);
488 // Check key system support.
489 KeySystemPropertiesMap::const_iterator key_system_iter =
490 concrete_key_system_map_.find(concrete_key_system);
491 if (key_system_iter == concrete_key_system_map_.end())
492 return false;
494 key_systems_support_uma_.ReportKeySystemSupport(key_system, false);
496 if (!has_type) {
497 DCHECK(codecs.empty());
498 return true;
501 SupportedCodecs key_system_supported_codecs =
502 key_system_iter->second.supported_codecs;
504 if (!IsSupportedContainer(mime_type, key_system_supported_codecs))
505 return false;
507 if (!codecs.empty() &&
508 !IsSupportedContainerAndCodecs(
509 mime_type, codecs, key_system_supported_codecs)) {
510 return false;
513 key_systems_support_uma_.ReportKeySystemSupport(key_system, true);
514 return true;
517 std::string KeySystems::GetKeySystemNameForUMA(
518 const std::string& key_system) const {
519 DCHECK(thread_checker_.CalledOnValidThread());
521 KeySystemNameForUMAMap::const_iterator iter =
522 key_system_name_for_uma_map_.find(key_system);
523 if (iter == key_system_name_for_uma_map_.end())
524 return kUnknownKeySystemNameForUMA;
526 return iter->second;
529 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
530 DCHECK(thread_checker_.CalledOnValidThread());
532 KeySystemPropertiesMap::const_iterator key_system_iter =
533 concrete_key_system_map_.find(concrete_key_system);
534 if (key_system_iter == concrete_key_system_map_.end()) {
535 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
536 return false;
539 return key_system_iter->second.use_aes_decryptor;
542 #if defined(ENABLE_PEPPER_CDMS)
543 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
544 DCHECK(thread_checker_.CalledOnValidThread());
546 KeySystemPropertiesMap::const_iterator key_system_iter =
547 concrete_key_system_map_.find(concrete_key_system);
548 if (key_system_iter == concrete_key_system_map_.end()) {
549 DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
550 return std::string();
553 const std::string& type = key_system_iter->second.pepper_type;
554 DLOG_IF(FATAL, type.empty()) << concrete_key_system << " is not Pepper-based";
555 return type;
557 #endif
559 void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
560 DCHECK(thread_checker_.CalledOnValidThread());
561 DCHECK(!container_to_codec_mask_map_.count(container));
562 container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask);
565 void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) {
566 DCHECK(thread_checker_.CalledOnValidThread());
567 DCHECK(!codec_string_map_.count(codec));
568 codec_string_map_[codec] = static_cast<EmeCodec>(mask);
571 //------------------------------------------------------------------------------
573 std::string GetUnprefixedKeySystemName(const std::string& key_system) {
574 if (key_system == kClearKeyKeySystem)
575 return kUnsupportedClearKeyKeySystem;
577 if (key_system == kPrefixedClearKeyKeySystem)
578 return kClearKeyKeySystem;
580 return key_system;
583 std::string GetPrefixedKeySystemName(const std::string& key_system) {
584 DCHECK_NE(key_system, kPrefixedClearKeyKeySystem);
586 if (key_system == kClearKeyKeySystem)
587 return kPrefixedClearKeyKeySystem;
589 return key_system;
592 bool IsSaneInitDataTypeWithContainer(
593 const std::string& init_data_type,
594 const std::string& container) {
595 if (init_data_type == "cenc") {
596 return container == "audio/mp4" || container == "video/mp4";
597 } else if (init_data_type == "webm") {
598 return container == "audio/webm" || container == "video/webm";
599 } else {
600 return true;
604 bool IsConcreteSupportedKeySystem(const std::string& key_system) {
605 return KeySystems::GetInstance().IsConcreteSupportedKeySystem(key_system);
608 bool IsSupportedKeySystem(const std::string& key_system) {
609 return KeySystems::GetInstance().IsSupportedKeySystem(key_system);
612 bool IsSupportedKeySystemWithInitDataType(
613 const std::string& key_system,
614 const std::string& init_data_type) {
615 return KeySystems::GetInstance().IsSupportedKeySystemWithInitDataType(
616 key_system, init_data_type);
619 bool IsSupportedKeySystemWithMediaMimeType(
620 const std::string& mime_type,
621 const std::vector<std::string>& codecs,
622 const std::string& key_system) {
623 return KeySystems::GetInstance().IsSupportedKeySystemWithMediaMimeType(
624 mime_type, codecs, key_system);
627 std::string GetKeySystemNameForUMA(const std::string& key_system) {
628 return KeySystems::GetInstance().GetKeySystemNameForUMA(key_system);
631 bool CanUseAesDecryptor(const std::string& concrete_key_system) {
632 return KeySystems::GetInstance().UseAesDecryptor(concrete_key_system);
635 #if defined(ENABLE_PEPPER_CDMS)
636 std::string GetPepperType(const std::string& concrete_key_system) {
637 return KeySystems::GetInstance().GetPepperType(concrete_key_system);
639 #endif
641 // These two functions are for testing purpose only. The declaration in the
642 // header file is guarded by "#if defined(UNIT_TEST)" so that they can be used
643 // by tests but not non-test code. However, this .cc file is compiled as part of
644 // "media" where "UNIT_TEST" is not defined. So we need to specify
645 // "MEDIA_EXPORT" here again so that they are visible to tests.
647 MEDIA_EXPORT void AddContainerMask(const std::string& container,
648 uint32 mask) {
649 KeySystems::GetInstance().AddContainerMask(container, mask);
652 MEDIA_EXPORT void AddCodecMask(const std::string& codec, uint32 mask) {
653 KeySystems::GetInstance().AddCodecMask(codec, mask);
656 } // namespace media