Shaka Packager SDK
Loading...
Searching...
No Matches
webm_content_encodings_client.cc
1// Copyright 2014 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 <packager/media/formats/webm/webm_content_encodings_client.h>
6
7#include <absl/log/check.h>
8#include <absl/log/log.h>
9
10#include <packager/media/formats/webm/webm_constants.h>
11
12namespace shaka {
13namespace media {
14
15WebMContentEncodingsClient::WebMContentEncodingsClient()
16 : content_encryption_encountered_(false), content_encodings_ready_(false) {}
17
18WebMContentEncodingsClient::~WebMContentEncodingsClient() {}
19
20const ContentEncodings& WebMContentEncodingsClient::content_encodings() const {
21 DCHECK(content_encodings_ready_);
22 return content_encodings_;
23}
24
25WebMParserClient* WebMContentEncodingsClient::OnListStart(int id) {
26 if (id == kWebMIdContentEncodings) {
27 DCHECK(!cur_content_encoding_.get());
28 DCHECK(!content_encryption_encountered_);
29 content_encodings_.clear();
30 content_encodings_ready_ = false;
31 return this;
32 }
33
34 if (id == kWebMIdContentEncoding) {
35 DCHECK(!cur_content_encoding_.get());
36 DCHECK(!content_encryption_encountered_);
37 cur_content_encoding_.reset(new ContentEncoding());
38 return this;
39 }
40
41 if (id == kWebMIdContentEncryption) {
42 DCHECK(cur_content_encoding_.get());
43 if (content_encryption_encountered_) {
44 LOG(ERROR) << "Unexpected multiple ContentEncryption.";
45 return NULL;
46 }
47 content_encryption_encountered_ = true;
48 return this;
49 }
50
51 if (id == kWebMIdContentEncAESSettings) {
52 DCHECK(cur_content_encoding_.get());
53 return this;
54 }
55
56 // This should not happen if WebMListParser is working properly.
57 DCHECK(false);
58 return NULL;
59}
60
61// Mandatory occurrence restriction is checked in this function. Multiple
62// occurrence restriction is checked in OnUInt and OnBinary.
63bool WebMContentEncodingsClient::OnListEnd(int id) {
64 if (id == kWebMIdContentEncodings) {
65 // ContentEncoding element is mandatory. Check this!
66 if (content_encodings_.empty()) {
67 LOG(ERROR) << "Missing ContentEncoding.";
68 return false;
69 }
70 content_encodings_ready_ = true;
71 return true;
72 }
73
74 if (id == kWebMIdContentEncoding) {
75 DCHECK(cur_content_encoding_.get());
76
77 //
78 // Specify default values to missing mandatory elements.
79 //
80
81 if (cur_content_encoding_->order() == ContentEncoding::kOrderInvalid) {
82 // Default value of encoding order is 0, which should only be used on the
83 // first ContentEncoding.
84 if (!content_encodings_.empty()) {
85 LOG(ERROR) << "Missing ContentEncodingOrder.";
86 return false;
87 }
88 cur_content_encoding_->set_order(0);
89 }
90
91 if (cur_content_encoding_->scope() == ContentEncoding::kScopeInvalid)
92 cur_content_encoding_->set_scope(ContentEncoding::kScopeAllFrameContents);
93
94 if (cur_content_encoding_->type() == ContentEncoding::kTypeInvalid)
95 cur_content_encoding_->set_type(ContentEncoding::kTypeCompression);
96
97 // Check for elements valid in spec but not supported for now.
98 if (cur_content_encoding_->type() == ContentEncoding::kTypeCompression) {
99 LOG(ERROR) << "ContentCompression not supported.";
100 return false;
101 }
102
103 // Enforce mandatory elements without default values.
104 DCHECK_EQ(cur_content_encoding_->type(), ContentEncoding::kTypeEncryption);
105 if (!content_encryption_encountered_) {
106 LOG(ERROR) << "ContentEncodingType is encryption but"
107 << " ContentEncryption is missing.";
108 return false;
109 }
110
111 content_encodings_.push_back(std::move(cur_content_encoding_));
112 content_encryption_encountered_ = false;
113 return true;
114 }
115
116 if (id == kWebMIdContentEncryption) {
117 DCHECK(cur_content_encoding_.get());
118 // Specify default value for elements that are not present.
119 if (cur_content_encoding_->encryption_algo() ==
120 ContentEncoding::kEncAlgoInvalid) {
121 cur_content_encoding_->set_encryption_algo(
122 ContentEncoding::kEncAlgoNotEncrypted);
123 }
124 return true;
125 }
126
127 if (id == kWebMIdContentEncAESSettings) {
128 if (cur_content_encoding_->cipher_mode() ==
129 ContentEncoding::kCipherModeInvalid)
130 cur_content_encoding_->set_cipher_mode(ContentEncoding::kCipherModeCtr);
131 return true;
132 }
133
134 // This should not happen if WebMListParser is working properly.
135 DCHECK(false);
136 return false;
137}
138
139// Multiple occurrence restriction and range are checked in this function.
140// Mandatory occurrence restriction is checked in OnListEnd.
141bool WebMContentEncodingsClient::OnUInt(int id, int64_t val) {
142 DCHECK(cur_content_encoding_.get());
143
144 if (id == kWebMIdContentEncodingOrder) {
145 if (cur_content_encoding_->order() != ContentEncoding::kOrderInvalid) {
146 LOG(ERROR) << "Unexpected multiple ContentEncodingOrder.";
147 return false;
148 }
149
150 if (val != static_cast<int64_t>(content_encodings_.size())) {
151 // According to the spec, encoding order starts with 0 and counts upwards.
152 LOG(ERROR) << "Unexpected ContentEncodingOrder.";
153 return false;
154 }
155
156 cur_content_encoding_->set_order(val);
157 return true;
158 }
159
160 if (id == kWebMIdContentEncodingScope) {
161 if (cur_content_encoding_->scope() != ContentEncoding::kScopeInvalid) {
162 LOG(ERROR) << "Unexpected multiple ContentEncodingScope.";
163 return false;
164 }
165
166 if (val == ContentEncoding::kScopeInvalid ||
167 val > ContentEncoding::kScopeMax) {
168 LOG(ERROR) << "Unexpected ContentEncodingScope.";
169 return false;
170 }
171
172 if (val & ContentEncoding::kScopeNextContentEncodingData) {
173 LOG(ERROR) << "Encoded next ContentEncoding is not "
174 "supported.";
175 return false;
176 }
177
178 cur_content_encoding_->set_scope(static_cast<ContentEncoding::Scope>(val));
179 return true;
180 }
181
182 if (id == kWebMIdContentEncodingType) {
183 if (cur_content_encoding_->type() != ContentEncoding::kTypeInvalid) {
184 LOG(ERROR) << "Unexpected multiple ContentEncodingType.";
185 return false;
186 }
187
188 if (val == ContentEncoding::kTypeCompression) {
189 LOG(ERROR) << "ContentCompression not supported.";
190 return false;
191 }
192
193 if (val != ContentEncoding::kTypeEncryption) {
194 LOG(ERROR) << "Unexpected ContentEncodingType " << val << ".";
195 return false;
196 }
197
198 cur_content_encoding_->set_type(static_cast<ContentEncoding::Type>(val));
199 return true;
200 }
201
202 if (id == kWebMIdContentEncAlgo) {
203 if (cur_content_encoding_->encryption_algo() !=
204 ContentEncoding::kEncAlgoInvalid) {
205 LOG(ERROR) << "Unexpected multiple ContentEncAlgo.";
206 return false;
207 }
208
209 if (val < ContentEncoding::kEncAlgoNotEncrypted ||
210 val > ContentEncoding::kEncAlgoAes) {
211 LOG(ERROR) << "Unexpected ContentEncAlgo " << val << ".";
212 return false;
213 }
214
215 cur_content_encoding_->set_encryption_algo(
216 static_cast<ContentEncoding::EncryptionAlgo>(val));
217 return true;
218 }
219
220 if (id == kWebMIdAESSettingsCipherMode) {
221 if (cur_content_encoding_->cipher_mode() !=
222 ContentEncoding::kCipherModeInvalid) {
223 LOG(ERROR) << "Unexpected multiple AESSettingsCipherMode.";
224 return false;
225 }
226
227 if (val != ContentEncoding::kCipherModeCtr) {
228 LOG(ERROR) << "Unexpected AESSettingsCipherMode " << val << ".";
229 return false;
230 }
231
232 cur_content_encoding_->set_cipher_mode(
233 static_cast<ContentEncoding::CipherMode>(val));
234 return true;
235 }
236
237 // This should not happen if WebMListParser is working properly.
238 DCHECK(false);
239 return false;
240}
241
242// Multiple occurrence restriction is checked in this function. Mandatory
243// restriction is checked in OnListEnd.
244bool WebMContentEncodingsClient::OnBinary(int id,
245 const uint8_t* data,
246 int size) {
247 DCHECK(cur_content_encoding_.get());
248 DCHECK(data);
249 DCHECK_GT(size, 0);
250
251 if (id == kWebMIdContentEncKeyID) {
252 if (!cur_content_encoding_->encryption_key_id().empty()) {
253 LOG(ERROR) << "Unexpected multiple ContentEncKeyID";
254 return false;
255 }
256 cur_content_encoding_->SetEncryptionKeyId(data, size);
257 return true;
258 }
259
260 // This should not happen if WebMListParser is working properly.
261 DCHECK(false);
262 return false;
263}
264
265} // namespace media
266} // namespace shaka
All the methods that are virtual are virtual for mocking.