diff options
Diffstat (limited to 'chromium/media/formats/webm/webm_content_encodings_client.cc')
-rw-r--r-- | chromium/media/formats/webm/webm_content_encodings_client.cc | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/chromium/media/formats/webm/webm_content_encodings_client.cc b/chromium/media/formats/webm/webm_content_encodings_client.cc new file mode 100644 index 00000000000..f2294de7024 --- /dev/null +++ b/chromium/media/formats/webm/webm_content_encodings_client.cc @@ -0,0 +1,265 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/formats/webm/webm_content_encodings_client.h" + +#include "base/logging.h" +#include "base/stl_util.h" +#include "media/formats/webm/webm_constants.h" + +namespace media { + +WebMContentEncodingsClient::WebMContentEncodingsClient(const LogCB& log_cb) + : log_cb_(log_cb), + content_encryption_encountered_(false), + content_encodings_ready_(false) { +} + +WebMContentEncodingsClient::~WebMContentEncodingsClient() { + STLDeleteElements(&content_encodings_); +} + +const ContentEncodings& WebMContentEncodingsClient::content_encodings() const { + DCHECK(content_encodings_ready_); + return content_encodings_; +} + +WebMParserClient* WebMContentEncodingsClient::OnListStart(int id) { + if (id == kWebMIdContentEncodings) { + DCHECK(!cur_content_encoding_.get()); + DCHECK(!content_encryption_encountered_); + STLDeleteElements(&content_encodings_); + content_encodings_ready_ = false; + return this; + } + + if (id == kWebMIdContentEncoding) { + DCHECK(!cur_content_encoding_.get()); + DCHECK(!content_encryption_encountered_); + cur_content_encoding_.reset(new ContentEncoding()); + return this; + } + + if (id == kWebMIdContentEncryption) { + DCHECK(cur_content_encoding_.get()); + if (content_encryption_encountered_) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncryption."; + return NULL; + } + content_encryption_encountered_ = true; + return this; + } + + if (id == kWebMIdContentEncAESSettings) { + DCHECK(cur_content_encoding_.get()); + return this; + } + + // This should not happen if WebMListParser is working properly. + DCHECK(false); + return NULL; +} + +// Mandatory occurrence restriction is checked in this function. Multiple +// occurrence restriction is checked in OnUInt and OnBinary. +bool WebMContentEncodingsClient::OnListEnd(int id) { + if (id == kWebMIdContentEncodings) { + // ContentEncoding element is mandatory. Check this! + if (content_encodings_.empty()) { + MEDIA_LOG(log_cb_) << "Missing ContentEncoding."; + return false; + } + content_encodings_ready_ = true; + return true; + } + + if (id == kWebMIdContentEncoding) { + DCHECK(cur_content_encoding_.get()); + + // + // Specify default values to missing mandatory elements. + // + + if (cur_content_encoding_->order() == ContentEncoding::kOrderInvalid) { + // Default value of encoding order is 0, which should only be used on the + // first ContentEncoding. + if (!content_encodings_.empty()) { + MEDIA_LOG(log_cb_) << "Missing ContentEncodingOrder."; + return false; + } + cur_content_encoding_->set_order(0); + } + + if (cur_content_encoding_->scope() == ContentEncoding::kScopeInvalid) + cur_content_encoding_->set_scope(ContentEncoding::kScopeAllFrameContents); + + if (cur_content_encoding_->type() == ContentEncoding::kTypeInvalid) + cur_content_encoding_->set_type(ContentEncoding::kTypeCompression); + + // Check for elements valid in spec but not supported for now. + if (cur_content_encoding_->type() == ContentEncoding::kTypeCompression) { + MEDIA_LOG(log_cb_) << "ContentCompression not supported."; + return false; + } + + // Enforce mandatory elements without default values. + DCHECK(cur_content_encoding_->type() == ContentEncoding::kTypeEncryption); + if (!content_encryption_encountered_) { + MEDIA_LOG(log_cb_) << "ContentEncodingType is encryption but" + << " ContentEncryption is missing."; + return false; + } + + content_encodings_.push_back(cur_content_encoding_.release()); + content_encryption_encountered_ = false; + return true; + } + + if (id == kWebMIdContentEncryption) { + DCHECK(cur_content_encoding_.get()); + // Specify default value for elements that are not present. + if (cur_content_encoding_->encryption_algo() == + ContentEncoding::kEncAlgoInvalid) { + cur_content_encoding_->set_encryption_algo( + ContentEncoding::kEncAlgoNotEncrypted); + } + return true; + } + + if (id == kWebMIdContentEncAESSettings) { + if (cur_content_encoding_->cipher_mode() == + ContentEncoding::kCipherModeInvalid) + cur_content_encoding_->set_cipher_mode(ContentEncoding::kCipherModeCtr); + return true; + } + + // This should not happen if WebMListParser is working properly. + DCHECK(false); + return false; +} + +// Multiple occurrence restriction and range are checked in this function. +// Mandatory occurrence restriction is checked in OnListEnd. +bool WebMContentEncodingsClient::OnUInt(int id, int64 val) { + DCHECK(cur_content_encoding_.get()); + + if (id == kWebMIdContentEncodingOrder) { + if (cur_content_encoding_->order() != ContentEncoding::kOrderInvalid) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingOrder."; + return false; + } + + if (val != static_cast<int64>(content_encodings_.size())) { + // According to the spec, encoding order starts with 0 and counts upwards. + MEDIA_LOG(log_cb_) << "Unexpected ContentEncodingOrder."; + return false; + } + + cur_content_encoding_->set_order(val); + return true; + } + + if (id == kWebMIdContentEncodingScope) { + if (cur_content_encoding_->scope() != ContentEncoding::kScopeInvalid) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingScope."; + return false; + } + + if (val == ContentEncoding::kScopeInvalid || + val > ContentEncoding::kScopeMax) { + MEDIA_LOG(log_cb_) << "Unexpected ContentEncodingScope."; + return false; + } + + if (val & ContentEncoding::kScopeNextContentEncodingData) { + MEDIA_LOG(log_cb_) << "Encoded next ContentEncoding is not supported."; + return false; + } + + cur_content_encoding_->set_scope(static_cast<ContentEncoding::Scope>(val)); + return true; + } + + if (id == kWebMIdContentEncodingType) { + if (cur_content_encoding_->type() != ContentEncoding::kTypeInvalid) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingType."; + return false; + } + + if (val == ContentEncoding::kTypeCompression) { + MEDIA_LOG(log_cb_) << "ContentCompression not supported."; + return false; + } + + if (val != ContentEncoding::kTypeEncryption) { + MEDIA_LOG(log_cb_) << "Unexpected ContentEncodingType " << val << "."; + return false; + } + + cur_content_encoding_->set_type(static_cast<ContentEncoding::Type>(val)); + return true; + } + + if (id == kWebMIdContentEncAlgo) { + if (cur_content_encoding_->encryption_algo() != + ContentEncoding::kEncAlgoInvalid) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncAlgo."; + return false; + } + + if (val < ContentEncoding::kEncAlgoNotEncrypted || + val > ContentEncoding::kEncAlgoAes) { + MEDIA_LOG(log_cb_) << "Unexpected ContentEncAlgo " << val << "."; + return false; + } + + cur_content_encoding_->set_encryption_algo( + static_cast<ContentEncoding::EncryptionAlgo>(val)); + return true; + } + + if (id == kWebMIdAESSettingsCipherMode) { + if (cur_content_encoding_->cipher_mode() != + ContentEncoding::kCipherModeInvalid) { + MEDIA_LOG(log_cb_) << "Unexpected multiple AESSettingsCipherMode."; + return false; + } + + if (val != ContentEncoding::kCipherModeCtr) { + MEDIA_LOG(log_cb_) << "Unexpected AESSettingsCipherMode " << val << "."; + return false; + } + + cur_content_encoding_->set_cipher_mode( + static_cast<ContentEncoding::CipherMode>(val)); + return true; + } + + // This should not happen if WebMListParser is working properly. + DCHECK(false); + return false; +} + +// Multiple occurrence restriction is checked in this function. Mandatory +// restriction is checked in OnListEnd. +bool WebMContentEncodingsClient::OnBinary(int id, const uint8* data, int size) { + DCHECK(cur_content_encoding_.get()); + DCHECK(data); + DCHECK_GT(size, 0); + + if (id == kWebMIdContentEncKeyID) { + if (!cur_content_encoding_->encryption_key_id().empty()) { + MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncKeyID"; + return false; + } + cur_content_encoding_->SetEncryptionKeyId(data, size); + return true; + } + + // This should not happen if WebMListParser is working properly. + DCHECK(false); + return false; +} + +} // namespace media |