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