DRMExtractor.cpp revision d5770917a50a828cb4337c2a392b3e4a375624b9
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    {
278        Mutex::Autolock autoLock(gDRMSnifferMutex);
279        if (gDrmManagerClient == NULL) {
280            gDrmManagerClient = new DrmManagerClient();
281        }
282    }
283
284    DecryptHandle *decryptHandle = source->DrmInitialization(gDrmManagerClient);
285
286    if (decryptHandle != NULL) {
287        if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
288            *mimeType = String8("drm+container_based+");
289        } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
290            *mimeType = String8("drm+es_based+");
291        }
292
293        *mimeType += decryptHandle->mimeType;
294        *confidence = 10.0f;
295
296        return true;
297    }
298
299    return false;
300}
301} //namespace android
302
303