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 // CENC SystemID for the Common System. |
19 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system | 19 // https://w3c.github.io/encrypted-media/cenc-format.html#common-system |
20 const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, | 20 const uint8_t kCencCommonSystemId[] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, |
21 0xc0, 0xb2, 0x4d, 0x02, | 21 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, |
22 0xac, 0xe3, 0x3c, 0x1e, | 22 0x52, 0xe2, 0xfb, 0x4b}; |
23 0x52, 0xe2, 0xfb, 0x4b }; | |
24 | 23 |
| 24 // Returns true if |input| contains only 1 or more valid 'pssh' boxes, false |
| 25 // otherwise. |pssh_boxes| is updated as the set of parsed 'pssh' boxes. |
| 26 // Note: All boxes in |input| must be 'pssh' boxes. However, if they can't be |
| 27 // properly parsed (e.g. unsupported version), then they will be skipped. |
25 static bool ReadAllPsshBoxes( | 28 static bool ReadAllPsshBoxes( |
26 const std::vector<uint8_t>& input, | 29 const std::vector<uint8_t>& input, |
27 std::vector<mp4::FullProtectionSystemSpecificHeader>* pssh_boxes) { | 30 std::vector<mp4::FullProtectionSystemSpecificHeader>* pssh_boxes) { |
28 DCHECK(!input.empty()); | 31 DCHECK(!input.empty()); |
29 | 32 |
30 // Verify that |input| contains only 'pssh' boxes. ReadAllChildren() is | 33 // Verify that |input| contains only 'pssh' boxes. ReadAllChildren() is |
31 // templated, so it checks that each box in |input| matches the box type of | 34 // templated, so it checks that each box in |input| matches the box type of |
32 // the parameter (in this case mp4::ProtectionSystemSpecificHeader is a | 35 // the parameter (in this case mp4::ProtectionSystemSpecificHeader is a |
33 // 'pssh' box). mp4::ProtectionSystemSpecificHeader doesn't validate the | 36 // 'pssh' box). mp4::ProtectionSystemSpecificHeader doesn't validate the |
34 // 'pssh' contents, so this simply verifies that |input| only contains | 37 // 'pssh' contents, so this simply verifies that |input| only contains |
(...skipping 28 matching lines...) Expand all Loading... |
63 | 66 |
64 bool ValidatePsshInput(const std::vector<uint8_t>& input) { | 67 bool ValidatePsshInput(const std::vector<uint8_t>& input) { |
65 // No 'pssh' boxes is considered valid. | 68 // No 'pssh' boxes is considered valid. |
66 if (input.empty()) | 69 if (input.empty()) |
67 return true; | 70 return true; |
68 | 71 |
69 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | 72 std::vector<mp4::FullProtectionSystemSpecificHeader> children; |
70 return ReadAllPsshBoxes(input, &children); | 73 return ReadAllPsshBoxes(input, &children); |
71 } | 74 } |
72 | 75 |
73 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, | 76 bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& pssh_boxes, |
74 KeyIdList* key_ids) { | 77 KeyIdList* key_ids) { |
| 78 // If there are no 'pssh' boxes then no key IDs found. |
| 79 if (pssh_boxes.empty()) |
| 80 return false; |
| 81 |
| 82 std::vector<mp4::FullProtectionSystemSpecificHeader> children; |
| 83 if (!ReadAllPsshBoxes(pssh_boxes, &children)) |
| 84 return false; |
| 85 |
| 86 // Check all children for an appropriate 'pssh' box, returning the |
| 87 // key IDs found. |
75 KeyIdList result; | 88 KeyIdList result; |
76 std::vector<uint8_t> common_system_id( | 89 std::vector<uint8_t> common_system_id( |
77 kCommonSystemId, kCommonSystemId + arraysize(kCommonSystemId)); | 90 kCencCommonSystemId, |
78 | 91 kCencCommonSystemId + arraysize(kCencCommonSystemId)); |
79 if (!input.empty()) { | 92 for (const auto& child : children) { |
80 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | 93 if (child.system_id == common_system_id) { |
81 if (!ReadAllPsshBoxes(input, &children)) | 94 key_ids->assign(child.key_ids.begin(), child.key_ids.end()); |
82 return false; | 95 return key_ids->size() > 0; |
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 } | 96 } |
90 } | 97 } |
91 | 98 |
92 key_ids->swap(result); | 99 // No matching 'pssh' box found. |
93 return key_ids->size() > 0; | 100 return false; |
94 } | 101 } |
95 | 102 |
96 bool GetPsshData(const std::vector<uint8_t>& input, | 103 bool GetPsshData(const std::vector<uint8_t>& input, |
97 const std::vector<uint8_t>& system_id, | 104 const std::vector<uint8_t>& system_id, |
98 std::vector<uint8_t>* pssh_data) { | 105 std::vector<uint8_t>* pssh_data) { |
99 if (input.empty()) | 106 if (input.empty()) |
100 return false; | 107 return false; |
101 | 108 |
102 std::vector<mp4::FullProtectionSystemSpecificHeader> children; | 109 std::vector<mp4::FullProtectionSystemSpecificHeader> children; |
103 if (!ReadAllPsshBoxes(input, &children)) | 110 if (!ReadAllPsshBoxes(input, &children)) |
104 return false; | 111 return false; |
105 | 112 |
106 // Check all children for an appropriate 'pssh' box, returning |data| from | 113 // Check all children for an appropriate 'pssh' box, returning |data| from |
107 // the first one found. | 114 // the first one found. |
108 for (const auto& child : children) { | 115 for (const auto& child : children) { |
109 if (child.system_id == system_id) { | 116 if (child.system_id == system_id) { |
110 pssh_data->assign(child.data.begin(), child.data.end()); | 117 pssh_data->assign(child.data.begin(), child.data.end()); |
111 return true; | 118 return true; |
112 } | 119 } |
113 } | 120 } |
114 | 121 |
115 // No matching 'pssh' box found. | 122 // No matching 'pssh' box found. |
116 return false; | 123 return false; |
117 } | 124 } |
118 | 125 |
119 } // namespace media | 126 } // namespace media |
OLD | NEW |