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

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

Issue 11830024: Do not require a key before processing unencrypted frames within a potentially encrypted stream. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 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
« media/crypto/aes_decryptor.cc ('K') | « media/crypto/aes_decryptor.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/memory/scoped_ptr.h"
8 #include "base/string_util.h" 9 #include "base/string_util.h"
9 #include "build/build_config.h" 10 #include "build/build_config.h"
10 #include "media/base/decoder_buffer.h" 11 #include "media/base/decoder_buffer.h"
11 #include "media/base/test_data_util.h" 12 #include "media/base/test_data_util.h"
12 #include "media/crypto/aes_decryptor.h" 13 #include "media/crypto/aes_decryptor.h"
13 14
14 using testing::AtMost; 15 using testing::AtMost;
15 16
16 namespace media { 17 namespace media {
17 18
(...skipping 18 matching lines...) Expand all
36 static const int kAppendTimeSec = 1; 37 static const int kAppendTimeSec = 1;
37 static const int kAppendTimeMs = kAppendTimeSec * 1000; 38 static const int kAppendTimeMs = kAppendTimeSec * 1000;
38 static const int k320WebMFileDurationMs = 2737; 39 static const int k320WebMFileDurationMs = 2737;
39 static const int k640WebMFileDurationMs = 2763; 40 static const int k640WebMFileDurationMs = 2763;
40 static const int k1280IsoFileDurationMs = 2736; 41 static const int k1280IsoFileDurationMs = 2736;
41 42
42 // Note: Tests using this class only exercise the DecryptingDemuxerStream path. 43 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
43 // They do not exercise the Decrypting{Audio|Video}Decoder path. 44 // They do not exercise the Decrypting{Audio|Video}Decoder path.
44 class FakeEncryptedMedia { 45 class FakeEncryptedMedia {
45 public: 46 public:
46 FakeEncryptedMedia() 47 // Defines the behavior of the "app" that responds to EME events.
48 class AppBase {
xhwang 2013/01/09 21:18:21 Looks like AppBase isn't doing a lot of work and i
ddorwin 2013/01/10 04:44:46 Done. I left KeyError since that's likely to be co
49 public:
50 virtual ~AppBase() {}
51
52 virtual void KeyAdded(const std::string& key_system,
53 const std::string& session_id) {
54 EXPECT_EQ(kClearKeySystem, key_system);
55 EXPECT_FALSE(session_id.empty());
56 FAIL() << "Unexpected KeyAdded";
57 }
58
59 virtual void KeyMessage(const std::string& key_system,
60 const std::string& session_id,
61 const std::string& message,
62 const std::string& default_url) {
63 EXPECT_EQ(kClearKeySystem, key_system);
64 EXPECT_FALSE(session_id.empty());
65 EXPECT_FALSE(message.empty());
66 FAIL() << "Unexpected KeyMessage";
67 }
68
69 virtual void NeedKey(const std::string& key_system,
70 const std::string& session_id,
71 const std::string& type,
72 scoped_array<uint8> init_data, int init_data_length,
73 AesDecryptor* decryptor) {
74 FAIL() << "Unexpected NeedKey";
75 }
76
77 virtual void KeyError(const std::string& key_system,
78 const std::string& session_id,
79 AesDecryptor::KeyError error_code,
80 int system_code) {
81 FAIL() << "Unexpected Key Error";
82 }
83 };
84
85 FakeEncryptedMedia(AppBase* app)
47 : decryptor_(base::Bind(&FakeEncryptedMedia::KeyAdded, 86 : decryptor_(base::Bind(&FakeEncryptedMedia::KeyAdded,
48 base::Unretained(this)), 87 base::Unretained(this)),
49 base::Bind(&FakeEncryptedMedia::KeyError, 88 base::Bind(&FakeEncryptedMedia::KeyError,
50 base::Unretained(this)), 89 base::Unretained(this)),
51 base::Bind(&FakeEncryptedMedia::KeyMessage, 90 base::Bind(&FakeEncryptedMedia::KeyMessage,
52 base::Unretained(this)), 91 base::Unretained(this)),
53 base::Bind(&FakeEncryptedMedia::NeedKey, 92 base::Bind(&FakeEncryptedMedia::NeedKey,
54 base::Unretained(this))) { 93 base::Unretained(this))),
94 app_(app) {
55 } 95 }
56 96
57 AesDecryptor* decryptor() { 97 AesDecryptor* decryptor() {
58 return &decryptor_; 98 return &decryptor_;
59 } 99 }
60 100
61 // Callbacks for firing key events. 101 // Callbacks for firing key events. Delegate to |app_|.
62 void KeyAdded(const std::string& key_system, const std::string& session_id) { 102 void KeyAdded(const std::string& key_system, const std::string& session_id) {
63 EXPECT_EQ(kClearKeySystem, key_system); 103 app_->KeyAdded(key_system, session_id);
64 EXPECT_FALSE(session_id.empty());
65 } 104 }
66 105
67 void KeyError(const std::string& key_system, 106 void KeyError(const std::string& key_system,
68 const std::string& session_id, 107 const std::string& session_id,
69 AesDecryptor::KeyError error_code, 108 AesDecryptor::KeyError error_code,
70 int system_code) { 109 int system_code) {
71 FAIL() << "Unexpected Key Error"; 110 app_->KeyError(key_system, session_id, error_code, system_code);
72 } 111 }
73 112
74 void KeyMessage(const std::string& key_system, 113 void KeyMessage(const std::string& key_system,
75 const std::string& session_id, 114 const std::string& session_id,
76 const std::string& message, 115 const std::string& message,
77 const std::string& default_url) { 116 const std::string& default_url) {
117 app_->KeyMessage(key_system, session_id, message, default_url);
118 }
119
120 void NeedKey(const std::string& key_system,
121 const std::string& session_id,
122 const std::string& type,
123 scoped_array<uint8> init_data, int init_data_length) {
124 app_->NeedKey(key_system, session_id, type,
125 init_data.Pass(), init_data_length, &decryptor_);
126 }
127
128 private:
129 AesDecryptor decryptor_;
130 scoped_ptr<AppBase> app_;
131 };
132
133 // Provides |kSecretKey| in response to needkey.
134 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
135 public:
136 void KeyAdded(const std::string& key_system,
137 const std::string& session_id) OVERRIDE {
138 EXPECT_EQ(kClearKeySystem, key_system);
139 EXPECT_FALSE(session_id.empty());
140 }
141
142 void KeyMessage(const std::string& key_system,
143 const std::string& session_id,
144 const std::string& message,
145 const std::string& default_url) OVERRIDE {
78 EXPECT_EQ(kClearKeySystem, key_system); 146 EXPECT_EQ(kClearKeySystem, key_system);
79 EXPECT_FALSE(session_id.empty()); 147 EXPECT_FALSE(session_id.empty());
80 EXPECT_FALSE(message.empty()); 148 EXPECT_FALSE(message.empty());
81 149
82 current_key_system_ = key_system; 150 current_key_system_ = key_system;
83 current_session_id_ = session_id; 151 current_session_id_ = session_id;
84 } 152 }
85 153
86 void NeedKey(const std::string& key_system, 154 void NeedKey(const std::string& key_system,
87 const std::string& session_id, 155 const std::string& session_id,
88 const std::string& type, 156 const std::string& type,
89 scoped_array<uint8> init_data, int init_data_length) { 157 scoped_array<uint8> init_data, int init_data_length,
158 AesDecryptor* decryptor) OVERRIDE {
90 current_key_system_ = key_system; 159 current_key_system_ = key_system;
91 current_session_id_ = session_id; 160 current_session_id_ = session_id;
92 161
93 // When NeedKey is called from the demuxer, the |key_system| will be empty. 162 // When NeedKey is called from the demuxer, the |key_system| will be empty.
94 // In this case, we need to call GenerateKeyRequest() to initialize a 163 // In this case, we need to call GenerateKeyRequest() to initialize a
95 // session (which will call KeyMessage). 164 // session (which will call KeyMessage).
96 if (current_key_system_.empty()) { 165 if (current_key_system_.empty()) {
97 EXPECT_TRUE(current_session_id_.empty()); 166 EXPECT_TRUE(current_session_id_.empty());
98 EXPECT_TRUE(decryptor_.GenerateKeyRequest( 167 EXPECT_TRUE(decryptor->GenerateKeyRequest(
99 kClearKeySystem, type, kInitData, arraysize(kInitData))); 168 kClearKeySystem, type, kInitData, arraysize(kInitData)));
100 } 169 }
101 170
102 EXPECT_FALSE(current_key_system_.empty()); 171 EXPECT_FALSE(current_key_system_.empty());
103 EXPECT_FALSE(current_session_id_.empty()); 172 EXPECT_FALSE(current_session_id_.empty());
104 decryptor_.AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey), 173 decryptor->AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey),
105 init_data.get(), init_data_length, current_session_id_); 174 init_data.get(), init_data_length, current_session_id_);
106 } 175 }
107 176
108 private:
109 AesDecryptor decryptor_;
110 std::string current_key_system_; 177 std::string current_key_system_;
111 std::string current_session_id_; 178 std::string current_session_id_;
112 }; 179 };
113 180
181 // Ignores needkey and does not perform a license request
182 class NoResponseApp : public FakeEncryptedMedia::AppBase {
183 public:
184 void NeedKey(const std::string& key_system,
185 const std::string& session_id,
186 const std::string& type,
187 scoped_array<uint8> init_data, int init_data_length,
188 AesDecryptor* decryptor) OVERRIDE {
189 }
190 };
191
114 // Helper class that emulates calls made on the ChunkDemuxer by the 192 // Helper class that emulates calls made on the ChunkDemuxer by the
115 // Media Source API. 193 // Media Source API.
116 class MockMediaSource { 194 class MockMediaSource {
117 public: 195 public:
118 MockMediaSource(const std::string& filename, const std::string& mimetype, 196 MockMediaSource(const std::string& filename, const std::string& mimetype,
119 int initial_append_size) 197 int initial_append_size)
120 : file_path_(GetTestDataFilePath(filename)), 198 : file_path_(GetTestDataFilePath(filename)),
121 current_position_(0), 199 current_position_(0),
122 initial_append_size_(initial_append_size), 200 initial_append_size_(initial_append_size),
123 mimetype_(mimetype) { 201 mimetype_(mimetype) {
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 Play(); 430 Play();
353 431
354 EXPECT_TRUE(WaitUntilOnEnded()); 432 EXPECT_TRUE(WaitUntilOnEnded());
355 source.Abort(); 433 source.Abort();
356 Stop(); 434 Stop();
357 } 435 }
358 436
359 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) { 437 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
360 MockMediaSource source("bear-320x240-16x9-aspect-av-enc_av.webm", kWebM, 438 MockMediaSource source("bear-320x240-16x9-aspect-av-enc_av.webm", kWebM,
361 kAppendWholeFile); 439 kAppendWholeFile);
362 FakeEncryptedMedia encrypted_media; 440 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
363 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 441 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
364 442
365 scoped_refptr<DecoderBuffer> second_file = 443 scoped_refptr<DecoderBuffer> second_file =
366 ReadTestDataFile("bear-640x360-av-enc_av.webm"); 444 ReadTestDataFile("bear-640x360-av-enc_av.webm");
367 445
368 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 446 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
369 second_file->GetData(), second_file->GetDataSize()); 447 second_file->GetData(), second_file->GetDataSize());
370 448
371 source.EndOfStream(); 449 source.EndOfStream();
372 450
373 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); 451 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
374 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); 452 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
375 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs, 453 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
376 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); 454 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
377 455
378 Play(); 456 Play();
379 457
380 EXPECT_TRUE(WaitUntilOnEnded()); 458 EXPECT_TRUE(WaitUntilOnEnded());
381 source.Abort(); 459 source.Abort();
382 Stop(); 460 Stop();
383 } 461 }
384 462
385 // Config changes from encrypted to clear are not currently supported. 463 // Config changes from encrypted to clear are not currently supported.
386 TEST_F(PipelineIntegrationTest, 464 TEST_F(PipelineIntegrationTest,
387 MediaSource_ConfigChange_ClearThenEncrypted_WebM) { 465 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
388 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM, 466 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
389 kAppendWholeFile); 467 kAppendWholeFile);
390 FakeEncryptedMedia encrypted_media; 468 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
391 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 469 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
392 470
393 scoped_refptr<DecoderBuffer> second_file = 471 scoped_refptr<DecoderBuffer> second_file =
394 ReadTestDataFile("bear-640x360-av-enc_av.webm"); 472 ReadTestDataFile("bear-640x360-av-enc_av.webm");
395 473
396 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 474 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
397 second_file->GetData(), second_file->GetDataSize()); 475 second_file->GetData(), second_file->GetDataSize());
398 476
399 source.EndOfStream(); 477 source.EndOfStream();
400 478
(...skipping 10 matching lines...) Expand all
411 489
412 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); 490 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
413 source.Abort(); 491 source.Abort();
414 } 492 }
415 493
416 // Config changes from clear to encrypted are not currently supported. 494 // Config changes from clear to encrypted are not currently supported.
417 TEST_F(PipelineIntegrationTest, 495 TEST_F(PipelineIntegrationTest,
418 MediaSource_ConfigChange_EncryptedThenClear_WebM) { 496 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
419 MockMediaSource source("bear-320x240-16x9-aspect-av-enc_av.webm", kWebM, 497 MockMediaSource source("bear-320x240-16x9-aspect-av-enc_av.webm", kWebM,
420 kAppendWholeFile); 498 kAppendWholeFile);
421 FakeEncryptedMedia encrypted_media; 499 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
422 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 500 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
423 501
424 scoped_refptr<DecoderBuffer> second_file = 502 scoped_refptr<DecoderBuffer> second_file =
425 ReadTestDataFile("bear-640x360.webm"); 503 ReadTestDataFile("bear-640x360.webm");
426 504
427 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 505 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
428 second_file->GetData(), second_file->GetDataSize()); 506 second_file->GetData(), second_file->GetDataSize());
429 507
430 source.EndOfStream(); 508 source.EndOfStream();
431 509
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 547
470 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) { 548 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
471 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"), 549 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
472 PIPELINE_OK)); 550 PIPELINE_OK));
473 Play(); 551 Play();
474 ASSERT_TRUE(WaitUntilOnEnded()); 552 ASSERT_TRUE(WaitUntilOnEnded());
475 } 553 }
476 554
477 TEST_F(PipelineIntegrationTest, EncryptedPlayback) { 555 TEST_F(PipelineIntegrationTest, EncryptedPlayback) {
478 MockMediaSource source("bear-320x240-encrypted.webm", kWebM, 219816); 556 MockMediaSource source("bear-320x240-encrypted.webm", kWebM, 219816);
479 FakeEncryptedMedia encrypted_media; 557 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
480 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 558 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
481 559
482 source.EndOfStream(); 560 source.EndOfStream();
561 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
562
563 Play();
564
565 ASSERT_TRUE(WaitUntilOnEnded());
566 source.Abort();
567 Stop();
568 }
569
570 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames) {
571 MockMediaSource source("bear-320x240-av-enc_av_un-all.webm",
572 kWebM, kAppendWholeFile);
573 FakeEncryptedMedia encrypted_media(new NoResponseApp());
574 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
575
576 source.EndOfStream();
483 ASSERT_EQ(PIPELINE_OK, pipeline_status_); 577 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
484 578
485 Play(); 579 Play();
486 580
487 ASSERT_TRUE(WaitUntilOnEnded()); 581 ASSERT_TRUE(WaitUntilOnEnded());
488 source.Abort(); 582 source.Abort();
489 Stop(); 583 Stop();
490 } 584 }
491 585
492 // TODO(acolwell): Fix flakiness http://crbug.com/117921 586 // TODO(acolwell): Fix flakiness http://crbug.com/117921
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 // Verify video decoder & renderer can handle aborted demuxer reads. 639 // Verify video decoder & renderer can handle aborted demuxer reads.
546 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { 640 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
547 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM, 641 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
548 32768, 642 32768,
549 base::TimeDelta::FromMilliseconds(200), 643 base::TimeDelta::FromMilliseconds(200),
550 base::TimeDelta::FromMilliseconds(1668), 644 base::TimeDelta::FromMilliseconds(1668),
551 0x1C896, 65536)); 645 0x1C896, 65536));
552 } 646 }
553 647
554 } // namespace media 648 } // namespace media
OLDNEW
« media/crypto/aes_decryptor.cc ('K') | « media/crypto/aes_decryptor.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698