Home | History | Annotate | Download | only in browser
      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 
     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 
     69 CdmMessageFilterAndroid::CdmMessageFilterAndroid()
     70     : BrowserMessageFilter(EncryptedMediaMsgStart) {}
     71 
     72 CdmMessageFilterAndroid::~CdmMessageFilterAndroid() {}
     73 
     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 
     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 
     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 
    116 void CdmMessageFilterAndroid::OnGetPlatformKeySystemNames(
    117     std::vector<std::string>* key_systems) {
    118   *key_systems = MediaDrmBridge::GetPlatformKeySystemNames();
    119 }
    120 
    121 }  // namespace cdm
    122