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.
5 #include "media/formats/webm/webm_content_encodings_client.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "media/formats/webm/webm_constants.h"
13 WebMContentEncodingsClient::WebMContentEncodingsClient(
14 const scoped_refptr
<MediaLog
>& media_log
)
15 : media_log_(media_log
),
16 content_encryption_encountered_(false),
17 content_encodings_ready_(false) {
20 WebMContentEncodingsClient::~WebMContentEncodingsClient() {
21 STLDeleteElements(&content_encodings_
);
24 const ContentEncodings
& WebMContentEncodingsClient::content_encodings() const {
25 DCHECK(content_encodings_ready_
);
26 return content_encodings_
;
29 WebMParserClient
* WebMContentEncodingsClient::OnListStart(int id
) {
30 if (id
== kWebMIdContentEncodings
) {
31 DCHECK(!cur_content_encoding_
.get());
32 DCHECK(!content_encryption_encountered_
);
33 STLDeleteElements(&content_encodings_
);
34 content_encodings_ready_
= false;
38 if (id
== kWebMIdContentEncoding
) {
39 DCHECK(!cur_content_encoding_
.get());
40 DCHECK(!content_encryption_encountered_
);
41 cur_content_encoding_
.reset(new ContentEncoding());
45 if (id
== kWebMIdContentEncryption
) {
46 DCHECK(cur_content_encoding_
.get());
47 if (content_encryption_encountered_
) {
48 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected multiple ContentEncryption.";
51 content_encryption_encountered_
= true;
55 if (id
== kWebMIdContentEncAESSettings
) {
56 DCHECK(cur_content_encoding_
.get());
60 // This should not happen if WebMListParser is working properly.
65 // Mandatory occurrence restriction is checked in this function. Multiple
66 // occurrence restriction is checked in OnUInt and OnBinary.
67 bool WebMContentEncodingsClient::OnListEnd(int id
) {
68 if (id
== kWebMIdContentEncodings
) {
69 // ContentEncoding element is mandatory. Check this!
70 if (content_encodings_
.empty()) {
71 MEDIA_LOG(ERROR
, media_log_
) << "Missing ContentEncoding.";
74 content_encodings_ready_
= true;
78 if (id
== kWebMIdContentEncoding
) {
79 DCHECK(cur_content_encoding_
.get());
82 // Specify default values to missing mandatory elements.
85 if (cur_content_encoding_
->order() == ContentEncoding::kOrderInvalid
) {
86 // Default value of encoding order is 0, which should only be used on the
87 // first ContentEncoding.
88 if (!content_encodings_
.empty()) {
89 MEDIA_LOG(ERROR
, media_log_
) << "Missing ContentEncodingOrder.";
92 cur_content_encoding_
->set_order(0);
95 if (cur_content_encoding_
->scope() == ContentEncoding::kScopeInvalid
)
96 cur_content_encoding_
->set_scope(ContentEncoding::kScopeAllFrameContents
);
98 if (cur_content_encoding_
->type() == ContentEncoding::kTypeInvalid
)
99 cur_content_encoding_
->set_type(ContentEncoding::kTypeCompression
);
101 // Check for elements valid in spec but not supported for now.
102 if (cur_content_encoding_
->type() == ContentEncoding::kTypeCompression
) {
103 MEDIA_LOG(ERROR
, media_log_
) << "ContentCompression not supported.";
107 // Enforce mandatory elements without default values.
108 DCHECK(cur_content_encoding_
->type() == ContentEncoding::kTypeEncryption
);
109 if (!content_encryption_encountered_
) {
110 MEDIA_LOG(ERROR
, media_log_
) << "ContentEncodingType is encryption but"
111 << " ContentEncryption is missing.";
115 content_encodings_
.push_back(cur_content_encoding_
.release());
116 content_encryption_encountered_
= false;
120 if (id
== kWebMIdContentEncryption
) {
121 DCHECK(cur_content_encoding_
.get());
122 // Specify default value for elements that are not present.
123 if (cur_content_encoding_
->encryption_algo() ==
124 ContentEncoding::kEncAlgoInvalid
) {
125 cur_content_encoding_
->set_encryption_algo(
126 ContentEncoding::kEncAlgoNotEncrypted
);
131 if (id
== kWebMIdContentEncAESSettings
) {
132 if (cur_content_encoding_
->cipher_mode() ==
133 ContentEncoding::kCipherModeInvalid
)
134 cur_content_encoding_
->set_cipher_mode(ContentEncoding::kCipherModeCtr
);
138 // This should not happen if WebMListParser is working properly.
143 // Multiple occurrence restriction and range are checked in this function.
144 // Mandatory occurrence restriction is checked in OnListEnd.
145 bool WebMContentEncodingsClient::OnUInt(int id
, int64 val
) {
146 DCHECK(cur_content_encoding_
.get());
148 if (id
== kWebMIdContentEncodingOrder
) {
149 if (cur_content_encoding_
->order() != ContentEncoding::kOrderInvalid
) {
150 MEDIA_LOG(ERROR
, media_log_
)
151 << "Unexpected multiple ContentEncodingOrder.";
155 if (val
!= static_cast<int64
>(content_encodings_
.size())) {
156 // According to the spec, encoding order starts with 0 and counts upwards.
157 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected ContentEncodingOrder.";
161 cur_content_encoding_
->set_order(val
);
165 if (id
== kWebMIdContentEncodingScope
) {
166 if (cur_content_encoding_
->scope() != ContentEncoding::kScopeInvalid
) {
167 MEDIA_LOG(ERROR
, media_log_
)
168 << "Unexpected multiple ContentEncodingScope.";
172 if (val
== ContentEncoding::kScopeInvalid
||
173 val
> ContentEncoding::kScopeMax
) {
174 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected ContentEncodingScope.";
178 if (val
& ContentEncoding::kScopeNextContentEncodingData
) {
179 MEDIA_LOG(ERROR
, media_log_
) << "Encoded next ContentEncoding is not "
184 cur_content_encoding_
->set_scope(static_cast<ContentEncoding::Scope
>(val
));
188 if (id
== kWebMIdContentEncodingType
) {
189 if (cur_content_encoding_
->type() != ContentEncoding::kTypeInvalid
) {
190 MEDIA_LOG(ERROR
, media_log_
)
191 << "Unexpected multiple ContentEncodingType.";
195 if (val
== ContentEncoding::kTypeCompression
) {
196 MEDIA_LOG(ERROR
, media_log_
) << "ContentCompression not supported.";
200 if (val
!= ContentEncoding::kTypeEncryption
) {
201 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected ContentEncodingType " << val
206 cur_content_encoding_
->set_type(static_cast<ContentEncoding::Type
>(val
));
210 if (id
== kWebMIdContentEncAlgo
) {
211 if (cur_content_encoding_
->encryption_algo() !=
212 ContentEncoding::kEncAlgoInvalid
) {
213 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected multiple ContentEncAlgo.";
217 if (val
< ContentEncoding::kEncAlgoNotEncrypted
||
218 val
> ContentEncoding::kEncAlgoAes
) {
219 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected ContentEncAlgo " << val
224 cur_content_encoding_
->set_encryption_algo(
225 static_cast<ContentEncoding::EncryptionAlgo
>(val
));
229 if (id
== kWebMIdAESSettingsCipherMode
) {
230 if (cur_content_encoding_
->cipher_mode() !=
231 ContentEncoding::kCipherModeInvalid
) {
232 MEDIA_LOG(ERROR
, media_log_
)
233 << "Unexpected multiple AESSettingsCipherMode.";
237 if (val
!= ContentEncoding::kCipherModeCtr
) {
238 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected AESSettingsCipherMode " << val
243 cur_content_encoding_
->set_cipher_mode(
244 static_cast<ContentEncoding::CipherMode
>(val
));
248 // This should not happen if WebMListParser is working properly.
253 // Multiple occurrence restriction is checked in this function. Mandatory
254 // restriction is checked in OnListEnd.
255 bool WebMContentEncodingsClient::OnBinary(int id
, const uint8
* data
, int size
) {
256 DCHECK(cur_content_encoding_
.get());
260 if (id
== kWebMIdContentEncKeyID
) {
261 if (!cur_content_encoding_
->encryption_key_id().empty()) {
262 MEDIA_LOG(ERROR
, media_log_
) << "Unexpected multiple ContentEncKeyID";
265 cur_content_encoding_
->SetEncryptionKeyId(data
, size
);
269 // This should not happen if WebMListParser is working properly.