blob: 63cb43012458d79ec1730a14cead26b4ee3bf186 [file] [log] [blame]
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001/*
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"
Gloria Wangdcd25ef2010-06-22 13:55:38 -070018
19#include <arpa/inet.h>
20#include <utils/String8.h>
James Dongf1d5aa12012-02-06 23:46:37 -080021#include <media/stagefright/foundation/ADebug.h>
Gloria Wangdcd25ef2010-06-22 13:55:38 -070022#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>
Gloria Wangdcd25ef2010-06-22 13:55:38 -070029
30#include <drm/drm_framework_common.h>
31#include <utils/Errors.h>
32
33
34namespace android {
35
Gloria Wangdcd25ef2010-06-22 13:55:38 -070036class DRMSource : public MediaSource {
37public:
38 DRMSource(const sp<MediaSource> &mediaSource,
Gloria Wangb5ce3612011-02-24 16:40:57 -080039 const sp<DecryptHandle> &decryptHandle,
Gloria Wang889b3402011-02-07 11:41:11 -080040 DrmManagerClient *managerClient,
41 int32_t trackId, DrmBuffer *ipmpBox);
Gloria Wangdcd25ef2010-06-22 13:55:38 -070042
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
49protected:
50 virtual ~DRMSource();
51
52private:
53 sp<MediaSource> mOriginalMediaSource;
Gloria Wangb5ce3612011-02-24 16:40:57 -080054 sp<DecryptHandle> mDecryptHandle;
Gloria Wang889b3402011-02-07 11:41:11 -080055 DrmManagerClient* mDrmManagerClient;
Gloria Wangdcd25ef2010-06-22 13:55:38 -070056 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
67DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
Gloria Wangb5ce3612011-02-24 16:40:57 -080068 const sp<DecryptHandle> &decryptHandle,
Gloria Wang889b3402011-02-07 11:41:11 -080069 DrmManagerClient *managerClient,
70 int32_t trackId, DrmBuffer *ipmpBox)
Gloria Wangdcd25ef2010-06-22 13:55:38 -070071 : mOriginalMediaSource(mediaSource),
72 mDecryptHandle(decryptHandle),
Gloria Wang889b3402011-02-07 11:41:11 -080073 mDrmManagerClient(managerClient),
Gloria Wangdcd25ef2010-06-22 13:55:38 -070074 mTrackId(trackId),
75 mNALLengthSize(0),
76 mWantsNALFragments(false) {
Gloria Wang8f641342011-02-08 13:24:08 -080077 CHECK(mDrmManagerClient);
Gloria Wang889b3402011-02-07 11:41:11 -080078 mDrmManagerClient->initializeDecryptUnit(
Gloria Wangdcd25ef2010-06-22 13:55:38 -070079 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);
Gloria Wang889b3402011-02-07 11:41:11 -0800103 mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700104}
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
Gloria Wang889b3402011-02-07 11:41:11 -0800143 if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
Gloria Wang73407432011-04-29 10:44:46 -0700144 &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700145
146 if (decryptedDrmBuffer.data) {
147 delete [] decryptedDrmBuffer.data;
148 decryptedDrmBuffer.data = NULL;
149 }
150
Gloria Wang73407432011-04-29 10:44:46 -0700151 return err;
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700152 }
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
231DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
232 : mDataSource(source),
Gloria Wang889b3402011-02-07 11:41:11 -0800233 mDecryptHandle(NULL),
234 mDrmManagerClient(NULL) {
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700235 mOriginalExtractor = MediaExtractor::Create(source, mime);
236 mOriginalExtractor->setDrmFlag(true);
Glenn Kasten8ddeebb2011-02-21 09:37:13 -0800237 mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700238
Gloria Wangb5ce3612011-02-24 16:40:57 -0800239 source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700240}
241
242DRMExtractor::~DRMExtractor() {
243}
244
245size_t DRMExtractor::countTracks() {
246 return mOriginalExtractor->countTracks();
247}
248
249sp<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
Gloria Wang889b3402011-02-07 11:41:11 -0800260 return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
261 trackID, &ipmpBox);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700262}
263
264sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
265 return mOriginalExtractor->getTrackMetaData(index, flags);
266}
267
268sp<MetaData> DRMExtractor::getMetaData() {
269 return mOriginalExtractor->getMetaData();
270}
271
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700272bool SniffDRM(
Gloria Wanga9741a92010-10-25 15:23:04 -0700273 const sp<DataSource> &source, String8 *mimeType, float *confidence,
274 sp<AMessage> *) {
Gloria Wangb5ce3612011-02-24 16:40:57 -0800275 sp<DecryptHandle> decryptHandle = source->DrmInitialization();
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700276
277 if (decryptHandle != NULL) {
278 if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
Gloria Wangb3714262010-11-01 15:53:16 -0700279 *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
James Dong9d2f3862012-01-10 08:24:37 -0800280 *confidence = 10.0f;
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700281 } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
Gloria Wangb3714262010-11-01 15:53:16 -0700282 *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
James Dong9d2f3862012-01-10 08:24:37 -0800283 *confidence = 10.0f;
284 } else {
285 return false;
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700286 }
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700287
288 return true;
289 }
290
291 return false;
292}
293} //namespace android
294