blob: 5a4502ae9523b67b249c3835858f585de11daead [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2 * Copyright 2017 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//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayer2Drm"
19
20#include "NuPlayer2Drm.h"
21
22#include "NdkWrapper.h"
23#include <utils/Log.h>
24
25
26namespace android {
27
28Vector<DrmUUID> NuPlayer2Drm::parsePSSH(const void *pssh, size_t psshsize)
29{
30 Vector<DrmUUID> drmSchemes, empty;
31 const int DATALEN_SIZE = 4;
32
33 // the format of the buffer is 1 or more of:
34 // {
35 // 16 byte uuid
36 // 4 byte data length N
37 // N bytes of data
38 // }
39 // Determine the number of entries in the source data.
40 // Since we got the data from stagefright, we trust it is valid and properly formatted.
41
42 const uint8_t *data = (const uint8_t*)pssh;
43 size_t len = psshsize;
44 size_t numentries = 0;
45 while (len > 0) {
46 if (len < DrmUUID::UUID_SIZE) {
47 ALOGE("ParsePSSH: invalid PSSH data");
48 return empty;
49 }
50
51 const uint8_t *uuidPtr = data;
52
53 // skip uuid
54 data += DrmUUID::UUID_SIZE;
55 len -= DrmUUID::UUID_SIZE;
56
57 // get data length
58 if (len < DATALEN_SIZE) {
59 ALOGE("ParsePSSH: invalid PSSH data");
60 return empty;
61 }
62
63 uint32_t datalen = *((uint32_t*)data);
64 data += DATALEN_SIZE;
65 len -= DATALEN_SIZE;
66
67 if (len < datalen) {
68 ALOGE("ParsePSSH: invalid PSSH data");
69 return empty;
70 }
71
72 // skip the data
73 data += datalen;
74 len -= datalen;
75
76 DrmUUID _uuid(uuidPtr);
77 drmSchemes.add(_uuid);
78
79 ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
80 _uuid.toHexString().string(),
81 DrmUUID::arrayToHex(data, datalen).string()
82 );
83
84 numentries++;
85 }
86
87 return drmSchemes;
88}
89
90Vector<DrmUUID> NuPlayer2Drm::getSupportedDrmSchemes(const void *pssh, size_t psshsize)
91{
92 Vector<DrmUUID> psshDRMs = parsePSSH(pssh, psshsize);
93
94 Vector<DrmUUID> supportedDRMs;
95 for (size_t i = 0; i < psshDRMs.size(); i++) {
96 DrmUUID uuid = psshDRMs[i];
97 if (AMediaDrmWrapper::isCryptoSchemeSupported(uuid.ptr(), NULL)) {
98 supportedDRMs.add(uuid);
99 }
100 }
101
102 ALOGV("getSupportedDrmSchemes: psshDRMs: %zu supportedDRMs: %zu",
103 psshDRMs.size(), supportedDRMs.size());
104
105 return supportedDRMs;
106}
107
108// Parcel has only private copy constructor so passing it in rather than returning
109void NuPlayer2Drm::retrieveDrmInfo(const void *pssh, size_t psshsize, Parcel *parcel)
110{
111 // 1) PSSH bytes
112 parcel->writeUint32(psshsize);
113 parcel->writeByteArray(psshsize, (const uint8_t*)pssh);
114
115 ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO PSSH: size: %zu %s", psshsize,
116 DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());
117
118 // 2) supportedDRMs
119 Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
120 parcel->writeUint32(supportedDRMs.size());
121 for (size_t i = 0; i < supportedDRMs.size(); i++) {
122 DrmUUID uuid = supportedDRMs[i];
123 parcel->writeByteArray(DrmUUID::UUID_SIZE, uuid.ptr());
124
125 ALOGV("retrieveDrmInfo: MEDIA2_DRM_INFO supportedScheme[%zu] %s", i,
126 uuid.toHexString().string());
127 }
128}
129
130} // namespace android