Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: components/cdm/browser/widevine_drm_delegate_android.cc

Issue 962793005: Adds MediaClientAndroid to support embedder/MediaDrmBridge interaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: overhaul: creates MediaClientAndroid (browser-side client), eliminates Java-based MediaDrmBridge ke… Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/cdm/browser/widevine_drm_delegate_android.h"
6
7 #include "base/logging.h"
8
9 namespace cdm {
10
11 namespace {
12
13 uint32_t ReadUint32(const uint8_t* data) {
14 uint32_t value = 0;
15 for (int i = 0; i < 4; ++i)
16 value = (value << 8) | data[i];
17 return value;
18 }
19
20 uint64_t ReadUint64(const uint8_t* data) {
21 uint64_t value = 0;
22 for (int i = 0; i < 8; ++i)
23 value = (value << 8) | data[i];
24 return value;
25 }
26
27 // The structure of an ISO CENC Protection System Specific Header (PSSH) box is
28 // as follows. (See ISO/IEC FDIS 23001-7:2011(E).)
29 // Note: ISO boxes use big-endian values.
30 //
31 // PSSH {
32 // uint32_t Size
33 // uint32_t Type
34 // uint64_t LargeSize # Field is only present if value(Size) == 1.
35 // uint32_t VersionAndFlags
36 // uint8_t[16] SystemId
37 // uint32_t DataSize
38 // uint8_t[DataSize] Data
39 // }
40 const int kBoxHeaderSize = 8; // Box's header contains Size and Type.
41 const int kBoxLargeSizeSize = 8;
42 const int kPsshVersionFlagSize = 4;
43 const int kPsshSystemIdSize = 16;
44 const int kPsshDataSizeSize = 4;
45 const uint32_t kTencType = 0x74656e63;
46 const uint32_t kPsshType = 0x70737368;
47
48 const uint8_t kWidevineUuid[16] = {
49 0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
50 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED };
51
52 // Tries to find a PSSH box with the Widevine UUID, parses the
53 // "Data" of the box and put it in |pssh_data|. Returns true if such a box is
54 // found and successfully parsed. Returns false otherwise.
55 // Notes:
56 // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box
57 // will be set in |pssh_data|.
58 // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped.
59 bool GetPsshData(const uint8_t* data,
60 int data_size,
61 std::vector<uint8_t>* pssh_data) {
62 const uint8_t* cur = data;
63 const uint8_t* data_end = data + data_size;
64 int bytes_left = data_size;
65
66 while (bytes_left > 0) {
67 const uint8_t* box_head = cur;
68
69 if (bytes_left < kBoxHeaderSize)
70 return false;
71
72 uint64_t box_size = ReadUint32(cur);
73 uint32_t type = ReadUint32(cur + 4);
74 cur += kBoxHeaderSize;
75 bytes_left -= kBoxHeaderSize;
76
77 if (box_size == 1) { // LargeSize is present.
78 if (bytes_left < kBoxLargeSizeSize)
79 return false;
80
81 box_size = ReadUint64(cur);
82 cur += kBoxLargeSizeSize;
83 bytes_left -= kBoxLargeSizeSize;
84 } else if (box_size == 0) {
85 box_size = bytes_left + kBoxHeaderSize;
86 }
87
88 const uint8_t* box_end = box_head + box_size;
89 if (data_end < box_end)
90 return false;
91
92 if (type == kTencType) {
93 // Skip 'tenc' box.
94 cur = box_end;
95 bytes_left = data_end - cur;
96 continue;
97 } else if (type != kPsshType) {
98 return false;
99 }
100
101 const int kPsshBoxMinimumSize =
102 kPsshVersionFlagSize + kPsshSystemIdSize + kPsshDataSizeSize;
103 if (box_end < cur + kPsshBoxMinimumSize)
104 return false;
105
106 uint32_t version_and_flags = ReadUint32(cur);
107 cur += kPsshVersionFlagSize;
108 bytes_left -= kPsshVersionFlagSize;
109 if (version_and_flags != 0)
110 return false;
111
112 DCHECK_GE(bytes_left, kPsshSystemIdSize);
113 if (!std::equal(kWidevineUuid,
114 kWidevineUuid + sizeof(kWidevineUuid), cur)) {
115 cur = box_end;
116 bytes_left = data_end - cur;
117 continue;
118 }
119
120 cur += kPsshSystemIdSize;
121 bytes_left -= kPsshSystemIdSize;
122
123 uint32_t data_size = ReadUint32(cur);
124 cur += kPsshDataSizeSize;
125 bytes_left -= kPsshDataSizeSize;
126
127 if (box_end < cur + data_size)
128 return false;
129
130 pssh_data->assign(cur, cur + data_size);
131 return true;
132 }
133
134 return false;
135 }
136
137 }
138
139 WidevineDrmDelegateAndroid::WidevineDrmDelegateAndroid() {
140 }
141
142 WidevineDrmDelegateAndroid::~WidevineDrmDelegateAndroid() {
143 }
144
145 const std::vector<uint8_t> WidevineDrmDelegateAndroid::GetUUID() const {
146 return std::vector<uint8_t>(kWidevineUuid,
147 kWidevineUuid + arraysize(kWidevineUuid));
xhwang 2015/04/24 04:52:23 alignment is off?
gunsch 2015/04/27 23:44:12 Heh, I think I had done a find/replace in the CL o
148 }
149
150 bool WidevineDrmDelegateAndroid::OnCreateSession(
151 const media::EmeInitDataType init_data_type,
152 const uint8_t* init_data,
153 int init_data_length,
154 std::vector<uint8_t>& init_data_out,
155 std::vector<std::string>& optional_parameters_out) {
156 // Widevine MediaDrm plugin only accepts the "data" part of the PSSH box as
157 // the init data when using MP4 container.
158 if (init_data_type == media::EmeInitDataType::CENC) {
159 if (!GetPsshData(init_data, init_data_length, &init_data_out))
160 return false;
161 }
162 return true;
xhwang 2015/04/24 04:52:23 tiny nit: we like to return early, so if (init_d
gunsch 2015/04/27 23:44:12 Done.
163 }
164
165 } // namespace cdm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698