DRMExtractor.cpp revision c2c22e7e20a3b10c180c2fed2bf24aedef8ed269
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/Utils.h> 27#include <media/stagefright/DataSource.h> 28#include <media/stagefright/MediaSource.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/MediaErrors.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaDebug.h> 34 35#include <drm/drm_framework_common.h> 36#include <utils/Errors.h> 37 38 39namespace android { 40 41DrmManagerClient* gDrmManagerClient = NULL; 42 43class DRMSource : public MediaSource { 44public: 45 DRMSource(const sp<MediaSource> &mediaSource, 46 DecryptHandle* decryptHandle, 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 54protected: 55 virtual ~DRMSource(); 56 57private: 58 sp<MediaSource> mOriginalMediaSource; 59 DecryptHandle* mDecryptHandle; 60 size_t mTrackId; 61 mutable Mutex mDRMLock; 62 size_t mNALLengthSize; 63 bool mWantsNALFragments; 64 65 DRMSource(const DRMSource &); 66 DRMSource &operator=(const DRMSource &); 67}; 68 69//////////////////////////////////////////////////////////////////////////////// 70 71DRMSource::DRMSource(const sp<MediaSource> &mediaSource, 72 DecryptHandle* decryptHandle, int32_t trackId, DrmBuffer* ipmpBox) 73 : mOriginalMediaSource(mediaSource), 74 mDecryptHandle(decryptHandle), 75 mTrackId(trackId), 76 mNALLengthSize(0), 77 mWantsNALFragments(false) { 78 gDrmManagerClient->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 101DRMSource::~DRMSource() { 102 Mutex::Autolock autoLock(mDRMLock); 103 gDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId); 104} 105 106status_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 118status_t DRMSource::stop() { 119 return mOriginalMediaSource->stop(); 120} 121 122sp<MetaData> DRMSource::getFormat() { 123 return mOriginalMediaSource->getFormat(); 124} 125 126status_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 = gDrmManagerClient->decrypt(mDecryptHandle, mTrackId, 144 &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != DRM_NO_ERROR) { 145 146 if (decryptedDrmBuffer.data) { 147 delete [] decryptedDrmBuffer.data; 148 decryptedDrmBuffer.data = NULL; 149 } 150 151 if (err == DRM_ERROR_LICENSE_EXPIRED) { 152 return ERROR_NO_LICENSE; 153 } else { 154 return ERROR_IO; 155 } 156 } 157 CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer); 158 159 const char *mime; 160 CHECK(getFormat()->findCString(kKeyMIMEType, &mime)); 161 162 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) { 163 uint8_t *dstData = (uint8_t*)src; 164 size_t srcOffset = 0; 165 size_t dstOffset = 0; 166 167 len = decryptedDrmBuffer.length; 168 while (srcOffset < len) { 169 CHECK(srcOffset + mNALLengthSize <= len); 170 size_t nalLength = 0; 171 const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]); 172 173 switch (mNALLengthSize) { 174 case 1: 175 nalLength = *data; 176 break; 177 case 2: 178 nalLength = U16_AT(data); 179 break; 180 case 3: 181 nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]); 182 break; 183 case 4: 184 nalLength = U32_AT(data); 185 break; 186 default: 187 CHECK(!"Should not be here."); 188 break; 189 } 190 191 srcOffset += mNALLengthSize; 192 193 if (srcOffset + nalLength > len) { 194 if (decryptedDrmBuffer.data) { 195 delete [] decryptedDrmBuffer.data; 196 decryptedDrmBuffer.data = NULL; 197 } 198 199 return ERROR_MALFORMED; 200 } 201 202 if (nalLength == 0) { 203 continue; 204 } 205 206 CHECK(dstOffset + 4 <= (*buffer)->size()); 207 208 dstData[dstOffset++] = 0; 209 dstData[dstOffset++] = 0; 210 dstData[dstOffset++] = 0; 211 dstData[dstOffset++] = 1; 212 memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength); 213 srcOffset += nalLength; 214 dstOffset += nalLength; 215 } 216 217 CHECK_EQ(srcOffset, len); 218 (*buffer)->set_range((*buffer)->range_offset(), dstOffset); 219 220 } else { 221 memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length); 222 (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length); 223 } 224 225 if (decryptedDrmBuffer.data) { 226 delete [] decryptedDrmBuffer.data; 227 decryptedDrmBuffer.data = NULL; 228 } 229 230 return OK; 231} 232 233//////////////////////////////////////////////////////////////////////////////// 234 235DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime) 236 : mDataSource(source), 237 mDecryptHandle(NULL) { 238 mOriginalExtractor = MediaExtractor::Create(source, mime); 239 mOriginalExtractor->setDrmFlag(true); 240 241 DrmManagerClient *client; 242 source->getDrmInfo(&mDecryptHandle, &client); 243} 244 245DRMExtractor::~DRMExtractor() { 246} 247 248size_t DRMExtractor::countTracks() { 249 return mOriginalExtractor->countTracks(); 250} 251 252sp<MediaSource> DRMExtractor::getTrack(size_t index) { 253 sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index); 254 originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1); 255 256 int32_t trackID; 257 CHECK(getTrackMetaData(index, 0)->findInt32(kKeyTrackID, &trackID)); 258 259 DrmBuffer ipmpBox; 260 ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length)); 261 CHECK(ipmpBox.length > 0); 262 263 return new DRMSource(originalMediaSource, mDecryptHandle, trackID, &ipmpBox); 264} 265 266sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) { 267 return mOriginalExtractor->getTrackMetaData(index, flags); 268} 269 270sp<MetaData> DRMExtractor::getMetaData() { 271 return mOriginalExtractor->getMetaData(); 272} 273 274static Mutex gDRMSnifferMutex; 275bool SniffDRM( 276 const sp<DataSource> &source, String8 *mimeType, float *confidence, 277 sp<AMessage> *) { 278 { 279 Mutex::Autolock autoLock(gDRMSnifferMutex); 280 if (gDrmManagerClient == NULL) { 281 gDrmManagerClient = new DrmManagerClient(); 282 } 283 284 if (gDrmManagerClient == NULL) { 285 return false; 286 } 287 } 288 289 DecryptHandle *decryptHandle = source->DrmInitialization(gDrmManagerClient); 290 291 if (decryptHandle != NULL) { 292 if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) { 293 *mimeType = String8("drm+container_based+") + decryptHandle->mimeType; 294 } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) { 295 *mimeType = String8("drm+es_based+") + decryptHandle->mimeType; 296 } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) { 297 *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM; 298 LOGW("SniffWVM: found match\n"); 299 } 300 *confidence = 10.0f; 301 302 return true; 303 } 304 305 return false; 306} 307} //namespace android 308 309