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(const LogCB
& log_cb
)
15 content_encryption_encountered_(false),
16 content_encodings_ready_(false) {
19 WebMContentEncodingsClient::~WebMContentEncodingsClient() {
20 STLDeleteElements(&content_encodings_
);
23 const ContentEncodings
& WebMContentEncodingsClient::content_encodings() const {
24 DCHECK(content_encodings_ready_
);
25 return content_encodings_
;
28 WebMParserClient
* WebMContentEncodingsClient::OnListStart(int id
) {
29 if (id
== kWebMIdContentEncodings
) {
30 DCHECK(!cur_content_encoding_
.get());
31 DCHECK(!content_encryption_encountered_
);
32 STLDeleteElements(&content_encodings_
);
33 content_encodings_ready_
= false;
37 if (id
== kWebMIdContentEncoding
) {
38 DCHECK(!cur_content_encoding_
.get());
39 DCHECK(!content_encryption_encountered_
);
40 cur_content_encoding_
.reset(new ContentEncoding());
44 if (id
== kWebMIdContentEncryption
) {
45 DCHECK(cur_content_encoding_
.get());
46 if (content_encryption_encountered_
) {
47 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncryption.";
50 content_encryption_encountered_
= true;
54 if (id
== kWebMIdContentEncAESSettings
) {
55 DCHECK(cur_content_encoding_
.get());
59 // This should not happen if WebMListParser is working properly.
64 // Mandatory occurrence restriction is checked in this function. Multiple
65 // occurrence restriction is checked in OnUInt and OnBinary.
66 bool WebMContentEncodingsClient::OnListEnd(int id
) {
67 if (id
== kWebMIdContentEncodings
) {
68 // ContentEncoding element is mandatory. Check this!
69 if (content_encodings_
.empty()) {
70 MEDIA_LOG(log_cb_
) << "Missing ContentEncoding.";
73 content_encodings_ready_
= true;
77 if (id
== kWebMIdContentEncoding
) {
78 DCHECK(cur_content_encoding_
.get());
81 // Specify default values to missing mandatory elements.
84 if (cur_content_encoding_
->order() == ContentEncoding::kOrderInvalid
) {
85 // Default value of encoding order is 0, which should only be used on the
86 // first ContentEncoding.
87 if (!content_encodings_
.empty()) {
88 MEDIA_LOG(log_cb_
) << "Missing ContentEncodingOrder.";
91 cur_content_encoding_
->set_order(0);
94 if (cur_content_encoding_
->scope() == ContentEncoding::kScopeInvalid
)
95 cur_content_encoding_
->set_scope(ContentEncoding::kScopeAllFrameContents
);
97 if (cur_content_encoding_
->type() == ContentEncoding::kTypeInvalid
)
98 cur_content_encoding_
->set_type(ContentEncoding::kTypeCompression
);
100 // Check for elements valid in spec but not supported for now.
101 if (cur_content_encoding_
->type() == ContentEncoding::kTypeCompression
) {
102 MEDIA_LOG(log_cb_
) << "ContentCompression not supported.";
106 // Enforce mandatory elements without default values.
107 DCHECK(cur_content_encoding_
->type() == ContentEncoding::kTypeEncryption
);
108 if (!content_encryption_encountered_
) {
109 MEDIA_LOG(log_cb_
) << "ContentEncodingType is encryption but"
110 << " ContentEncryption is missing.";
114 content_encodings_
.push_back(cur_content_encoding_
.release());
115 content_encryption_encountered_
= false;
119 if (id
== kWebMIdContentEncryption
) {
120 DCHECK(cur_content_encoding_
.get());
121 // Specify default value for elements that are not present.
122 if (cur_content_encoding_
->encryption_algo() ==
123 ContentEncoding::kEncAlgoInvalid
) {
124 cur_content_encoding_
->set_encryption_algo(
125 ContentEncoding::kEncAlgoNotEncrypted
);
130 if (id
== kWebMIdContentEncAESSettings
) {
131 if (cur_content_encoding_
->cipher_mode() ==
132 ContentEncoding::kCipherModeInvalid
)
133 cur_content_encoding_
->set_cipher_mode(ContentEncoding::kCipherModeCtr
);
137 // This should not happen if WebMListParser is working properly.
142 // Multiple occurrence restriction and range are checked in this function.
143 // Mandatory occurrence restriction is checked in OnListEnd.
144 bool WebMContentEncodingsClient::OnUInt(int id
, int64 val
) {
145 DCHECK(cur_content_encoding_
.get());
147 if (id
== kWebMIdContentEncodingOrder
) {
148 if (cur_content_encoding_
->order() != ContentEncoding::kOrderInvalid
) {
149 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncodingOrder.";
153 if (val
!= static_cast<int64
>(content_encodings_
.size())) {
154 // According to the spec, encoding order starts with 0 and counts upwards.
155 MEDIA_LOG(log_cb_
) << "Unexpected ContentEncodingOrder.";
159 cur_content_encoding_
->set_order(val
);
163 if (id
== kWebMIdContentEncodingScope
) {
164 if (cur_content_encoding_
->scope() != ContentEncoding::kScopeInvalid
) {
165 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncodingScope.";
169 if (val
== ContentEncoding::kScopeInvalid
||
170 val
> ContentEncoding::kScopeMax
) {
171 MEDIA_LOG(log_cb_
) << "Unexpected ContentEncodingScope.";
175 if (val
& ContentEncoding::kScopeNextContentEncodingData
) {
176 MEDIA_LOG(log_cb_
) << "Encoded next ContentEncoding is not supported.";
180 cur_content_encoding_
->set_scope(static_cast<ContentEncoding::Scope
>(val
));
184 if (id
== kWebMIdContentEncodingType
) {
185 if (cur_content_encoding_
->type() != ContentEncoding::kTypeInvalid
) {
186 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncodingType.";
190 if (val
== ContentEncoding::kTypeCompression
) {
191 MEDIA_LOG(log_cb_
) << "ContentCompression not supported.";
195 if (val
!= ContentEncoding::kTypeEncryption
) {
196 MEDIA_LOG(log_cb_
) << "Unexpected ContentEncodingType " << val
<< ".";
200 cur_content_encoding_
->set_type(static_cast<ContentEncoding::Type
>(val
));
204 if (id
== kWebMIdContentEncAlgo
) {
205 if (cur_content_encoding_
->encryption_algo() !=
206 ContentEncoding::kEncAlgoInvalid
) {
207 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncAlgo.";
211 if (val
< ContentEncoding::kEncAlgoNotEncrypted
||
212 val
> ContentEncoding::kEncAlgoAes
) {
213 MEDIA_LOG(log_cb_
) << "Unexpected ContentEncAlgo " << val
<< ".";
217 cur_content_encoding_
->set_encryption_algo(
218 static_cast<ContentEncoding::EncryptionAlgo
>(val
));
222 if (id
== kWebMIdAESSettingsCipherMode
) {
223 if (cur_content_encoding_
->cipher_mode() !=
224 ContentEncoding::kCipherModeInvalid
) {
225 MEDIA_LOG(log_cb_
) << "Unexpected multiple AESSettingsCipherMode.";
229 if (val
!= ContentEncoding::kCipherModeCtr
) {
230 MEDIA_LOG(log_cb_
) << "Unexpected AESSettingsCipherMode " << val
<< ".";
234 cur_content_encoding_
->set_cipher_mode(
235 static_cast<ContentEncoding::CipherMode
>(val
));
239 // This should not happen if WebMListParser is working properly.
244 // Multiple occurrence restriction is checked in this function. Mandatory
245 // restriction is checked in OnListEnd.
246 bool WebMContentEncodingsClient::OnBinary(int id
, const uint8
* data
, int size
) {
247 DCHECK(cur_content_encoding_
.get());
251 if (id
== kWebMIdContentEncKeyID
) {
252 if (!cur_content_encoding_
->encryption_key_id().empty()) {
253 MEDIA_LOG(log_cb_
) << "Unexpected multiple ContentEncKeyID";
256 cur_content_encoding_
->SetEncryptionKeyId(data
, size
);
260 // This should not happen if WebMListParser is working properly.