DRMExtractor.cpp revision adc4d9c86d45376a3936a67616c2a302f08b5f21
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 41class DRMSource : public MediaSource { 42public: 43 DRMSource(const sp<MediaSource> &mediaSource, 44 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 54protected: 55 virtual ~DRMSource(); 56 57private: 58 sp<MediaSource> mOriginalMediaSource; 59 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 72DRMSource::DRMSource(const sp<MediaSource> &mediaSource, 73 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 106DRMSource::~DRMSource() { 107 Mutex::Autolock autoLock(mDRMLock); 108 mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId); 109} 110 111status_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 123status_t DRMSource::stop() { 124 return mOriginalMediaSource->stop(); 125} 126 127sp<MetaData> DRMSource::getFormat() { 128 return mOriginalMediaSource->getFormat(); 129} 130 131status_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)) != DRM_NO_ERROR) { 150 151 if (decryptedDrmBuffer.data) { 152 delete [] decryptedDrmBuffer.data; 153 decryptedDrmBuffer.data = NULL; 154 } 155 156 if (err == DRM_ERROR_LICENSE_EXPIRED) { 157 return ERROR_NO_LICENSE; 158 } else { 159 return ERROR_IO; 160 } 161 } 162 CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer); 163 164 const char *mime; 165 CHECK(getFormat()->findCString(kKeyMIMEType, &mime)); 166 167 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) { 168 uint8_t *dstData = (uint8_t*)src; 169 size_t srcOffset = 0; 170 size_t dstOffset = 0; 171 172 len = decryptedDrmBuffer.length; 173 while (srcOffset < len) { 174 CHECK(srcOffset + mNALLengthSize <= len); 175 size_t nalLength = 0; 176 const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]); 177 178 switch (mNALLengthSize) { 179 case 1: 180 nalLength = *data; 181 break; 182 case 2: 183 nalLength = U16_AT(data); 184 break; 185 case 3: 186 nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]); 187 break; 188 case 4: 189 nalLength = U32_AT(data); 190 break; 191 default: 192 CHECK(!"Should not be here."); 193 break; 194 } 195 196 srcOffset += mNALLengthSize; 197 198 if (srcOffset + nalLength > len) { 199 if (decryptedDrmBuffer.data) { 200 delete [] decryptedDrmBuffer.data; 201 decryptedDrmBuffer.data = NULL; 202 } 203 204 return ERROR_MALFORMED; 205 } 206 207 if (nalLength == 0) { 208 continue; 209 } 210 211 CHECK(dstOffset + 4 <= (*buffer)->size()); 212 213 dstData[dstOffset++] = 0; 214 dstData[dstOffset++] = 0; 215 dstData[dstOffset++] = 0; 216 dstData[dstOffset++] = 1; 217 memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength); 218 srcOffset += nalLength; 219 dstOffset += nalLength; 220 } 221 222 CHECK_EQ(srcOffset, len); 223 (*buffer)->set_range((*buffer)->range_offset(), dstOffset); 224 225 } else { 226 memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length); 227 (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length); 228 } 229 230 if (decryptedDrmBuffer.data) { 231 delete [] decryptedDrmBuffer.data; 232 decryptedDrmBuffer.data = NULL; 233 } 234 235 return OK; 236} 237 238//////////////////////////////////////////////////////////////////////////////// 239 240DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime) 241 : mDataSource(source), 242 mDecryptHandle(NULL), 243 mDrmManagerClient(NULL) { 244 mOriginalExtractor = MediaExtractor::Create(source, mime); 245 mOriginalExtractor->setDrmFlag(true); 246 247 source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); 248} 249 250DRMExtractor::~DRMExtractor() { 251} 252 253size_t DRMExtractor::countTracks() { 254 return mOriginalExtractor->countTracks(); 255} 256 257sp<MediaSource> DRMExtractor::getTrack(size_t index) { 258 sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index); 259 originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1); 260 261 int32_t trackID; 262 CHECK(getTrackMetaData(index, 0)->findInt32(kKeyTrackID, &trackID)); 263 264 DrmBuffer ipmpBox; 265 ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length)); 266 CHECK(ipmpBox.length > 0); 267 268 return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient, 269 trackID, &ipmpBox); 270} 271 272sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) { 273 return mOriginalExtractor->getTrackMetaData(index, flags); 274} 275 276sp<MetaData> DRMExtractor::getMetaData() { 277 return mOriginalExtractor->getMetaData(); 278} 279 280bool SniffDRM( 281 const sp<DataSource> &source, String8 *mimeType, float *confidence, 282 sp<AMessage> *) { 283 DecryptHandle *decryptHandle = source->DrmInitialization(); 284 285 if (decryptHandle != NULL) { 286 if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) { 287 *mimeType = String8("drm+container_based+") + decryptHandle->mimeType; 288 } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) { 289 *mimeType = String8("drm+es_based+") + decryptHandle->mimeType; 290 } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) { 291 *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM; 292 LOGW("SniffWVM: found match\n"); 293 } 294 *confidence = 10.0f; 295 296 return true; 297 } 298 299 return false; 300} 301} //namespace android 302 303