blob: 1f3d58181471c60527f910277751abd73964a055 [file] [log] [blame]
Gloria Wangd5770912010-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"
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
Gloria Wangd5770912010-06-22 13:55:38 -070041class DRMSource : public MediaSource {
42public:
43 DRMSource(const sp<MediaSource> &mediaSource,
Gloria Wangae775272011-02-24 16:40:57 -080044 const sp<DecryptHandle> &decryptHandle,
Gloria Wangc2dc4722011-02-07 11:41:11 -080045 DrmManagerClient *managerClient,
46 int32_t trackId, DrmBuffer *ipmpBox);
Gloria Wangd5770912010-06-22 13:55:38 -070047
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;
Gloria Wangae775272011-02-24 16:40:57 -080059 sp<DecryptHandle> mDecryptHandle;
Gloria Wangc2dc4722011-02-07 11:41:11 -080060 DrmManagerClient* mDrmManagerClient;
Gloria Wangd5770912010-06-22 13:55:38 -070061 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,
Gloria Wangae775272011-02-24 16:40:57 -080073 const sp<DecryptHandle> &decryptHandle,
Gloria Wangc2dc4722011-02-07 11:41:11 -080074 DrmManagerClient *managerClient,
75 int32_t trackId, DrmBuffer *ipmpBox)
Gloria Wangd5770912010-06-22 13:55:38 -070076 : mOriginalMediaSource(mediaSource),
77 mDecryptHandle(decryptHandle),
Gloria Wangc2dc4722011-02-07 11:41:11 -080078 mDrmManagerClient(managerClient),
Gloria Wangd5770912010-06-22 13:55:38 -070079 mTrackId(trackId),
80 mNALLengthSize(0),
81 mWantsNALFragments(false) {
Gloria Wangadc4d9c2011-02-08 13:24:08 -080082 CHECK(mDrmManagerClient);
Gloria Wangc2dc4722011-02-07 11:41:11 -080083 mDrmManagerClient->initializeDecryptUnit(
Gloria Wangd5770912010-06-22 13:55:38 -070084 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);
Gloria Wangc2dc4722011-02-07 11:41:11 -0800108 mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
Gloria Wangd5770912010-06-22 13:55:38 -0700109}
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
Gloria Wangc2dc4722011-02-07 11:41:11 -0800148 if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
Gloria Wangf16e1ab2011-04-29 10:44:46 -0700149 &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
Gloria Wangd5770912010-06-22 13:55:38 -0700150
151 if (decryptedDrmBuffer.data) {
152 delete [] decryptedDrmBuffer.data;
153 decryptedDrmBuffer.data = NULL;
154 }
155
Gloria Wangf16e1ab2011-04-29 10:44:46 -0700156 return err;
Gloria Wangd5770912010-06-22 13:55:38 -0700157 }
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
236DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
237 : mDataSource(source),
Gloria Wangc2dc4722011-02-07 11:41:11 -0800238 mDecryptHandle(NULL),
239 mDrmManagerClient(NULL) {
Gloria Wangd5770912010-06-22 13:55:38 -0700240 mOriginalExtractor = MediaExtractor::Create(source, mime);
241 mOriginalExtractor->setDrmFlag(true);
Glenn Kasten5f630692011-02-21 09:37:13 -0800242 mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
Gloria Wangd5770912010-06-22 13:55:38 -0700243
Gloria Wangae775272011-02-24 16:40:57 -0800244 source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
Gloria Wangd5770912010-06-22 13:55:38 -0700245}
246
247DRMExtractor::~DRMExtractor() {
248}
249
250size_t DRMExtractor::countTracks() {
251 return mOriginalExtractor->countTracks();
252}
253
254sp<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
Gloria Wangc2dc4722011-02-07 11:41:11 -0800265 return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
266 trackID, &ipmpBox);
Gloria Wangd5770912010-06-22 13:55:38 -0700267}
268
269sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
270 return mOriginalExtractor->getTrackMetaData(index, flags);
271}
272
273sp<MetaData> DRMExtractor::getMetaData() {
274 return mOriginalExtractor->getMetaData();
275}
276
Gloria Wangd5770912010-06-22 13:55:38 -0700277bool SniffDRM(
Gloria Wangb8791472010-10-25 15:23:04 -0700278 const sp<DataSource> &source, String8 *mimeType, float *confidence,
279 sp<AMessage> *) {
Gloria Wangae775272011-02-24 16:40:57 -0800280 sp<DecryptHandle> decryptHandle = source->DrmInitialization();
Gloria Wangd5770912010-06-22 13:55:38 -0700281
282 if (decryptHandle != NULL) {
283 if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
Gloria Wangc2c22e72010-11-01 15:53:16 -0700284 *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
Gloria Wangd5770912010-06-22 13:55:38 -0700285 } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
Gloria Wangc2c22e72010-11-01 15:53:16 -0700286 *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
James Dongd70c64d2011-12-14 10:57:05 -0800287 } else if (decryptHandle->decryptApiType == DecryptApiType::WV_BASED) {
288 *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
289 LOGW("SniffWVM: found match\n");
Gloria Wangd5770912010-06-22 13:55:38 -0700290 }
James Dongd70c64d2011-12-14 10:57:05 -0800291 *confidence = 10.0f;
Gloria Wangd5770912010-06-22 13:55:38 -0700292
293 return true;
294 }
295
296 return false;
297}
298} //namespace android
299