Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(430)

Side by Side Diff: media/filters/pipeline_integration_test.cc

Issue 10534096: Generalize AesDecryptor to make it more spec compliant. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated to pass layout tests. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/pipeline_integration_test_base.h" 5 #include "media/filters/pipeline_integration_test_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "media/base/decoder_buffer.h" 8 #include "media/base/decoder_buffer.h"
9 #include "media/base/mock_filters.h"
9 #include "media/base/test_data_util.h" 10 #include "media/base/test_data_util.h"
11 #include "media/crypto/aes_decryptor.h"
12 #include "media/crypto/decryptor_client.h"
10 #include "media/filters/chunk_demuxer_client.h" 13 #include "media/filters/chunk_demuxer_client.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 using ::testing::_;
11 17
12 namespace media { 18 namespace media {
13 19
14 // Key ID of the video track in test file "bear-320x240-encrypted.webm". 20 static const char kSourceId[] = "SourceId";
15 static const unsigned char kKeyId[] = 21 static const char kClearKeySystem[] = "org.w3.clearkey";
16 "\x11\xa5\x18\x37\xc4\x73\x84\x03\xe5\xe6\x57\xed\x8e\x06\xd9\x7c"; 22 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
17
18 static const char* kSourceId = "SourceId";
19 23
20 // Helper class that emulates calls made on the ChunkDemuxer by the 24 // Helper class that emulates calls made on the ChunkDemuxer by the
21 // Media Source API. 25 // Media Source API.
22 class MockMediaSource : public ChunkDemuxerClient { 26 class MockMediaSource : public ChunkDemuxerClient {
23 public: 27 public:
24 MockMediaSource(const std::string& filename, int initial_append_size) 28 MockMediaSource(const std::string& filename, int initial_append_size)
25 : url_(GetTestDataURL(filename)), 29 : url_(GetTestDataURL(filename)),
26 current_position_(0), 30 current_position_(0),
27 initial_append_size_(initial_append_size) { 31 initial_append_size_(initial_append_size) {
28 file_data_ = ReadTestDataFile(filename); 32 file_data_ = ReadTestDataFile(filename);
29 33
30 DCHECK_GT(initial_append_size_, 0); 34 DCHECK_GT(initial_append_size_, 0);
31 DCHECK_LE(initial_append_size_, file_data_->GetDataSize()); 35 DCHECK_LE(initial_append_size_, file_data_->GetDataSize());
32 } 36 }
33 37
34 virtual ~MockMediaSource() {} 38 virtual ~MockMediaSource() {}
35 39
36 void set_decryptor(AesDecryptor* decryptor) { 40 void set_decryptor_client(DecryptorClient* decryptor_client) {
37 decryptor_ = decryptor; 41 decryptor_client_ = decryptor_client;
38 }
39 AesDecryptor* decryptor() const {
40 return decryptor_;
41 } 42 }
42 43
43 const std::string& url() const { return url_; } 44 const std::string& url() const { return url_; }
44 45
45 void Seek(int new_position, int seek_append_size) { 46 void Seek(int new_position, int seek_append_size) {
46 chunk_demuxer_->StartWaitingForSeek(); 47 chunk_demuxer_->StartWaitingForSeek();
47 48
48 chunk_demuxer_->Abort(kSourceId); 49 chunk_demuxer_->Abort(kSourceId);
49 50
50 DCHECK_GE(new_position, 0); 51 DCHECK_GE(new_position, 0);
(...skipping 30 matching lines...) Expand all
81 codecs[0] = "vp8"; 82 codecs[0] = "vp8";
82 codecs[1] = "vorbis"; 83 codecs[1] = "vorbis";
83 chunk_demuxer_->AddId(kSourceId, "video/webm", codecs); 84 chunk_demuxer_->AddId(kSourceId, "video/webm", codecs);
84 AppendData(initial_append_size_); 85 AppendData(initial_append_size_);
85 } 86 }
86 87
87 virtual void DemuxerClosed() { 88 virtual void DemuxerClosed() {
88 chunk_demuxer_ = NULL; 89 chunk_demuxer_ = NULL;
89 } 90 }
90 91
91 virtual void KeyNeeded(scoped_array<uint8> init_data, int init_data_size) { 92 virtual void DemuxerNeedKey(scoped_array<uint8> init_data,
93 int init_data_size) {
92 DCHECK(init_data.get()); 94 DCHECK(init_data.get());
93 DCHECK_EQ(init_data_size, 16); 95 DCHECK_EQ(init_data_size, 16);
94 DCHECK(decryptor()); 96 DCHECK(decryptor_client_);
95 // In test file bear-320x240-encrypted.webm, the decryption key is equal to 97 decryptor_client_->NeedKey("", "", init_data.Pass(), init_data_size);
96 // |init_data|.
97 decryptor()->AddKey(init_data.get(), init_data_size,
98 init_data.get(), init_data_size);
99 } 98 }
100 99
101 private: 100 private:
102 std::string url_; 101 std::string url_;
103 scoped_refptr<DecoderBuffer> file_data_; 102 scoped_refptr<DecoderBuffer> file_data_;
104 int current_position_; 103 int current_position_;
105 int initial_append_size_; 104 int initial_append_size_;
106 scoped_refptr<ChunkDemuxer> chunk_demuxer_; 105 scoped_refptr<ChunkDemuxer> chunk_demuxer_;
107 AesDecryptor* decryptor_; 106 DecryptorClient* decryptor_client_;
107 };
108
109 class MockEncryptedMedia : public MockDecryptorClient {
scherkus (not reviewing) 2012/06/13 23:35:08 does this need to extend MockDecryptorClient? if
xhwang 2012/06/15 01:41:04 Done.
110 public:
111 MockEncryptedMedia() : decryptor_(this) {}
112
113 AesDecryptor* decryptor() {
114 return &decryptor_;
115 }
116
117 // DecryptorClient implementation.
118 virtual void KeyMessage(const std::string& key_system,
119 const std::string& session_id,
120 scoped_array<uint8> message,
121 int message_length,
122 const std::string& default_url) {
123 EXPECT_TRUE(key_system == kClearKeySystem);
124 EXPECT_TRUE(!session_id.empty());
125 EXPECT_TRUE(message.get());
126 EXPECT_GT(message_length, 0);
scherkus (not reviewing) 2012/06/13 23:35:08 do we not care what the message is?
xhwang 2012/06/15 01:41:04 Currently the AesDecryptor just returns the init_d
127 key_system_string_ = key_system;
128 session_id_string_ = session_id;
129 }
130
131 virtual void NeedKey(const std::string& key_system,
132 const std::string& session_id,
133 scoped_array<uint8> init_data,
134 int init_data_length) {
135 key_system_string_ = key_system;
136 session_id_string_ = session_id;
137 if (key_system_string_.empty()) {
scherkus (not reviewing) 2012/06/13 23:35:08 do we fire need key w/ empty key system today?
xhwang 2012/06/15 01:41:04 Yes. When NeedKey is fired from the demuxer. Added
138 DCHECK(session_id_string_.empty());
139 decryptor_.GenerateKeyRequest(kClearKeySystem,
140 kInitData, arraysize(kInitData));
141 }
142
143 EXPECT_FALSE(key_system_string_.empty());
scherkus (not reviewing) 2012/06/13 23:35:08 based on if statement above it looks like key_syst
ddorwin 2012/06/14 21:04:04 This assumes KeyMessage gets called (and that AesD
xhwang 2012/06/15 01:41:04 Done.
144 EXPECT_FALSE(session_id_string_.empty());
145 // In test file bear-320x240-encrypted.webm, the decryption key is equal to
146 // |init_data|.
147 decryptor_.AddKey(key_system_string_, init_data.get(), init_data_length,
148 init_data.get(), init_data_length, session_id_string_);
149 }
150
151 private:
152 AesDecryptor decryptor_;
153 std::string key_system_string_;
154 std::string session_id_string_;
108 }; 155 };
109 156
110 class PipelineIntegrationTest 157 class PipelineIntegrationTest
111 : public testing::Test, 158 : public testing::Test,
112 public PipelineIntegrationTestBase { 159 public PipelineIntegrationTestBase {
113 public: 160 public:
114 void StartPipelineWithMediaSource(MockMediaSource& source) { 161 void StartPipelineWithMediaSource(MockMediaSource* source) {
115 pipeline_->Start( 162 pipeline_->Start(
116 CreateFilterCollection(&source), 163 CreateFilterCollection(source),
117 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), 164 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
118 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), 165 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
119 NetworkEventCB(), QuitOnStatusCB(PIPELINE_OK)); 166 NetworkEventCB(), QuitOnStatusCB(PIPELINE_OK));
120 167
121 ASSERT_TRUE(decoder_.get()); 168 ASSERT_TRUE(decoder_.get());
122 source.set_decryptor(decryptor_.get());
123 169
124 message_loop_.Run(); 170 message_loop_.Run();
125 } 171 }
172
173 void StartPipelineWithEncryptedMedia(MockMediaSource* source,
174 MockEncryptedMedia* encrypted_media) {
175 pipeline_->Start(
176 CreateFilterCollection(source),
177 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
178 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
179 NetworkEventCB(), QuitOnStatusCB(PIPELINE_OK));
180
181 ASSERT_TRUE(decoder_.get());
182 decoder_->set_decryptor(encrypted_media->decryptor());
183 source->set_decryptor_client(encrypted_media);
184
185 EXPECT_CALL(*encrypted_media, KeyAdded(kClearKeySystem, _));
186
187 message_loop_.Run();
188 }
126 189
127 // Verifies that seeking works properly for ChunkDemuxer when the 190 // Verifies that seeking works properly for ChunkDemuxer when the
128 // seek happens while there is a pending read on the ChunkDemuxer 191 // seek happens while there is a pending read on the ChunkDemuxer
129 // and no data is available. 192 // and no data is available.
130 bool TestSeekDuringRead(const std::string& filename, 193 bool TestSeekDuringRead(const std::string& filename,
131 int initial_append_size, 194 int initial_append_size,
132 base::TimeDelta start_seek_time, 195 base::TimeDelta start_seek_time,
133 base::TimeDelta seek_time, 196 base::TimeDelta seek_time,
134 int seek_file_position, 197 int seek_file_position,
135 int seek_append_size) { 198 int seek_append_size) {
136 MockMediaSource source(filename, initial_append_size); 199 MockMediaSource source(filename, initial_append_size);
137 StartPipelineWithMediaSource(source); 200 StartPipelineWithMediaSource(&source);
138 201
139 if (pipeline_status_ != PIPELINE_OK) 202 if (pipeline_status_ != PIPELINE_OK)
140 return false; 203 return false;
141 204
142 Play(); 205 Play();
143 if (!WaitUntilCurrentTimeIsAfter(start_seek_time)) 206 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
144 return false; 207 return false;
145 208
146 source.Seek(seek_file_position, seek_append_size); 209 source.Seek(seek_file_position, seek_append_size);
147 if (!Seek(seek_time)) 210 if (!Seek(seek_time))
(...skipping 22 matching lines...) Expand all
170 Play(); 233 Play();
171 234
172 ASSERT_TRUE(WaitUntilOnEnded()); 235 ASSERT_TRUE(WaitUntilOnEnded());
173 236
174 EXPECT_EQ(GetVideoHash(), "f0be120a90a811506777c99a2cdf7cc1"); 237 EXPECT_EQ(GetVideoHash(), "f0be120a90a811506777c99a2cdf7cc1");
175 EXPECT_EQ(GetAudioHash(), "6138555be3389e6aba4c8e6f70195d50"); 238 EXPECT_EQ(GetAudioHash(), "6138555be3389e6aba4c8e6f70195d50");
176 } 239 }
177 240
178 TEST_F(PipelineIntegrationTest, EncryptedPlayback) { 241 TEST_F(PipelineIntegrationTest, EncryptedPlayback) {
179 MockMediaSource source("bear-320x240-encrypted.webm", 219726); 242 MockMediaSource source("bear-320x240-encrypted.webm", 219726);
180 StartPipelineWithMediaSource(source); 243 MockEncryptedMedia encrypted_media;
244 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
181 245
182 source.EndOfStream(); 246 source.EndOfStream();
183 ASSERT_EQ(PIPELINE_OK, pipeline_status_); 247 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
184 248
185 Play(); 249 Play();
186 250
187 ASSERT_TRUE(WaitUntilOnEnded()); 251 ASSERT_TRUE(WaitUntilOnEnded());
188 source.Abort(); 252 source.Abort();
189 Stop(); 253 Stop();
190 } 254 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 307
244 // Verify video decoder & renderer can handle aborted demuxer reads. 308 // Verify video decoder & renderer can handle aborted demuxer reads.
245 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { 309 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
246 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", 32768, 310 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", 32768,
247 base::TimeDelta::FromMilliseconds(200), 311 base::TimeDelta::FromMilliseconds(200),
248 base::TimeDelta::FromMilliseconds(1668), 312 base::TimeDelta::FromMilliseconds(1668),
249 0x1C896, 65536)); 313 0x1C896, 65536));
250 } 314 }
251 315
252 } // namespace media 316 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698