Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2010 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 #include "include/DRMExtractor.h"
     18 
     19 #include <arpa/inet.h>
     20 #include <utils/String8.h>
     21 #include <media/stagefright/foundation/ADebug.h>
     22 #include <media/stagefright/Utils.h>
     23 #include <media/stagefright/DataSource.h>
     24 #include <media/stagefright/MediaSource.h>
     25 #include <media/stagefright/MediaDefs.h>
     26 #include <media/stagefright/MetaData.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 #include <media/stagefright/MediaBuffer.h>
     29 
     30 #include <drm/drm_framework_common.h>
     31 #include <utils/Errors.h>
     32 
     33 
     34 namespace android {
     35 
     36 class DRMSource : public MediaSource {
     37 public:
     38     DRMSource(const sp<MediaSource> &mediaSource,
     39             const sp<DecryptHandle> &decryptHandle,
     40             DrmManagerClient *managerClient,
     41             int32_t trackId, DrmBuffer *ipmpBox);
     42 
     43     virtual status_t start(MetaData *params = NULL);
     44     virtual status_t stop();
     45     virtual sp<MetaData> getFormat();
     46     virtual status_t read(
     47             MediaBuffer **buffer, const ReadOptions *options = NULL);
     48 
     49 protected:
     50     virtual ~DRMSource();
     51 
     52 private:
     53     sp<MediaSource> mOriginalMediaSource;
     54     sp<DecryptHandle> mDecryptHandle;
     55     DrmManagerClient* mDrmManagerClient;
     56     size_t mTrackId;
     57     mutable Mutex mDRMLock;
     58     size_t mNALLengthSize;
     59     bool mWantsNALFragments;
     60 
     61     DRMSource(const DRMSource &);
     62     DRMSource &operator=(const DRMSource &);
     63 };
     64 
     65 ////////////////////////////////////////////////////////////////////////////////
     66 
     67 DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
     68         const sp<DecryptHandle> &decryptHandle,
     69         DrmManagerClient *managerClient,
     70         int32_t trackId, DrmBuffer *ipmpBox)
     71     : mOriginalMediaSource(mediaSource),
     72       mDecryptHandle(decryptHandle),
     73       mDrmManagerClient(managerClient),
     74       mTrackId(trackId),
     75       mNALLengthSize(0),
     76       mWantsNALFragments(false) {
     77     CHECK(mDrmManagerClient);
     78     mDrmManagerClient->initializeDecryptUnit(
     79             mDecryptHandle, trackId, ipmpBox);
     80 
     81     const char *mime;
     82     bool success = getFormat()->findCString(kKeyMIMEType, &mime);
     83     CHECK(success);
     84 
     85     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
     86         uint32_t type;
     87         const void *data;
     88         size_t size;
     89         CHECK(getFormat()->findData(kKeyAVCC, &type, &data, &size));
     90 
     91         const uint8_t *ptr = (const uint8_t *)data;
     92 
     93         CHECK(size >= 7);
     94         CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
     95 
     96         // The number of bytes used to encode the length of a NAL unit.
     97         mNALLengthSize = 1 + (ptr[4] & 3);
     98     }
     99 }
    100 
    101 DRMSource::~DRMSource() {
    102     Mutex::Autolock autoLock(mDRMLock);
    103     mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
    104 }
    105 
    106 status_t DRMSource::start(MetaData *params) {
    107     int32_t val;
    108     if (params && params->findInt32(kKeyWantsNALFragments, &val)
    109         && val != 0) {
    110         mWantsNALFragments = true;
    111     } else {
    112         mWantsNALFragments = false;
    113     }
    114 
    115    return mOriginalMediaSource->start(params);
    116 }
    117 
    118 status_t DRMSource::stop() {
    119     return mOriginalMediaSource->stop();
    120 }
    121 
    122 sp<MetaData> DRMSource::getFormat() {
    123     return mOriginalMediaSource->getFormat();
    124 }
    125 
    126 status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
    127     Mutex::Autolock autoLock(mDRMLock);
    128     status_t err;
    129     if ((err = mOriginalMediaSource->read(buffer, options)) != OK) {
    130         return err;
    131     }
    132 
    133     size_t len = (*buffer)->range_length();
    134 
    135     char *src = (char *)(*buffer)->data() + (*buffer)->range_offset();
    136 
    137     DrmBuffer encryptedDrmBuffer(src, len);
    138     DrmBuffer decryptedDrmBuffer;
    139     decryptedDrmBuffer.length = len;
    140     decryptedDrmBuffer.data = new char[len];
    141     DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
    142 
    143     if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
    144             &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
    145 
    146         if (decryptedDrmBuffer.data) {
    147             delete [] decryptedDrmBuffer.data;
    148             decryptedDrmBuffer.data = NULL;
    149         }
    150 
    151         return err;
    152     }
    153     CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);
    154 
    155     const char *mime;
    156     CHECK(getFormat()->findCString(kKeyMIMEType, &mime));
    157 
    158     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) {
    159         uint8_t *dstData = (uint8_t*)src;
    160         size_t srcOffset = 0;
    161         size_t dstOffset = 0;
    162 
    163         len = decryptedDrmBuffer.length;
    164         while (srcOffset < len) {
    165             CHECK(srcOffset + mNALLengthSize <= len);
    166             size_t nalLength = 0;
    167             const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]);
    168 
    169             switch (mNALLengthSize) {
    170                 case 1:
    171                     nalLength = *data;
    172                     break;
    173                 case 2:
    174                     nalLength = U16_AT(data);
    175                     break;
    176                 case 3:
    177                     nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]);
    178                     break;
    179                 case 4:
    180                     nalLength = U32_AT(data);
    181                     break;
    182                 default:
    183                     CHECK(!"Should not be here.");
    184                     break;
    185             }
    186 
    187             srcOffset += mNALLengthSize;
    188 
    189             if (srcOffset + nalLength > len) {
    190                 if (decryptedDrmBuffer.data) {
    191                     delete [] decryptedDrmBuffer.data;
    192                     decryptedDrmBuffer.data = NULL;
    193                 }
    194 
    195                 return ERROR_MALFORMED;
    196             }
    197 
    198             if (nalLength == 0) {
    199                 continue;
    200             }
    201 
    202             CHECK(dstOffset + 4 <= (*buffer)->size());
    203 
    204             dstData[dstOffset++] = 0;
    205             dstData[dstOffset++] = 0;
    206             dstData[dstOffset++] = 0;
    207             dstData[dstOffset++] = 1;
    208             memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength);
    209             srcOffset += nalLength;
    210             dstOffset += nalLength;
    211         }
    212 
    213         CHECK_EQ(srcOffset, len);
    214         (*buffer)->set_range((*buffer)->range_offset(), dstOffset);
    215 
    216     } else {
    217         memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length);
    218         (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length);
    219     }
    220 
    221     if (decryptedDrmBuffer.data) {
    222         delete [] decryptedDrmBuffer.data;
    223         decryptedDrmBuffer.data = NULL;
    224     }
    225 
    226     return OK;
    227 }
    228 
    229 ////////////////////////////////////////////////////////////////////////////////
    230 
    231 DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
    232     : mDataSource(source),
    233       mDecryptHandle(NULL),
    234       mDrmManagerClient(NULL) {
    235     mOriginalExtractor = MediaExtractor::Create(source, mime);
    236     mOriginalExtractor->setDrmFlag(true);
    237     mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
    238 
    239     source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
    240 }
    241 
    242 DRMExtractor::~DRMExtractor() {
    243 }
    244 
    245 size_t DRMExtractor::countTracks() {
    246     return mOriginalExtractor->countTracks();
    247 }
    248 
    249 sp<MediaSource> DRMExtractor::getTrack(size_t index) {
    250     sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index);
    251     originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1);
    252 
    253     int32_t trackID;
    254     CHECK(getTrackMetaData(index, 0)->findInt32(kKeyTrackID, &trackID));
    255 
    256     DrmBuffer ipmpBox;
    257     ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length));
    258     CHECK(ipmpBox.length > 0);
    259 
    260     return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
    261             trackID, &ipmpBox);
    262 }
    263 
    264 sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
    265     return mOriginalExtractor->getTrackMetaData(index, flags);
    266 }
    267 
    268 sp<MetaData> DRMExtractor::getMetaData() {
    269     return mOriginalExtractor->getMetaData();
    270 }
    271 
    272 bool SniffDRM(
    273     const sp<DataSource> &source, String8 *mimeType, float *confidence,
    274         sp<AMessage> *) {
    275     sp<DecryptHandle> decryptHandle = source->DrmInitialization();
    276 
    277     if (decryptHandle != NULL) {
    278         if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
    279             *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
    280             *confidence = 10.0f;
    281         } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
    282             *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
    283             *confidence = 10.0f;
    284         } else {
    285             return false;
    286         }
    287 
    288         return true;
    289     }
    290 
    291     return false;
    292 }
    293 } //namespace android
    294 
    295