Home | History | Annotate | Download | only in nuplayer2
      1 /*
      2  * Copyright 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "NuPlayer2Drm"
     19 
     20 #include "NuPlayer2Drm.h"
     21 
     22 #include <media/NdkWrapper.h>
     23 #include <utils/Log.h>
     24 #include <sstream>
     25 
     26 namespace android {
     27 
     28 Vector<DrmUUID> NuPlayer2Drm::parsePSSH(const void *pssh, size_t psshsize)
     29 {
     30     Vector<DrmUUID> drmSchemes, empty;
     31     const int DATALEN_SIZE = 4;
     32 
     33     // the format of the buffer is 1 or more of:
     34     //    {
     35     //        16 byte uuid
     36     //        4 byte data length N
     37     //        N bytes of data
     38     //    }
     39     // Determine the number of entries in the source data.
     40     // Since we got the data from stagefright, we trust it is valid and properly formatted.
     41 
     42     const uint8_t *data = (const uint8_t*)pssh;
     43     size_t len = psshsize;
     44     size_t numentries = 0;
     45     while (len > 0) {
     46         if (len < DrmUUID::UUID_SIZE) {
     47             ALOGE("ParsePSSH: invalid PSSH data");
     48             return empty;
     49         }
     50 
     51         const uint8_t *uuidPtr = data;
     52 
     53         // skip uuid
     54         data += DrmUUID::UUID_SIZE;
     55         len -= DrmUUID::UUID_SIZE;
     56 
     57         // get data length
     58         if (len < DATALEN_SIZE) {
     59             ALOGE("ParsePSSH: invalid PSSH data");
     60             return empty;
     61         }
     62 
     63         uint32_t datalen = *((uint32_t*)data);
     64         data += DATALEN_SIZE;
     65         len -= DATALEN_SIZE;
     66 
     67         if (len < datalen) {
     68             ALOGE("ParsePSSH: invalid PSSH data");
     69             return empty;
     70         }
     71 
     72         // skip the data
     73         data += datalen;
     74         len -= datalen;
     75 
     76         DrmUUID _uuid(uuidPtr);
     77         drmSchemes.add(_uuid);
     78 
     79         ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
     80                 _uuid.toHexString().string(),
     81                 DrmUUID::arrayToHex(data, datalen).string()
     82              );
     83 
     84         numentries++;
     85     }
     86 
     87     return drmSchemes;
     88 }
     89 
     90 Vector<DrmUUID> NuPlayer2Drm::getSupportedDrmSchemes(const void *pssh, size_t psshsize)
     91 {
     92     Vector<DrmUUID> psshDRMs = parsePSSH(pssh, psshsize);
     93 
     94     Vector<DrmUUID> supportedDRMs;
     95     for (size_t i = 0; i < psshDRMs.size(); i++) {
     96         DrmUUID uuid = psshDRMs[i];
     97         if (AMediaDrmWrapper::isCryptoSchemeSupported(uuid.ptr(), NULL)) {
     98             supportedDRMs.add(uuid);
     99         }
    100     }
    101 
    102     ALOGV("getSupportedDrmSchemes: psshDRMs: %zu supportedDRMs: %zu",
    103             psshDRMs.size(), supportedDRMs.size());
    104 
    105     return supportedDRMs;
    106 }
    107 
    108 sp<ABuffer> NuPlayer2Drm::retrieveDrmInfo(const void *pssh, uint32_t psshsize)
    109 {
    110     std::ostringstream buf;
    111 
    112     // 1) PSSH bytes
    113     buf.write(reinterpret_cast<const char *>(&psshsize), sizeof(psshsize));
    114     buf.write(reinterpret_cast<const char *>(pssh), psshsize);
    115 
    116     ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  PSSH: size: %u %s", psshsize,
    117             DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());
    118 
    119     // 2) supportedDRMs
    120     Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
    121     uint32_t n = supportedDRMs.size();
    122     buf.write(reinterpret_cast<char *>(&n), sizeof(n));
    123     for (size_t i = 0; i < n; i++) {
    124         DrmUUID uuid = supportedDRMs[i];
    125         buf.write(reinterpret_cast<const char *>(&n), sizeof(n));
    126         buf.write(reinterpret_cast<const char *>(uuid.ptr()), DrmUUID::UUID_SIZE);
    127 
    128         ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO  supportedScheme[%zu] %s", i,
    129                 uuid.toHexString().string());
    130     }
    131 
    132     sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(buf.str().c_str(), buf.tellp());
    133     return drmInfoBuffer;
    134 }
    135 
    136 sp<ABuffer> NuPlayer2Drm::retrieveDrmInfo(PsshInfo *psshInfo)
    137 {
    138 
    139     std::ostringstream pssh, drmInfo;
    140 
    141     // 0) Generate PSSH bytes
    142     for (size_t i = 0; i < psshInfo->numentries; i++) {
    143         PsshEntry *entry = &psshInfo->entries[i];
    144         uint32_t datalen = entry->datalen;
    145         pssh.write(reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
    146         pssh.write(reinterpret_cast<const char *>(&datalen), sizeof(datalen));
    147         pssh.write(reinterpret_cast<const char *>(entry->data), datalen);
    148     }
    149 
    150     uint32_t psshSize = pssh.tellp();
    151     const uint8_t* psshPtr = reinterpret_cast<const uint8_t*>(pssh.str().c_str());
    152     const char *psshHex = DrmUUID::arrayToHex(psshPtr, psshSize).string();
    153     ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  PSSH: size: %u %s", psshSize, psshHex);
    154 
    155     // 1) Write PSSH bytes
    156     drmInfo.write(reinterpret_cast<const char *>(&psshSize), sizeof(psshSize));
    157     drmInfo.write(reinterpret_cast<const char *>(pssh.str().c_str()), psshSize);
    158 
    159     // 2) Write supportedDRMs
    160     uint32_t numentries = psshInfo->numentries;
    161     drmInfo.write(reinterpret_cast<const char *>(&numentries), sizeof(numentries));
    162     for (size_t i = 0; i < numentries; i++) {
    163         PsshEntry *entry = &psshInfo->entries[i];
    164         drmInfo.write(reinterpret_cast<const char *>(&entry->uuid), sizeof(entry->uuid));
    165         ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO  supportedScheme[%zu] %s", i,
    166                 DrmUUID::arrayToHex((const uint8_t*)&entry->uuid, sizeof(AMediaUUID)).string());
    167     }
    168 
    169     sp<ABuffer> drmInfoBuf = ABuffer::CreateAsCopy(drmInfo.str().c_str(), drmInfo.tellp());
    170     drmInfoBuf->setRange(0, drmInfo.tellp());
    171     return drmInfoBuf;
    172 }
    173 
    174 }   // namespace android
    175