1 // Copyright (c) 2012 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.
5 #include "media/webm/webm_content_encodings_client.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "media/webm/webm_constants.h"
13 WebMContentEncodingsClient::WebMContentEncodingsClient()
14 : content_encryption_encountered_(false),
15 content_encodings_ready_(false) {
18 WebMContentEncodingsClient::~WebMContentEncodingsClient() {
19 STLDeleteElements(&content_encodings_
);
22 const ContentEncodings
& WebMContentEncodingsClient::content_encodings() const {
23 DCHECK(content_encodings_ready_
);
24 return content_encodings_
;
27 WebMParserClient
* WebMContentEncodingsClient::OnListStart(int id
) {
28 if (id
== kWebMIdContentEncodings
) {
29 DCHECK(!cur_content_encoding_
.get());
30 DCHECK(!content_encryption_encountered_
);
31 STLDeleteElements(&content_encodings_
);
32 content_encodings_ready_
= false;
36 if (id
== kWebMIdContentEncoding
) {
37 DCHECK(!cur_content_encoding_
.get());
38 DCHECK(!content_encryption_encountered_
);
39 cur_content_encoding_
.reset(new ContentEncoding());
43 if (id
== kWebMIdContentEncryption
) {
44 DCHECK(cur_content_encoding_
.get());
45 if (content_encryption_encountered_
) {
46 DVLOG(1) << "Unexpected multiple ContentEncryption.";
49 content_encryption_encountered_
= true;
53 if (id
== kWebMIdContentEncAESSettings
) {
54 DCHECK(cur_content_encoding_
.get());
58 // This should not happen if WebMListParser is working properly.
63 // Mandatory occurrence restriction is checked in this function. Multiple
64 // occurrence restriction is checked in OnUInt and OnBinary.
65 bool WebMContentEncodingsClient::OnListEnd(int id
) {
66 if (id
== kWebMIdContentEncodings
) {
67 // ContentEncoding element is mandatory. Check this!
68 if (content_encodings_
.empty()) {
69 DVLOG(1) << "Missing ContentEncoding.";
72 content_encodings_ready_
= true;
76 if (id
== kWebMIdContentEncoding
) {
77 DCHECK(cur_content_encoding_
.get());
80 // Specify default values to missing mandatory elements.
83 if (cur_content_encoding_
->order() == ContentEncoding::kOrderInvalid
) {
84 // Default value of encoding order is 0, which should only be used on the
85 // first ContentEncoding.
86 if (!content_encodings_
.empty()) {
87 DVLOG(1) << "Missing ContentEncodingOrder.";
90 cur_content_encoding_
->set_order(0);
93 if (cur_content_encoding_
->scope() == ContentEncoding::kScopeInvalid
)
94 cur_content_encoding_
->set_scope(ContentEncoding::kScopeAllFrameContents
);
96 if (cur_content_encoding_
->type() == ContentEncoding::kTypeInvalid
)
97 cur_content_encoding_
->set_type(ContentEncoding::kTypeCompression
);
99 // Check for elements valid in spec but not supported for now.
100 if (cur_content_encoding_
->type() == ContentEncoding::kTypeCompression
) {
101 DVLOG(1) << "ContentCompression not supported.";
105 // Enforce mandatory elements without default values.
106 DCHECK(cur_content_encoding_
->type() == ContentEncoding::kTypeEncryption
);
107 if (!content_encryption_encountered_
) {
108 DVLOG(1) << "ContentEncodingType is encryption but ContentEncryption "
113 content_encodings_
.push_back(cur_content_encoding_
.release());
114 content_encryption_encountered_
= false;
118 if (id
== kWebMIdContentEncryption
) {
119 DCHECK(cur_content_encoding_
.get());
120 // Specify default value for elements that are not present.
121 if (cur_content_encoding_
->encryption_algo() ==
122 ContentEncoding::kEncAlgoInvalid
) {
123 cur_content_encoding_
->set_encryption_algo(
124 ContentEncoding::kEncAlgoNotEncrypted
);
129 if (id
== kWebMIdContentEncAESSettings
) {
130 if (cur_content_encoding_
->cipher_mode() ==
131 ContentEncoding::kCipherModeInvalid
)
132 cur_content_encoding_
->set_cipher_mode(ContentEncoding::kCipherModeCtr
);
136 // This should not happen if WebMListParser is working properly.
141 // Multiple occurrence restriction and range are checked in this function.
142 // Mandatory occurrence restriction is checked in OnListEnd.
143 bool WebMContentEncodingsClient::OnUInt(int id
, int64 val
) {
144 DCHECK(cur_content_encoding_
.get());
146 if (id
== kWebMIdContentEncodingOrder
) {
147 if (cur_content_encoding_
->order() != ContentEncoding::kOrderInvalid
) {
148 DVLOG(1) << "Unexpected multiple ContentEncodingOrder.";
152 if (val
!= static_cast<int64
>(content_encodings_
.size())) {
153 // According to the spec, encoding order starts with 0 and counts upwards.
154 DVLOG(1) << "Unexpected ContentEncodingOrder.";
158 cur_content_encoding_
->set_order(val
);
162 if (id
== kWebMIdContentEncodingScope
) {
163 if (cur_content_encoding_
->scope() != ContentEncoding::kScopeInvalid
) {
164 DVLOG(1) << "Unexpected multiple ContentEncodingScope.";
168 if (val
== ContentEncoding::kScopeInvalid
||
169 val
> ContentEncoding::kScopeMax
) {
170 DVLOG(1) << "Unexpected ContentEncodingScope.";
174 if (val
& ContentEncoding::kScopeNextContentEncodingData
) {
175 DVLOG(1) << "Encoded next ContentEncoding is not supported.";
179 cur_content_encoding_
->set_scope(static_cast<ContentEncoding::Scope
>(val
));
183 if (id
== kWebMIdContentEncodingType
) {
184 if (cur_content_encoding_
->type() != ContentEncoding::kTypeInvalid
) {
185 DVLOG(1) << "Unexpected multiple ContentEncodingType.";
189 if (val
== ContentEncoding::kTypeCompression
) {
190 DVLOG(1) << "ContentCompression not supported.";
194 if (val
!= ContentEncoding::kTypeEncryption
) {
195 DVLOG(1) << "Unexpected ContentEncodingType " << val
<< ".";
199 cur_content_encoding_
->set_type(static_cast<ContentEncoding::Type
>(val
));
203 if (id
== kWebMIdContentEncAlgo
) {
204 if (cur_content_encoding_
->encryption_algo() !=
205 ContentEncoding::kEncAlgoInvalid
) {
206 DVLOG(1) << "Unexpected multiple ContentEncAlgo.";
210 if (val
< ContentEncoding::kEncAlgoNotEncrypted
||
211 val
> ContentEncoding::kEncAlgoAes
) {
212 DVLOG(1) << "Unexpected ContentEncAlgo " << val
<< ".";
216 cur_content_encoding_
->set_encryption_algo(
217 static_cast<ContentEncoding::EncryptionAlgo
>(val
));
221 if (id
== kWebMIdAESSettingsCipherMode
) {
222 if (cur_content_encoding_
->cipher_mode() !=
223 ContentEncoding::kCipherModeInvalid
) {
224 DVLOG(1) << "Unexpected multiple AESSettingsCipherMode.";
228 if (val
!= ContentEncoding::kCipherModeCtr
) {
229 DVLOG(1) << "Unexpected AESSettingsCipherMode " << val
<< ".";
233 cur_content_encoding_
->set_cipher_mode(
234 static_cast<ContentEncoding::CipherMode
>(val
));
238 // This should not happen if WebMListParser is working properly.
243 // Multiple occurrence restriction is checked in this function. Mandatory
244 // restriction is checked in OnListEnd.
245 bool WebMContentEncodingsClient::OnBinary(int id
, const uint8
* data
, int size
) {
246 DCHECK(cur_content_encoding_
.get());
250 if (id
== kWebMIdContentEncKeyID
) {
251 if (!cur_content_encoding_
->encryption_key_id().empty()) {
252 DVLOG(1) << "Unexpected multiple ContentEncKeyID";
255 cur_content_encoding_
->SetEncryptionKeyId(data
, size
);
259 // This should not happen if WebMListParser is working properly.