OLD | NEW |
---|---|
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 "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "media/formats/mp4/box_definitions.h" | 8 #include "media/formats/mp4/box_definitions.h" |
9 #include "media/formats/mp4/box_reader.h" | 9 #include "media/formats/mp4/box_reader.h" |
10 | 10 |
11 namespace media { | 11 namespace media { |
12 | 12 |
13 // The initialization data for encrypted media files using the ISO Common | 13 // The initialization data for encrypted media files using the ISO Common |
14 // Encryption ('cenc') protection scheme may contain one or more protection | 14 // Encryption ('cenc') protection scheme may contain one or more protection |
15 // system specific header ('pssh') boxes. | 15 // system specific header ('pssh') boxes. |
16 // ref: https://w3c.github.io/encrypted-media/cenc-format.html | 16 // ref: https://w3c.github.io/encrypted-media/cenc-format.html |
17 | 17 |
18 // SystemID for the Common System. | 18 // Returns true if |input| contains only 1 or more valid 'pssh' boxes, false |
19 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system | 19 // otherwise. |pssh_boxes| is updated as the set of parsed 'pssh' boxes. |
20 const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, | 20 // Note: All boxes in |input| must be 'pssh' boxes. However, if they can't be |
21 0xc0, 0xb2, 0x4d, 0x02, | 21 // properly parsed (e.g. unsupported version), then they will be skipped. |
22 0xac, 0xe3, 0x3c, 0x1e, | |
23 0x52, 0xe2, 0xfb, 0x4b }; | |
24 | |
25 static bool ReadAllPsshBoxes( | 22 static bool ReadAllPsshBoxes( |
26 const std::vector<uint8_t>& input, | 23 const std::vector<uint8_t>& input, |
27 std::vector<mp4::FullProtectionSystemSpecificHeader>* pssh_boxes) { | 24 std::vector<mp4::FullProtectionSystemSpecificHeader>* pssh_boxes) { |
28 DCHECK(!input.empty()); | 25 DCHECK(!input.empty()); |
29 | 26 |
30 // Verify that |input| contains only 'pssh' boxes. ReadAllChildren() is | 27 // Verify that |input| contains only 'pssh' boxes. ReadAllChildren() is |
31 // templated, so it checks that each box in |input| matches the box type of | 28 // templated, so it checks that each box in |input| matches the box type of |
32 // the parameter (in this case mp4::ProtectionSystemSpecificHeader is a | 29 // the parameter (in this case mp4::ProtectionSystemSpecificHeader is a |
33 // 'pssh' box). mp4::ProtectionSystemSpecificHeader doesn't validate the | 30 // 'pssh' box). mp4::ProtectionSystemSpecificHeader doesn't validate the |
34 // 'pssh' contents, so this simply verifies that |input| only contains | 31 // 'pssh' contents, so this simply verifies that |input| only contains |
(...skipping 28 matching lines...) Expand all Loading... | |
63 | 60 |
64 bool ValidatePsshInput(const std::vector<uint8_t>& input) { | 61 bool ValidatePsshInput(const std::vector<uint8_t>& input) { |
65 // No 'pssh' boxes is considered valid. | 62 // No 'pssh' boxes is considered valid. |
66 if (input.empty()) | 63 if (input.empty()) |
67 return true; | 64 return true; |
68 | 65 |
69 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | 66 std::vector<mp4::FullProtectionSystemSpecificHeader> children; |
70 return ReadAllPsshBoxes(input, &children); | 67 return ReadAllPsshBoxes(input, &children); |
71 } | 68 } |
72 | 69 |
73 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, | 70 bool GetKeyIdsFromPsshBoxes(const std::vector<uint8_t>& pssh_boxes, |
74 KeyIdList* key_ids) { | 71 const std::vector<uint8_t>& system_id, |
72 KeyIdList* key_ids) { | |
73 // If there are no 'pssh' boxes then no key IDs found. | |
74 if (pssh_boxes.empty()) | |
75 return false; | |
76 | |
77 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | |
78 if (!ReadAllPsshBoxes(pssh_boxes, &children)) | |
ddorwin
2015/06/25 22:49:23
We now have |pssh_boxes| passed to |input| AND |ps
jrummell
2015/06/30 00:49:12
Acknowledged.
| |
79 return false; | |
80 | |
81 // Check all children for an appropriate 'pssh' box, returning the | |
82 // key IDs found. | |
75 KeyIdList result; | 83 KeyIdList result; |
76 std::vector<uint8_t> common_system_id( | 84 for (const auto& child : children) { |
77 kCommonSystemId, kCommonSystemId + arraysize(kCommonSystemId)); | 85 if (child.system_id == system_id) { |
78 | 86 key_ids->assign(child.key_ids.begin(), child.key_ids.end()); |
79 if (!input.empty()) { | 87 return key_ids->size() > 0; |
80 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | |
81 if (!ReadAllPsshBoxes(input, &children)) | |
82 return false; | |
83 | |
84 // Check all children for an appropriate 'pssh' box, concatenating any | |
85 // key IDs found. | |
86 for (const auto& child : children) { | |
87 if (child.system_id == common_system_id && child.key_ids.size() > 0) | |
88 result.insert(result.end(), child.key_ids.begin(), child.key_ids.end()); | |
89 } | 88 } |
90 } | 89 } |
91 | 90 |
92 key_ids->swap(result); | 91 // No matching 'pssh' box found. |
93 return key_ids->size() > 0; | 92 return false; |
94 } | 93 } |
95 | 94 |
96 bool GetPsshData(const std::vector<uint8_t>& input, | 95 bool GetPsshData(const std::vector<uint8_t>& input, |
97 const std::vector<uint8_t>& system_id, | 96 const std::vector<uint8_t>& system_id, |
98 std::vector<uint8_t>* pssh_data) { | 97 std::vector<uint8_t>* pssh_data) { |
99 if (input.empty()) | 98 if (input.empty()) |
100 return false; | 99 return false; |
101 | 100 |
102 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | 101 std::vector<mp4::FullProtectionSystemSpecificHeader> children; |
103 if (!ReadAllPsshBoxes(input, &children)) | 102 if (!ReadAllPsshBoxes(input, &children)) |
104 return false; | 103 return false; |
105 | 104 |
106 // Check all children for an appropriate 'pssh' box, returning |data| from | 105 // Check all children for an appropriate 'pssh' box, returning |data| from |
107 // the first one found. | 106 // the first one found. |
108 for (const auto& child : children) { | 107 for (const auto& child : children) { |
109 if (child.system_id == system_id) { | 108 if (child.system_id == system_id) { |
110 pssh_data->assign(child.data.begin(), child.data.end()); | 109 pssh_data->assign(child.data.begin(), child.data.end()); |
111 return true; | 110 return true; |
112 } | 111 } |
113 } | 112 } |
114 | 113 |
115 // No matching 'pssh' box found. | 114 // No matching 'pssh' box found. |
116 return false; | 115 return false; |
117 } | 116 } |
118 | 117 |
119 } // namespace media | 118 } // namespace media |
OLD | NEW |