Home | History | Annotate | Download | only in webm
      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.
      4 
      5 #include "media/webm/webm_content_encodings_client.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "media/webm/webm_constants.h"
     10 
     11 namespace media {
     12 
     13 WebMContentEncodingsClient::WebMContentEncodingsClient(const LogCB& log_cb)
     14     : log_cb_(log_cb),
     15       content_encryption_encountered_(false),
     16       content_encodings_ready_(false) {
     17 }
     18 
     19 WebMContentEncodingsClient::~WebMContentEncodingsClient() {
     20   STLDeleteElements(&content_encodings_);
     21 }
     22 
     23 const ContentEncodings& WebMContentEncodingsClient::content_encodings() const {
     24   DCHECK(content_encodings_ready_);
     25   return content_encodings_;
     26 }
     27 
     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;
     34     return this;
     35   }
     36 
     37   if (id == kWebMIdContentEncoding) {
     38     DCHECK(!cur_content_encoding_.get());
     39     DCHECK(!content_encryption_encountered_);
     40     cur_content_encoding_.reset(new ContentEncoding());
     41     return this;
     42   }
     43 
     44   if (id == kWebMIdContentEncryption) {
     45     DCHECK(cur_content_encoding_.get());
     46     if (content_encryption_encountered_) {
     47       MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncryption.";
     48       return NULL;
     49     }
     50     content_encryption_encountered_ = true;
     51     return this;
     52   }
     53 
     54   if (id == kWebMIdContentEncAESSettings) {
     55     DCHECK(cur_content_encoding_.get());
     56     return this;
     57   }
     58 
     59   // This should not happen if WebMListParser is working properly.
     60   DCHECK(false);
     61   return NULL;
     62 }
     63 
     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.";
     71       return false;
     72     }
     73     content_encodings_ready_ = true;
     74     return true;
     75   }
     76 
     77   if (id == kWebMIdContentEncoding) {
     78     DCHECK(cur_content_encoding_.get());
     79 
     80     //
     81     // Specify default values to missing mandatory elements.
     82     //
     83 
     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.";
     89         return false;
     90       }
     91       cur_content_encoding_->set_order(0);
     92     }
     93 
     94     if (cur_content_encoding_->scope() == ContentEncoding::kScopeInvalid)
     95       cur_content_encoding_->set_scope(ContentEncoding::kScopeAllFrameContents);
     96 
     97     if (cur_content_encoding_->type() == ContentEncoding::kTypeInvalid)
     98       cur_content_encoding_->set_type(ContentEncoding::kTypeCompression);
     99 
    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.";
    103       return false;
    104     }
    105 
    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.";
    111       return false;
    112     }
    113 
    114     content_encodings_.push_back(cur_content_encoding_.release());
    115     content_encryption_encountered_ = false;
    116     return true;
    117   }
    118 
    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);
    126     }
    127     return true;
    128   }
    129 
    130   if (id == kWebMIdContentEncAESSettings) {
    131     if (cur_content_encoding_->cipher_mode() ==
    132         ContentEncoding::kCipherModeInvalid)
    133       cur_content_encoding_->set_cipher_mode(ContentEncoding::kCipherModeCtr);
    134     return true;
    135   }
    136 
    137   // This should not happen if WebMListParser is working properly.
    138   DCHECK(false);
    139   return false;
    140 }
    141 
    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());
    146 
    147   if (id == kWebMIdContentEncodingOrder) {
    148     if (cur_content_encoding_->order() != ContentEncoding::kOrderInvalid) {
    149       MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingOrder.";
    150       return false;
    151     }
    152 
    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.";
    156       return false;
    157     }
    158 
    159     cur_content_encoding_->set_order(val);
    160     return true;
    161   }
    162 
    163   if (id == kWebMIdContentEncodingScope) {
    164     if (cur_content_encoding_->scope() != ContentEncoding::kScopeInvalid) {
    165       MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingScope.";
    166       return false;
    167     }
    168 
    169     if (val == ContentEncoding::kScopeInvalid ||
    170         val > ContentEncoding::kScopeMax) {
    171       MEDIA_LOG(log_cb_) << "Unexpected ContentEncodingScope.";
    172       return false;
    173     }
    174 
    175     if (val & ContentEncoding::kScopeNextContentEncodingData) {
    176       MEDIA_LOG(log_cb_) << "Encoded next ContentEncoding is not supported.";
    177       return false;
    178     }
    179 
    180     cur_content_encoding_->set_scope(static_cast<ContentEncoding::Scope>(val));
    181     return true;
    182   }
    183 
    184   if (id == kWebMIdContentEncodingType) {
    185     if (cur_content_encoding_->type() != ContentEncoding::kTypeInvalid) {
    186       MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncodingType.";
    187       return false;
    188     }
    189 
    190     if (val == ContentEncoding::kTypeCompression) {
    191       MEDIA_LOG(log_cb_) << "ContentCompression not supported.";
    192       return false;
    193     }
    194 
    195     if (val != ContentEncoding::kTypeEncryption) {
    196       MEDIA_LOG(log_cb_) << "Unexpected ContentEncodingType " << val << ".";
    197       return false;
    198     }
    199 
    200     cur_content_encoding_->set_type(static_cast<ContentEncoding::Type>(val));
    201     return true;
    202   }
    203 
    204   if (id == kWebMIdContentEncAlgo) {
    205     if (cur_content_encoding_->encryption_algo() !=
    206         ContentEncoding::kEncAlgoInvalid) {
    207       MEDIA_LOG(log_cb_) << "Unexpected multiple ContentEncAlgo.";
    208       return false;
    209     }
    210 
    211     if (val < ContentEncoding::kEncAlgoNotEncrypted ||
    212         val > ContentEncoding::kEncAlgoAes) {
    213       MEDIA_LOG(log_cb_) << "Unexpected ContentEncAlgo " << val << ".";
    214       return false;
    215     }
    216 
    217     cur_content_encoding_->set_encryption_algo(
    218         static_cast<ContentEncoding::EncryptionAlgo>(val));
    219     return true;
    220   }
    221 
    222   if (id == kWebMIdAESSettingsCipherMode) {
    223     if (cur_content_encoding_->cipher_mode() !=
    224         ContentEncoding::kCipherModeInvalid) {
    225       MEDIA_LOG(log_cb_) << "Unexpected multiple AESSettingsCipherMode.";
    226       return false;
    227     }
    228 
    229     if (val != ContentEncoding::kCipherModeCtr) {
    230       MEDIA_LOG(log_cb_) << "Unexpected AESSettingsCipherMode " << val << ".";
    231       return false;
    232     }
    233 
    234     cur_content_encoding_->set_cipher_mode(
    235         static_cast<ContentEncoding::CipherMode>(val));
    236     return true;
    237   }
    238 
    239   // This should not happen if WebMListParser is working properly.
    240   DCHECK(false);
    241   return false;
    242 }
    243 
    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());
    248   DCHECK(data);
    249   DCHECK_GT(size, 0);
    250 
    251   if (id == kWebMIdContentEncKeyID) {
    252     if (!cur_content_encoding_->encryption_key_id().empty()) {
    253       MEDIA_LOG(log_cb_) << "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