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

Side by Side Diff: media/cdm/cenc_utils.cc

Issue 1145853002: DONT REVIEW: Move GetPsshData() into cenc_utils (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « media/cdm/cenc_utils.h ('k') | media/cdm/cenc_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/cdm/cenc_utils.h" 5 #include "media/cdm/cenc_utils.h"
6 6
7 #include "media/base/bit_reader.h" 7 #include "media/base/bit_reader.h"
8 8
9 namespace media { 9 namespace media {
10 10
(...skipping 15 matching lines...) Expand all
26 // unsigned int(8)[16] SystemID; 26 // unsigned int(8)[16] SystemID;
27 // if (version > 0) 27 // if (version > 0)
28 // { 28 // {
29 // unsigned int(32) KID_count; 29 // unsigned int(32) KID_count;
30 // { 30 // {
31 // unsigned int(8)[16] KID; 31 // unsigned int(8)[16] KID;
32 // } [KID_count] 32 // } [KID_count]
33 // } 33 // }
34 // unsigned int(32) DataSize; 34 // unsigned int(32) DataSize;
35 // unsigned int(8)[DataSize] Data; 35 // unsigned int(8)[DataSize] Data;
36 // Only versions 0 and 1 of the 'pssh' boxes are supported. Any other versions
37 // are ignored.
36 38
37 // Minimum size of a 'pssh' box includes all the required fields (size, type, 39 // Minimum size of a 'pssh' box includes all the required fields (size, type,
38 // version, flags, SystemID, DataSize). 40 // version, flags, SystemID, DataSize).
39 const int kMinimumBoxSizeInBytes = 32; 41 const uint32_t kMinimumBoxSizeInBytes = 32;
42
43 // Size of a SystemID field in bytes.
44 const uint32_t kSystemIDSizeInBytes = 16;
45
46 // Size of a KID field in bytes.
47 const uint32_t kKIDSizeInBytes = 16;
40 48
41 // SystemID for the Common System. 49 // SystemID for the Common System.
42 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system 50 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system
43 const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, 51 const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec,
44 0xc0, 0xb2, 0x4d, 0x02, 52 0xc0, 0xb2, 0x4d, 0x02,
45 0xac, 0xe3, 0x3c, 0x1e, 53 0xac, 0xe3, 0x3c, 0x1e,
46 0x52, 0xe2, 0xfb, 0x4b }; 54 0x52, 0xe2, 0xfb, 0x4b };
47 55
48 #define RCHECK(x) \ 56 #define RCHECK(x) \
49 do { \ 57 do { \
50 if (!(x)) \ 58 if (!(x)) \
51 return false; \ 59 return false; \
52 } while (0) 60 } while (0)
53 61
54 // Helper function to read up to 32 bits from a bit stream. 62 // Helper function to read up to 32 bits from a bit stream.
55 static uint32_t ReadBits(BitReader* reader, int num_bits) { 63 static uint32_t ReadBits(BitReader* reader, int num_bits) {
56 DCHECK_GE(reader->bits_available(), num_bits); 64 DCHECK_GE(reader->bits_available(), num_bits);
57 DCHECK((num_bits > 0) && (num_bits <= 32)); 65 DCHECK((num_bits > 0) && (num_bits <= 32));
58 uint32_t value; 66 uint32_t value;
59 reader->ReadBits(num_bits, &value); 67 reader->ReadBits(num_bits, &value);
60 return value; 68 return value;
61 } 69 }
62 70
63 // Checks whether the next 16 bytes matches the Common SystemID. 71 // Return the number of bytes available in |reader|.
64 // Assumes |reader| has enough data. 72 static uint32_t BytesAvailable(BitReader* reader) {
65 static bool IsCommonSystemID(BitReader* reader) { 73 return reader->bits_available() / 8;
66 for (uint32_t i = 0; i < arraysize(kCommonSystemId); ++i) { 74 }
67 if (ReadBits(reader, 8) != kCommonSystemId[i]) 75
76 // Checks whether the next bytes in |reader| match the specified |system_id|.
77 static bool MatchSystemID(BitReader* reader,
78 const std::vector<uint8_t>& system_id) {
79 RCHECK(BytesAvailable(reader) >= system_id.size());
80 for (const auto& data : system_id) {
81 if (ReadBits(reader, 8) != data)
68 return false; 82 return false;
69 } 83 }
70 return true; 84 return true;
71 } 85 }
72 86
73 // Checks that |reader| contains a valid 'ppsh' box header. |reader| is updated 87 // Checks that |reader| contains a valid 'ppsh' box header. |reader| is updated
74 // to point to the content immediately following the box header. Returns true 88 // to point to the content immediately following the box header. Returns true
75 // if the header looks valid and |reader| contains enough data for the size of 89 // if the header looks valid and |reader| contains enough data for the size of
76 // header. |size| is updated as the computed size of the box header. Otherwise 90 // header. |size| is updated as the computed size of the box header. Otherwise
77 // false is returned. 91 // false is returned.
78 static bool ValidBoxHeader(BitReader* reader, uint32* size) { 92 static bool ValidBoxHeader(BitReader* reader, uint32_t* size) {
79 // Enough data for a miniumum size 'pssh' box? 93 // Enough data for a miniumum size 'pssh' box?
80 uint32 available_bytes = reader->bits_available() / 8; 94 uint32_t available_bytes = BytesAvailable(reader);
81 RCHECK(available_bytes >= kMinimumBoxSizeInBytes); 95 RCHECK(available_bytes >= kMinimumBoxSizeInBytes);
82 96
83 *size = ReadBits(reader, 32); 97 *size = ReadBits(reader, 32);
84 98
85 // Must be a 'pssh' box or else fail. 99 // Must be a 'pssh' box or else fail.
86 RCHECK(ReadBits(reader, 8) == 'p'); 100 RCHECK(ReadBits(reader, 8) == 'p');
87 RCHECK(ReadBits(reader, 8) == 's'); 101 RCHECK(ReadBits(reader, 8) == 's');
88 RCHECK(ReadBits(reader, 8) == 's'); 102 RCHECK(ReadBits(reader, 8) == 's');
89 RCHECK(ReadBits(reader, 8) == 'h'); 103 RCHECK(ReadBits(reader, 8) == 'h');
90 104
91 if (*size == 1) { 105 if (*size == 1) {
92 // If largesize > 2**32 it is too big. 106 // If largesize > 2**32 it is too big.
93 RCHECK(ReadBits(reader, 32) == 0); 107 RCHECK(ReadBits(reader, 32) == 0);
94 *size = ReadBits(reader, 32); 108 *size = ReadBits(reader, 32);
95 } else if (*size == 0) { 109 } else if (*size == 0) {
96 *size = available_bytes; 110 *size = available_bytes;
97 } 111 }
98 112
99 // Check that the buffer contains at least size bytes. 113 // Check that the buffer contains at least size bytes.
100 return available_bytes >= *size; 114 return available_bytes >= *size;
101 } 115 }
102 116
103 bool ValidatePsshInput(const std::vector<uint8_t>& input) { 117 bool ValidatePsshInput(const std::vector<uint8_t>& input) {
104 size_t offset = 0; 118 size_t offset = 0;
105 while (offset < input.size()) { 119 while (offset < input.size()) {
106 // Create a BitReader over the remaining part of the buffer. 120 // Create a BitReader over the remaining part of the buffer.
107 BitReader reader(&input[offset], input.size() - offset); 121 BitReader reader(&input[offset], input.size() - offset);
108 uint32 size; 122 uint32_t size;
109 RCHECK(ValidBoxHeader(&reader, &size)); 123 RCHECK(ValidBoxHeader(&reader, &size));
110 124
111 // Update offset to point at the next 'pssh' box (may not be one). 125 // Update offset to point at the next 'pssh' box (may not be one).
112 offset += size; 126 offset += size;
113 } 127 }
114 128
115 // Only valid if this contains 0 or more 'pssh' boxes. 129 // Only valid if this contains 0 or more 'pssh' boxes.
116 return offset == input.size(); 130 return offset == input.size();
117 } 131 }
118 132
119 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, 133 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input,
120 KeyIdList* key_ids) { 134 KeyIdList* key_ids) {
121 size_t offset = 0; 135 size_t offset = 0;
122 KeyIdList result; 136 KeyIdList result;
137 std::vector<uint8_t> common_system_id(
138 kCommonSystemId, kCommonSystemId + arraysize(kCommonSystemId));
123 139
124 while (offset < input.size()) { 140 while (offset < input.size()) {
125 BitReader reader(&input[offset], input.size() - offset); 141 BitReader reader(&input[offset], input.size() - offset);
126 uint32 size; 142 uint32_t size;
127 RCHECK(ValidBoxHeader(&reader, &size)); 143 RCHECK(ValidBoxHeader(&reader, &size));
128 144
129 // Update offset to point at the next 'pssh' box (may not be one). 145 // Update offset to point at the next 'pssh' box (may not be one).
130 offset += size; 146 offset += size;
131 147
132 // Check the version, as KIDs only available if version > 0. 148 // Check the version. Only version 0 and 1 'pssh' boxes are supported.
149 // However, KIDs only available if version > 0, so skip if version != 1.
133 uint8_t version = ReadBits(&reader, 8); 150 uint8_t version = ReadBits(&reader, 8);
134 if (version == 0) 151 if (version != 1)
135 continue; 152 continue;
136 153
137 // flags must be 0. If not, assume incorrect 'pssh' box and move to the 154 // flags must be 0. If not, assume incorrect 'pssh' box and move to the
138 // next one. 155 // next one.
139 if (ReadBits(&reader, 24) != 0) 156 if (ReadBits(&reader, 24) != 0)
140 continue; 157 continue;
141 158
142 // Validate SystemID 159 // Validate SystemID
143 RCHECK(static_cast<uint32_t>(reader.bits_available()) >= 160 if (!MatchSystemID(&reader, common_system_id))
144 arraysize(kCommonSystemId) * 8);
145 if (!IsCommonSystemID(&reader))
146 continue; // Not Common System, so try the next pssh box. 161 continue; // Not Common System, so try the next pssh box.
147 162
148 // Since version > 0, next field is the KID_count. 163 // Since version > 0, next field is the KID_count.
149 RCHECK(static_cast<uint32_t>(reader.bits_available()) >= 164 RCHECK(BytesAvailable(&reader) >= sizeof(uint32_t));
150 sizeof(uint32_t) * 8);
151 uint32_t count = ReadBits(&reader, 32); 165 uint32_t count = ReadBits(&reader, 32);
152 166
153 if (count == 0) 167 if (count == 0)
154 continue; 168 continue;
155 169
156 // Make sure there is enough data for all the KIDs specified, and then 170 // Make sure there is enough data for all the KIDs specified, and then
157 // extract them. 171 // extract them.
158 RCHECK(static_cast<uint32_t>(reader.bits_available()) > count * 16 * 8); 172 RCHECK(BytesAvailable(&reader) > count * kKIDSizeInBytes);
159 while (count > 0) { 173 while (count > 0) {
160 std::vector<uint8_t> key; 174 std::vector<uint8_t> key;
161 key.reserve(16); 175 key.reserve(kKIDSizeInBytes);
162 for (int i = 0; i < 16; ++i) { 176 for (uint32_t i = 0; i < kKIDSizeInBytes; ++i) {
163 key.push_back(ReadBits(&reader, 8)); 177 key.push_back(ReadBits(&reader, 8));
164 } 178 }
165 result.push_back(key); 179 result.push_back(key);
166 --count; 180 --count;
167 } 181 }
168 182
169 // Don't bother checking DataSize and Data. 183 // Don't bother checking DataSize and Data.
170 } 184 }
171 185
172 key_ids->swap(result); 186 key_ids->swap(result);
173 187
174 // TODO(jrummell): This should return true only if there was at least one 188 // TODO(jrummell): This should return true only if there was at least one
175 // key ID present. However, numerous test files don't contain the 'pssh' box 189 // key ID present. However, numerous test files don't contain the 'pssh' box
176 // for Common Format, so no keys are found. http://crbug.com/460308 190 // for Common Format, so no keys are found. http://crbug.com/460308
177 return true; 191 return true;
178 } 192 }
179 193
194 bool GetPsshData(const std::vector<uint8_t>& input,
195 const std::vector<uint8_t>& system_id,
196 std::vector<uint8_t>* pssh_data) {
197 DCHECK_EQ(system_id.size(), kSystemIDSizeInBytes);
198 size_t offset = 0;
199
200 while (offset < input.size()) {
201 // Create a BitReader over the remaining part of the buffer.
202 BitReader reader(&input[offset], input.size() - offset);
203 uint32_t size;
204 RCHECK(ValidBoxHeader(&reader, &size));
205
206 // Update offset to point at the next 'pssh' box (may not be one).
207 offset += size;
208
209 // Check the version. Only version 0 and 1 'pssh' boxes are supported.
210 // Other versions are skipped.
211 uint8_t version = ReadBits(&reader, 8);
212 if (version > 1)
213 continue;
214
215 // flags must be 0. If not, assume incorrect 'pssh' box and move to the
216 // next one.
217 if (ReadBits(&reader, 24) != 0)
218 continue;
219
220 // Validate SystemID. If not, try the next 'pssh' box.
221 if (!MatchSystemID(&reader, system_id))
222 continue;
223
224 // If version > 0, next field is the KID_count. Skip any KIDs in the
225 // 'pssh' box.
226 if (version > 0) {
227 RCHECK(BytesAvailable(&reader) >= sizeof(uint32_t));
228 uint32_t count = ReadBits(&reader, 32);
229 RCHECK(reader.SkipBits(count * kKIDSizeInBytes * 8));
230 }
231
232 // Now get the datasize.
233 RCHECK(BytesAvailable(&reader) >= sizeof(uint32_t));
234 uint32_t datasize = ReadBits(&reader, 32);
235
236 // Now get the data and return it.
237 RCHECK(BytesAvailable(&reader) >= datasize);
238 for (uint32_t i = 0; i < datasize; ++i) {
239 pssh_data->push_back(ReadBits(&reader, 8));
240 }
241 return true;
242 }
243
244 // No matching 'pssh' box found, so fail.
245 return false;
246 }
247
180 } // namespace media 248 } // namespace media
OLDNEW
« no previous file with comments | « media/cdm/cenc_utils.h ('k') | media/cdm/cenc_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698