1 // Copyright 2014 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.
4
5 #include "components/cdm/browser/cdm_message_filter_android.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "components/cdm/common/cdm_messages_android.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "media/base/android/media_codec_bridge.h"
13 #include "media/base/android/media_drm_bridge.h"
14
15 using content::BrowserThread;
16 using content::SupportedCodecs;
17 using media::MediaCodecBridge;
18 using media::MediaDrmBridge;
19
20 namespace cdm {
21
22 const size_t kMaxKeySystemLength = 256;
23
24 enum CodecType {
25 CODEC_AUDIO,
26 CODEC_VIDEO
27 };
28
29 struct CodecInfo {
30 SupportedCodecs codec;
31 CodecType codec_type;
32 const char* codec_name;
33 const char* container_mime_type;
34 };
35
36 const CodecInfo kCodecsToQuery[] = {
37 {content::EME_CODEC_WEBM_VORBIS, CODEC_AUDIO, "vorbis", "video/webm"},
38 {content::EME_CODEC_WEBM_VP8, CODEC_VIDEO, "vp8", "video/webm"},
39 {content::EME_CODEC_WEBM_VP9, CODEC_VIDEO, "vp9", "video/webm"},
40 #if defined(USE_PROPRIETARY_CODECS)
41 {content::EME_CODEC_MP4_AAC, CODEC_AUDIO, "mp4a", "video/mp4"},
42 {content::EME_CODEC_MP4_AVC1, CODEC_VIDEO, "avc1", "video/mp4"}
43 #endif // defined(USE_PROPRIETARY_CODECS)
44 };
45
GetSupportedCodecs(const SupportedKeySystemRequest & request,bool video_must_be_compositable)46 static SupportedCodecs GetSupportedCodecs(
47 const SupportedKeySystemRequest& request,
48 bool video_must_be_compositable) {
49 const std::string& key_system = request.key_system;
50 SupportedCodecs supported_codecs = content::EME_CODEC_NONE;
51
52 for (size_t i = 0; i < arraysize(kCodecsToQuery); ++i) {
53 const CodecInfo& info = kCodecsToQuery[i];
54 // TODO(qinmin): Remove the composition logic when secure contents can be
55 // composited.
56 bool is_secure = (info.codec_type == CODEC_VIDEO)
57 ? (!video_must_be_compositable) : false;
58 if ((request.codecs & info.codec) &&
59 MediaDrmBridge::IsKeySystemSupportedWithType(
60 key_system, info.container_mime_type) &&
61 MediaCodecBridge::CanDecode(info.codec_name, is_secure)) {
62 supported_codecs |= info.codec;
63 }
64 }
65
66 return supported_codecs;
67 }
68
CdmMessageFilterAndroid()69 CdmMessageFilterAndroid::CdmMessageFilterAndroid()
70 : BrowserMessageFilter(EncryptedMediaMsgStart) {}
71
~CdmMessageFilterAndroid()72 CdmMessageFilterAndroid::~CdmMessageFilterAndroid() {}
73
OnMessageReceived(const IPC::Message & message)74 bool CdmMessageFilterAndroid::OnMessageReceived(const IPC::Message& message) {
75 bool handled = true;
76 IPC_BEGIN_MESSAGE_MAP(CdmMessageFilterAndroid, message)
77 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_QueryKeySystemSupport,
78 OnQueryKeySystemSupport)
79 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_GetPlatformKeySystemNames,
80 OnGetPlatformKeySystemNames)
81 IPC_MESSAGE_UNHANDLED(handled = false)
82 IPC_END_MESSAGE_MAP()
83 return handled;
84 }
85
OverrideThreadForMessage(const IPC::Message & message,BrowserThread::ID * thread)86 void CdmMessageFilterAndroid::OverrideThreadForMessage(
87 const IPC::Message& message, BrowserThread::ID* thread) {
88 // Move the IPC handling to FILE thread as it is not very cheap.
89 if (message.type() == ChromeViewHostMsg_QueryKeySystemSupport::ID)
90 *thread = BrowserThread::FILE;
91 }
92
OnQueryKeySystemSupport(const SupportedKeySystemRequest & request,SupportedKeySystemResponse * response)93 void CdmMessageFilterAndroid::OnQueryKeySystemSupport(
94 const SupportedKeySystemRequest& request,
95 SupportedKeySystemResponse* response) {
96 if (!response) {
97 NOTREACHED() << "NULL response pointer provided.";
98 return;
99 }
100
101 if (request.key_system.size() > kMaxKeySystemLength) {
102 NOTREACHED() << "Invalid key system: " << request.key_system;
103 return;
104 }
105
106 if (!MediaDrmBridge::IsKeySystemSupported(request.key_system))
107 return;
108
109 DCHECK(request.codecs & content::EME_CODEC_ALL) << "unrecognized codec";
110 response->key_system = request.key_system;
111 // TODO(qinmin): check composition is supported or not.
112 response->compositing_codecs = GetSupportedCodecs(request, true);
113 response->non_compositing_codecs = GetSupportedCodecs(request, false);
114 }
115
OnGetPlatformKeySystemNames(std::vector<std::string> * key_systems)116 void CdmMessageFilterAndroid::OnGetPlatformKeySystemNames(
117 std::vector<std::string>* key_systems) {
118 *key_systems = MediaDrmBridge::GetPlatformKeySystemNames();
119 }
120
121 } // namespace cdm
122