diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-24 03:50:55 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-24 03:50:55 +0000 |
commit | a5f078461ddae8dd50a68dccfbd2c31882cb62d5 (patch) | |
tree | c831d4e2a7af5f91ca21ccc1019ccbde87fe02c2 /media/webm | |
parent | a58fec2f838877199288d1756b4ac55aeafd4794 (diff) | |
download | chromium_src-a5f078461ddae8dd50a68dccfbd2c31882cb62d5.zip chromium_src-a5f078461ddae8dd50a68dccfbd2c31882cb62d5.tar.gz chromium_src-a5f078461ddae8dd50a68dccfbd2c31882cb62d5.tar.bz2 |
Add content encoding support to WebM demuxer.
BUG=none
TEST=passed media_unittests
Review URL: http://codereview.chromium.org/9084002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123422 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r-- | media/webm/webm_constants.h | 2 | ||||
-rw-r--r-- | media/webm/webm_content_encodings.cc | 19 | ||||
-rw-r--r-- | media/webm/webm_content_encodings.h | 65 | ||||
-rw-r--r-- | media/webm/webm_content_encodings_client.cc | 231 | ||||
-rw-r--r-- | media/webm/webm_content_encodings_client.h | 40 | ||||
-rw-r--r-- | media/webm/webm_content_encodings_client_unittest.cc | 201 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.cc | 22 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.h | 9 |
8 files changed, 588 insertions, 1 deletions
diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h index 433b31c..ecd01df 100644 --- a/media/webm/webm_constants.h +++ b/media/webm/webm_constants.h @@ -5,6 +5,8 @@ #ifndef MEDIA_WEBM_WEBM_CONSTANTS_H_ #define MEDIA_WEBM_WEBM_CONSTANTS_H_ +#include "base/basictypes.h" + namespace media { // WebM element IDs. diff --git a/media/webm/webm_content_encodings.cc b/media/webm/webm_content_encodings.cc new file mode 100644 index 0000000..53cd171 --- /dev/null +++ b/media/webm/webm_content_encodings.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2012 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/webm/webm_content_encodings.h" + +namespace media { + +ContentEncoding::ContentEncoding() + : order_(kOrderInvalid), + scope_(kScopeInvalid), + type_(kTypeInvalid), + encryption_algo_(kEncAlgoInvalid), + encryption_key_id_size_(0) { +} + +ContentEncoding::~ContentEncoding() {} + +} // namespace media diff --git a/media/webm/webm_content_encodings.h b/media/webm/webm_content_encodings.h new file mode 100644 index 0000000..4a5f62f --- /dev/null +++ b/media/webm/webm_content_encodings.h @@ -0,0 +1,65 @@ +// Copyright (c) 2012 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. + +#ifndef MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_H_ +#define MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_H_ + +#include <vector> + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "media/base/media_export.h" + +namespace media { + +struct MEDIA_EXPORT ContentEncoding : public base::RefCounted<ContentEncoding> { + // The following enum definitions are based on the ContentEncoding element + // specified in the Matroska spec. + + static const int kOrderInvalid = -1; + + enum Scope { + kScopeInvalid = 0, + kScopeAllFrameContents = 1, + kScopeTrackPrivateData = 2, + kScopeNextContentEncodingData = 4, + kScopeMax = 7, + }; + + enum Type { + kTypeInvalid = -1, + kTypeCompression = 0, + kTypeEncryption = 1, + }; + + enum EncryptionAlgo { + kEncAlgoInvalid = -1, + kEncAlgoNotEncrypted = 0, + kEncAlgoDes = 1, + kEncAlgo3des = 2, + kEncAlgoTwofish = 3, + kEncAlgoBlowfish = 4, + kEncAlgoAes = 5, + }; + + ContentEncoding(); + virtual ~ContentEncoding(); + + int64 order_; + Scope scope_; + Type type_; + EncryptionAlgo encryption_algo_; + scoped_array<uint8> encryption_key_id_; + int encryption_key_id_size_; + + private: + DISALLOW_COPY_AND_ASSIGN(ContentEncoding); +}; + +typedef std::vector<scoped_refptr<ContentEncoding> > ContentEncodings; + +} // namespace media + +#endif // MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_H_ diff --git a/media/webm/webm_content_encodings_client.cc b/media/webm/webm_content_encodings_client.cc new file mode 100644 index 0000000..4e09ff8 --- /dev/null +++ b/media/webm/webm_content_encodings_client.cc @@ -0,0 +1,231 @@ +// Copyright (c) 2012 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/webm/webm_content_encodings_client.h" + +#include "base/logging.h" +#include "media/webm/webm_constants.h" + +namespace media { + +WebMContentEncodingsClient::WebMContentEncodingsClient() + : content_encryption_encountered_(false) { +} + +WebMContentEncodingsClient::~WebMContentEncodingsClient() {} + +const ContentEncodings& WebMContentEncodingsClient::content_encodings() const { + return content_encodings_; +} + +WebMParserClient* WebMContentEncodingsClient::OnListStart(int id) { + if (id == kWebMIdContentEncodings) { + DCHECK(!cur_content_encoding_); + DCHECK(!content_encryption_encountered_); + content_encodings_.clear(); + return this; + } + + if (id == kWebMIdContentEncoding) { + DCHECK(!cur_content_encoding_); + DCHECK(!content_encryption_encountered_); + cur_content_encoding_ = new ContentEncoding; + return this; + } + + if (id == kWebMIdContentEncryption) { + DCHECK(cur_content_encoding_); + if (content_encryption_encountered_) { + DVLOG(1) << "Unexpected multiple ContentEncryption."; + return NULL; + } + content_encryption_encountered_ = true; + 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()) { + DVLOG(1) << "Missing ContentEncoding."; + return false; + } + return true; + } + + if (id == kWebMIdContentEncoding) { + DCHECK(cur_content_encoding_); + + // + // 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()) { + DVLOG(1) << "Missing ContentEncodingOrder."; + return false; + } + cur_content_encoding_->order_ = 0; + } + + if (cur_content_encoding_->scope_ == ContentEncoding::kScopeInvalid) + cur_content_encoding_->scope_ = ContentEncoding::kScopeAllFrameContents; + + if (cur_content_encoding_->type_ == ContentEncoding::kTypeInvalid) + cur_content_encoding_->type_ = ContentEncoding::kTypeCompression; + + // Check for elements valid in spec but not supported for now. + if (cur_content_encoding_->type_ == ContentEncoding::kTypeCompression) { + DVLOG(1) << "ContentCompression not supported."; + return false; + } + + // Enforce mandatory elements without default values. + DCHECK(cur_content_encoding_->type_ == ContentEncoding::kTypeEncryption); + if (!content_encryption_encountered_) { + DVLOG(1) << "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_); + // Specify default value for elements that are not present. + if (cur_content_encoding_->encryption_algo_ == + ContentEncoding::kEncAlgoInvalid) { + cur_content_encoding_->encryption_algo_ = + ContentEncoding::kEncAlgoNotEncrypted; + } + 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_); + + if (id == kWebMIdContentEncodingOrder) { + if (cur_content_encoding_->order_ != ContentEncoding::kOrderInvalid) { + DVLOG(1) << "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. + DVLOG(1) << "Unexpected ContentEncodingOrder."; + return false; + } + + cur_content_encoding_->order_ = val; + return true; + } + + if (id == kWebMIdContentEncodingScope) { + if (cur_content_encoding_->scope_ != ContentEncoding::kScopeInvalid) { + DVLOG(1) << "Unexpected multiple ContentEncodingScope."; + return false; + } + + if (val == ContentEncoding::kScopeInvalid || + val > ContentEncoding::kScopeMax) { + DVLOG(1) << "Unexpected ContentEncodingScope."; + return false; + } + + if (val & ContentEncoding::kScopeNextContentEncodingData) { + DVLOG(1) << "Encoded next ContentEncoding is not supported."; + return false; + } + + cur_content_encoding_->scope_ = static_cast<ContentEncoding::Scope>(val); + return true; + } + + if (id == kWebMIdContentEncodingType) { + if (cur_content_encoding_->type_ != ContentEncoding::kTypeInvalid) { + DVLOG(1) << "Unexpected multiple ContentEncodingType."; + return false; + } + + if (val == ContentEncoding::kTypeCompression) { + DVLOG(1) << "ContentCompression not supported."; + return false; + } + + if (val != ContentEncoding::kTypeEncryption) { + DVLOG(1) << "Unexpected ContentEncodingType " << val << "."; + return false; + } + + cur_content_encoding_->type_ = static_cast<ContentEncoding::Type>(val); + return true; + } + + if (id == kWebMIdContentEncAlgo) { + if (cur_content_encoding_->encryption_algo_ != + ContentEncoding::kEncAlgoInvalid) { + DVLOG(1) << "Unexpected multiple ContentEncAlgo."; + return false; + } + + if (val < ContentEncoding::kEncAlgoNotEncrypted || + val > ContentEncoding::kEncAlgoAes) { + DVLOG(1) << "Unexpected ContentEncAlgo " << val << "."; + return false; + } + + cur_content_encoding_->encryption_algo_ = + static_cast<ContentEncoding::EncryptionAlgo>(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_); + DCHECK(data); + DCHECK_GT(size, 0); + + if (id == kWebMIdContentEncKeyID) { + if (cur_content_encoding_->encryption_key_id_.get() || + cur_content_encoding_->encryption_key_id_size_) { + DVLOG(1) << "Unexpected multiple ContentEncKeyID"; + return false; + } + cur_content_encoding_->encryption_key_id_.reset(new uint8[size]); + memcpy(cur_content_encoding_->encryption_key_id_.get(), data, size); + cur_content_encoding_->encryption_key_id_size_ = size; + return true; + } + + // This should not happen if WebMListParser is working properly. + DCHECK(false); + return false; +} + +} // namespace media diff --git a/media/webm/webm_content_encodings_client.h b/media/webm/webm_content_encodings_client.h new file mode 100644 index 0000000..9a4c876 --- /dev/null +++ b/media/webm/webm_content_encodings_client.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012 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. + +#ifndef MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_CLIENT_H_ +#define MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_CLIENT_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "media/base/media_export.h" +#include "media/webm/webm_content_encodings.h" +#include "media/webm/webm_parser.h" + +namespace media { + +// Parser for WebM ContentEncodings element. +class MEDIA_EXPORT WebMContentEncodingsClient : public WebMParserClient { + public: + WebMContentEncodingsClient(); + virtual ~WebMContentEncodingsClient(); + + const ContentEncodings& content_encodings() const; + + // WebMParserClient methods + virtual WebMParserClient* OnListStart(int id) OVERRIDE; + virtual bool OnListEnd(int id) OVERRIDE; + virtual bool OnUInt(int id, int64 val) OVERRIDE; + virtual bool OnBinary(int id, const uint8* data, int size) OVERRIDE; + + private: + scoped_refptr<ContentEncoding> cur_content_encoding_; + bool content_encryption_encountered_; + ContentEncodings content_encodings_; + + DISALLOW_COPY_AND_ASSIGN(WebMContentEncodingsClient); +}; + +} // namespace media + +#endif // MEDIA_WEBM_WEBM_CONTENT_ENCODINGS_CLIENT_H_ diff --git a/media/webm/webm_content_encodings_client_unittest.cc b/media/webm/webm_content_encodings_client_unittest.cc new file mode 100644 index 0000000..b3e8daa --- /dev/null +++ b/media/webm/webm_content_encodings_client_unittest.cc @@ -0,0 +1,201 @@ +// Copyright (c) 2012 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/webm/webm_constants.h" +#include "media/webm/webm_content_encodings_client.h" +#include "media/webm/webm_parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class WebMContentEncodingsClientTest : public testing::Test { + public: + WebMContentEncodingsClientTest() + : parser_(kWebMIdContentEncodings, &client_) {} + + void ParseAndExpectToFail(const uint8* buf, int size) { + int result = parser_.Parse(buf, size); + EXPECT_EQ(-1, result); + const ContentEncodings content_encodings = client_.content_encodings(); + EXPECT_TRUE(content_encodings.empty()); + } + + protected: + WebMContentEncodingsClient client_; + WebMListParser parser_; +}; + +TEST_F(WebMContentEncodingsClientTest, EmptyContentEncodings) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x80, // ContentEncodings (size = 0) + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +TEST_F(WebMContentEncodingsClientTest, EmptyContentEncoding) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x83, // ContentEncodings (size = 3) + 0x63, 0x40, 0x80, // ContentEncoding (size = 0) + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +TEST_F(WebMContentEncodingsClientTest, SingleContentEncoding) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0xA1, // ContentEncodings (size = 33) + 0x62, 0x40, 0x9e, // ContentEncoding (size = 30) + 0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1) + 0x50, 0x32, 0x81, 0x01, // ContentEncodingScope (size = 1) + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x8F, // ContentEncryption (size = 15) + 0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1) + 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8) + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + }; + int size = sizeof(kContentEncodings); + + int result = parser_.Parse(kContentEncodings, size); + ASSERT_EQ(size, result); + const ContentEncodings content_encodings = client_.content_encodings(); + ASSERT_EQ(1u, content_encodings.size()); + EXPECT_EQ(0, content_encodings[0]->order_); + EXPECT_EQ(ContentEncoding::kScopeAllFrameContents, + content_encodings[0]->scope_); + EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[0]->type_); + EXPECT_EQ(ContentEncoding::kEncAlgoAes, + content_encodings[0]->encryption_algo_); + EXPECT_TRUE(content_encodings[0]->encryption_key_id_.get()); + EXPECT_EQ(8, content_encodings[0]->encryption_key_id_size_); +} + +TEST_F(WebMContentEncodingsClientTest, MultipleContentEncoding) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0xC2, // ContentEncodings (size = 66) + 0x62, 0x40, 0x9e, // ContentEncoding (size = 30) + 0x50, 0x31, 0x81, 0x00, // ContentEncodingOrder (size = 1) + 0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1) + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x8F, // ContentEncryption (size = 15) + 0x47, 0xE1, 0x81, 0x05, // ContentEncAlgo (size = 1) + 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8) + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0x62, 0x40, 0x9e, // ContentEncoding (size = 30) + 0x50, 0x31, 0x81, 0x01, // ContentEncodingOrder (size = 1) + 0x50, 0x32, 0x81, 0x03, // ContentEncodingScope (size = 1) + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x8F, // ContentEncryption (size = 15) + 0x47, 0xE1, 0x81, 0x01, // ContentEncAlgo (size = 1) + 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8) + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + }; + int size = sizeof(kContentEncodings); + + int result = parser_.Parse(kContentEncodings, size); + ASSERT_EQ(size, result); + const ContentEncodings content_encodings = client_.content_encodings(); + ASSERT_EQ(2u, content_encodings.size()); + + for (int i = 0; i < 2; ++i) { + EXPECT_EQ(i, content_encodings[i]->order_); + EXPECT_EQ(ContentEncoding::kScopeAllFrameContents | + ContentEncoding::kScopeTrackPrivateData, + content_encodings[i]->scope_); + EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[i]->type_); + EXPECT_EQ(!i ? ContentEncoding::kEncAlgoAes : ContentEncoding::kEncAlgoDes, + content_encodings[i]->encryption_algo_); + EXPECT_TRUE(content_encodings[i]->encryption_key_id_.get()); + EXPECT_EQ(8, content_encodings[i]->encryption_key_id_size_); + } +} + +TEST_F(WebMContentEncodingsClientTest, DefaultValues) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x8A, // ContentEncodings (size = 10) + 0x62, 0x40, 0x87, // ContentEncoding (size = 7) + // ContentEncodingOrder missing + // ContentEncodingScope missing + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x80, // ContentEncryption (size = 0) + // ContentEncAlgo missing + }; + int size = sizeof(kContentEncodings); + + int result = parser_.Parse(kContentEncodings, size); + ASSERT_EQ(size, result); + const ContentEncodings content_encodings = client_.content_encodings(); + ASSERT_EQ(1u, content_encodings.size()); + EXPECT_EQ(0, content_encodings[0]->order_); + EXPECT_EQ(ContentEncoding::kScopeAllFrameContents, + content_encodings[0]->scope_); + EXPECT_EQ(ContentEncoding::kTypeEncryption, content_encodings[0]->type_); + EXPECT_EQ(ContentEncoding::kEncAlgoNotEncrypted, + content_encodings[0]->encryption_algo_); + EXPECT_FALSE(content_encodings[0]->encryption_key_id_.get()); + EXPECT_EQ(0, content_encodings[0]->encryption_key_id_size_); +} + +TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingOrder) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14) + 0x62, 0x40, 0x8B, // ContentEncoding (size = 11) + 0x50, 0x31, 0x81, 0xEE, // ContentEncodingOrder (size = 1), invalid + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x80, // ContentEncryption (size = 0) + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingScope) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14) + 0x62, 0x40, 0x8B, // ContentEncoding (size = 11) + 0x50, 0x32, 0x81, 0xEE, // ContentEncodingScope (size = 1), invalid + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x80, // ContentEncryption (size = 0) + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +TEST_F(WebMContentEncodingsClientTest, InvalidContentEncodingType) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x8E, // ContentEncodings (size = 14) + 0x62, 0x40, 0x8B, // ContentEncoding (size = 11) + 0x50, 0x33, 0x81, 0x00, // ContentEncodingType (size = 1), invalid + 0x50, 0x35, 0x80, // ContentEncryption (size = 0) + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +// ContentEncodingType is encryption but no ContentEncryption present. +TEST_F(WebMContentEncodingsClientTest, MissingContentEncryption) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x87, // ContentEncodings (size = 7) + 0x62, 0x40, 0x84, // ContentEncoding (size = 4) + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + // ContentEncryption missing + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +TEST_F(WebMContentEncodingsClientTest, InvalidContentEncAlgo) { + const uint8 kContentEncodings[] = { + 0x6D, 0x80, 0x99, // ContentEncodings (size = 25) + 0x62, 0x40, 0x96, // ContentEncoding (size = 22) + 0x50, 0x33, 0x81, 0x01, // ContentEncodingType (size = 1) + 0x50, 0x35, 0x8F, // ContentEncryption (size = 15) + 0x47, 0xE1, 0x81, 0xEE, // ContentEncAlgo (size = 1), invalid + 0x47, 0xE2, 0x88, // ContentEncKeyID (size = 8) + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + }; + int size = sizeof(kContentEncodings); + ParseAndExpectToFail(kContentEncodings, size); +} + +} // media diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc index d340b66..9757b10 100644 --- a/media/webm/webm_tracks_parser.cc +++ b/media/webm/webm_tracks_parser.cc @@ -45,16 +45,28 @@ int WebMTracksParser::Parse(const uint8* buf, int size) { WebMParserClient* WebMTracksParser::OnListStart(int id) { + if (id == kWebMIdContentEncodings) { + DCHECK(!track_content_encodings_client_.get()); + track_content_encodings_client_.reset(new WebMContentEncodingsClient); + return track_content_encodings_client_->OnListStart(id); + } + if (id == kWebMIdTrackEntry) { track_type_ = -1; track_num_ = -1; track_default_duration_ = -1; + return this; } return this; } bool WebMTracksParser::OnListEnd(int id) { + if (id == kWebMIdContentEncodings) { + DCHECK(track_content_encodings_client_.get()); + return track_content_encodings_client_->OnListEnd(id); + } + if (id == kWebMIdTrackEntry) { if (track_type_ == -1 || track_num_ == -1) { DVLOG(1) << "Missing TrackEntry data" @@ -74,9 +86,17 @@ bool WebMTracksParser::OnListEnd(int id) { if (track_type_ == kWebMTrackTypeVideo) { video_track_num_ = track_num_; video_default_duration_ = default_duration; + if (track_content_encodings_client_.get()) { + video_content_encodings_ = + track_content_encodings_client_->content_encodings(); + } } else if (track_type_ == kWebMTrackTypeAudio) { audio_track_num_ = track_num_; audio_default_duration_ = default_duration; + if (track_content_encodings_client_.get()) { + audio_content_encodings_ = + track_content_encodings_client_->content_encodings(); + } } else { DVLOG(1) << "Unexpected TrackType " << track_type_; return false; @@ -84,6 +104,8 @@ bool WebMTracksParser::OnListEnd(int id) { track_type_ = -1; track_num_ = -1; + track_content_encodings_client_.reset(); + return true; } return true; diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h index 5c5aeda..4626e8b 100644 --- a/media/webm/webm_tracks_parser.h +++ b/media/webm/webm_tracks_parser.h @@ -6,7 +6,9 @@ #define MEDIA_WEBM_WEBM_TRACKS_PARSER_H_ #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "base/time.h" +#include "media/webm/webm_content_encodings_client.h" #include "media/webm/webm_parser.h" namespace media { @@ -14,7 +16,7 @@ namespace media { // Parser for WebM Tracks element. class WebMTracksParser : public WebMParserClient { public: - WebMTracksParser(int64 timecode_scale); + explicit WebMTracksParser(int64 timecode_scale); virtual ~WebMTracksParser(); // Parses a WebM Tracks element in |buf|. @@ -48,10 +50,15 @@ class WebMTracksParser : public WebMParserClient { int64 track_type_; int64 track_num_; int64 track_default_duration_; + scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_; + int64 audio_track_num_; base::TimeDelta audio_default_duration_; + ContentEncodings audio_content_encodings_; + int64 video_track_num_; base::TimeDelta video_default_duration_; + ContentEncodings video_content_encodings_; DISALLOW_IMPLICIT_CONSTRUCTORS(WebMTracksParser); }; |