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

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: rebased 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
« no previous file with comments | « 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 24 matching lines...) Expand all
42 static const int kAppendTimeSec = 1; 43 static const int kAppendTimeSec = 1;
43 static const int kAppendTimeMs = kAppendTimeSec * 1000; 44 static const int kAppendTimeMs = kAppendTimeSec * 1000;
44 static const int k320WebMFileDurationMs = 2737; 45 static const int k320WebMFileDurationMs = 2737;
45 static const int k640WebMFileDurationMs = 2763; 46 static const int k640WebMFileDurationMs = 2763;
46 static const int k1280IsoFileDurationMs = 2736; 47 static const int k1280IsoFileDurationMs = 2736;
47 48
48 // Note: Tests using this class only exercise the DecryptingDemuxerStream path. 49 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
49 // They do not exercise the Decrypting{Audio|Video}Decoder path. 50 // They do not exercise the Decrypting{Audio|Video}Decoder path.
50 class FakeEncryptedMedia { 51 class FakeEncryptedMedia {
51 public: 52 public:
52 FakeEncryptedMedia() 53 // Defines the behavior of the "app" that responds to EME events.
54 class AppBase {
55 public:
56 virtual ~AppBase() {}
57
58 virtual void KeyAdded(const std::string& key_system,
59 const std::string& session_id) = 0;
60
61 // Errors are not expected unless overridden.
62 virtual void KeyError(const std::string& key_system,
63 const std::string& session_id,
64 AesDecryptor::KeyError error_code,
65 int system_code) {
66 FAIL() << "Unexpected Key Error";
67 }
68
69 virtual void KeyMessage(const std::string& key_system,
70 const std::string& session_id,
71 const std::string& message,
72 const std::string& default_url) = 0;
73
74 virtual void NeedKey(const std::string& key_system,
75 const std::string& session_id,
76 const std::string& type,
77 scoped_array<uint8> init_data, int init_data_length,
78 AesDecryptor* decryptor) = 0;
79 };
80
81 FakeEncryptedMedia(AppBase* app)
53 : decryptor_(base::Bind(&FakeEncryptedMedia::KeyAdded, 82 : decryptor_(base::Bind(&FakeEncryptedMedia::KeyAdded,
54 base::Unretained(this)), 83 base::Unretained(this)),
55 base::Bind(&FakeEncryptedMedia::KeyError, 84 base::Bind(&FakeEncryptedMedia::KeyError,
56 base::Unretained(this)), 85 base::Unretained(this)),
57 base::Bind(&FakeEncryptedMedia::KeyMessage, 86 base::Bind(&FakeEncryptedMedia::KeyMessage,
58 base::Unretained(this)), 87 base::Unretained(this)),
59 base::Bind(&FakeEncryptedMedia::NeedKey, 88 base::Bind(&FakeEncryptedMedia::NeedKey,
60 base::Unretained(this))) { 89 base::Unretained(this))),
90 app_(app) {
61 } 91 }
62 92
63 AesDecryptor* decryptor() { 93 AesDecryptor* decryptor() {
64 return &decryptor_; 94 return &decryptor_;
65 } 95 }
66 96
67 // Callbacks for firing key events. 97 // Callbacks for firing key events. Delegate to |app_|.
68 void KeyAdded(const std::string& key_system, const std::string& session_id) { 98 void KeyAdded(const std::string& key_system, const std::string& session_id) {
69 EXPECT_EQ(kClearKeySystem, key_system); 99 app_->KeyAdded(key_system, session_id);
70 EXPECT_FALSE(session_id.empty());
71 } 100 }
72 101
73 void KeyError(const std::string& key_system, 102 void KeyError(const std::string& key_system,
74 const std::string& session_id, 103 const std::string& session_id,
75 AesDecryptor::KeyError error_code, 104 AesDecryptor::KeyError error_code,
76 int system_code) { 105 int system_code) {
77 FAIL() << "Unexpected Key Error"; 106 app_->KeyError(key_system, session_id, error_code, system_code);
78 } 107 }
79 108
80 void KeyMessage(const std::string& key_system, 109 void KeyMessage(const std::string& key_system,
81 const std::string& session_id, 110 const std::string& session_id,
82 const std::string& message, 111 const std::string& message,
83 const std::string& default_url) { 112 const std::string& default_url) {
113 app_->KeyMessage(key_system, session_id, message, default_url);
114 }
115
116 void NeedKey(const std::string& key_system,
117 const std::string& session_id,
118 const std::string& type,
119 scoped_array<uint8> init_data, int init_data_length) {
120 app_->NeedKey(key_system, session_id, type,
121 init_data.Pass(), init_data_length, &decryptor_);
122 }
123
124 private:
125 AesDecryptor decryptor_;
126 scoped_ptr<AppBase> app_;
127 };
128
129 // Provides |kSecretKey| in response to needkey.
130 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
131 public:
132 virtual void KeyAdded(const std::string& key_system,
133 const std::string& session_id) OVERRIDE {
134 EXPECT_EQ(kClearKeySystem, key_system);
135 EXPECT_FALSE(session_id.empty());
136 }
137
138 virtual void KeyMessage(const std::string& key_system,
139 const std::string& session_id,
140 const std::string& message,
141 const std::string& default_url) OVERRIDE {
84 EXPECT_EQ(kClearKeySystem, key_system); 142 EXPECT_EQ(kClearKeySystem, key_system);
85 EXPECT_FALSE(session_id.empty()); 143 EXPECT_FALSE(session_id.empty());
86 EXPECT_FALSE(message.empty()); 144 EXPECT_FALSE(message.empty());
87 145
88 current_key_system_ = key_system; 146 current_key_system_ = key_system;
89 current_session_id_ = session_id; 147 current_session_id_ = session_id;
90 } 148 }
91 149
92 void NeedKey(const std::string& key_system, 150 virtual void NeedKey(const std::string& key_system,
93 const std::string& session_id, 151 const std::string& session_id,
94 const std::string& type, 152 const std::string& type,
95 scoped_array<uint8> init_data, int init_data_length) { 153 scoped_array<uint8> init_data, int init_data_length,
154 AesDecryptor* decryptor) OVERRIDE {
96 current_key_system_ = key_system; 155 current_key_system_ = key_system;
97 current_session_id_ = session_id; 156 current_session_id_ = session_id;
98 157
99 // When NeedKey is called from the demuxer, the |key_system| will be empty. 158 // When NeedKey is called from the demuxer, the |key_system| will be empty.
100 // In this case, we need to call GenerateKeyRequest() to initialize a 159 // In this case, we need to call GenerateKeyRequest() to initialize a
101 // session (which will call KeyMessage). 160 // session (which will call KeyMessage).
102 if (current_key_system_.empty()) { 161 if (current_key_system_.empty()) {
103 EXPECT_TRUE(current_session_id_.empty()); 162 EXPECT_TRUE(current_session_id_.empty());
104 EXPECT_TRUE(decryptor_.GenerateKeyRequest( 163 EXPECT_TRUE(decryptor->GenerateKeyRequest(
105 kClearKeySystem, type, kInitData, arraysize(kInitData))); 164 kClearKeySystem, type, kInitData, arraysize(kInitData)));
106 } 165 }
107 166
108 EXPECT_FALSE(current_key_system_.empty()); 167 EXPECT_FALSE(current_key_system_.empty());
109 EXPECT_FALSE(current_session_id_.empty()); 168 EXPECT_FALSE(current_session_id_.empty());
110 decryptor_.AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey), 169 decryptor->AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey),
111 init_data.get(), init_data_length, current_session_id_); 170 init_data.get(), init_data_length, current_session_id_);
112 } 171 }
113 172
114 private:
115 AesDecryptor decryptor_;
116 std::string current_key_system_; 173 std::string current_key_system_;
117 std::string current_session_id_; 174 std::string current_session_id_;
118 }; 175 };
119 176
177 // Ignores needkey and does not perform a license request
178 class NoResponseApp : public FakeEncryptedMedia::AppBase {
179 public:
180 virtual void KeyAdded(const std::string& key_system,
181 const std::string& session_id) OVERRIDE {
182 EXPECT_EQ(kClearKeySystem, key_system);
183 EXPECT_FALSE(session_id.empty());
184 FAIL() << "Unexpected KeyAdded";
185 }
186
187 virtual void KeyMessage(const std::string& key_system,
188 const std::string& session_id,
189 const std::string& message,
190 const std::string& default_url) OVERRIDE {
191 EXPECT_EQ(kClearKeySystem, key_system);
192 EXPECT_FALSE(session_id.empty());
193 EXPECT_FALSE(message.empty());
194 FAIL() << "Unexpected KeyMessage";
195 }
196
197 virtual void NeedKey(const std::string& key_system,
198 const std::string& session_id,
199 const std::string& type,
200 scoped_array<uint8> init_data, int init_data_length,
201 AesDecryptor* decryptor) OVERRIDE {
202 }
203 };
204
120 // Helper class that emulates calls made on the ChunkDemuxer by the 205 // Helper class that emulates calls made on the ChunkDemuxer by the
121 // Media Source API. 206 // Media Source API.
122 class MockMediaSource { 207 class MockMediaSource {
123 public: 208 public:
124 MockMediaSource(const std::string& filename, const std::string& mimetype, 209 MockMediaSource(const std::string& filename, const std::string& mimetype,
125 int initial_append_size) 210 int initial_append_size)
126 : file_path_(GetTestDataFilePath(filename)), 211 : file_path_(GetTestDataFilePath(filename)),
127 current_position_(0), 212 current_position_(0),
128 initial_append_size_(initial_append_size), 213 initial_append_size_(initial_append_size),
129 mimetype_(mimetype) { 214 mimetype_(mimetype) {
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 Play(); 443 Play();
359 444
360 EXPECT_TRUE(WaitUntilOnEnded()); 445 EXPECT_TRUE(WaitUntilOnEnded());
361 source.Abort(); 446 source.Abort();
362 Stop(); 447 Stop();
363 } 448 }
364 449
365 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) { 450 TEST_F(PipelineIntegrationTest, MediaSource_ConfigChange_Encrypted_WebM) {
366 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM, 451 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
367 kAppendWholeFile); 452 kAppendWholeFile);
368 FakeEncryptedMedia encrypted_media; 453 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
369 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 454 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
370 455
371 scoped_refptr<DecoderBuffer> second_file = 456 scoped_refptr<DecoderBuffer> second_file =
372 ReadTestDataFile("bear-640x360-av_enc-av.webm"); 457 ReadTestDataFile("bear-640x360-av_enc-av.webm");
373 458
374 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 459 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
375 second_file->GetData(), second_file->GetDataSize()); 460 second_file->GetData(), second_file->GetDataSize());
376 461
377 source.EndOfStream(); 462 source.EndOfStream();
378 463
379 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); 464 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
380 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); 465 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
381 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs, 466 EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
382 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); 467 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
383 468
384 Play(); 469 Play();
385 470
386 EXPECT_TRUE(WaitUntilOnEnded()); 471 EXPECT_TRUE(WaitUntilOnEnded());
387 source.Abort(); 472 source.Abort();
388 Stop(); 473 Stop();
389 } 474 }
390 475
391 // Config changes from encrypted to clear are not currently supported. 476 // Config changes from encrypted to clear are not currently supported.
392 TEST_F(PipelineIntegrationTest, 477 TEST_F(PipelineIntegrationTest,
393 MediaSource_ConfigChange_ClearThenEncrypted_WebM) { 478 MediaSource_ConfigChange_ClearThenEncrypted_WebM) {
394 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM, 479 MockMediaSource source("bear-320x240-16x9-aspect.webm", kWebM,
395 kAppendWholeFile); 480 kAppendWholeFile);
396 FakeEncryptedMedia encrypted_media; 481 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
397 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 482 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
398 483
399 scoped_refptr<DecoderBuffer> second_file = 484 scoped_refptr<DecoderBuffer> second_file =
400 ReadTestDataFile("bear-640x360-av_enc-av.webm"); 485 ReadTestDataFile("bear-640x360-av_enc-av.webm");
401 486
402 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 487 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
403 second_file->GetData(), second_file->GetDataSize()); 488 second_file->GetData(), second_file->GetDataSize());
404 489
405 source.EndOfStream(); 490 source.EndOfStream();
406 491
(...skipping 10 matching lines...) Expand all
417 502
418 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); 503 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError());
419 source.Abort(); 504 source.Abort();
420 } 505 }
421 506
422 // Config changes from clear to encrypted are not currently supported. 507 // Config changes from clear to encrypted are not currently supported.
423 TEST_F(PipelineIntegrationTest, 508 TEST_F(PipelineIntegrationTest,
424 MediaSource_ConfigChange_EncryptedThenClear_WebM) { 509 MediaSource_ConfigChange_EncryptedThenClear_WebM) {
425 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM, 510 MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm", kWebM,
426 kAppendWholeFile); 511 kAppendWholeFile);
427 FakeEncryptedMedia encrypted_media; 512 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
428 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 513 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
429 514
430 scoped_refptr<DecoderBuffer> second_file = 515 scoped_refptr<DecoderBuffer> second_file =
431 ReadTestDataFile("bear-640x360.webm"); 516 ReadTestDataFile("bear-640x360.webm");
432 517
433 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), 518 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
434 second_file->GetData(), second_file->GetDataSize()); 519 second_file->GetData(), second_file->GetDataSize());
435 520
436 source.EndOfStream(); 521 source.EndOfStream();
437 522
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 } 558 }
474 #endif 559 #endif
475 560
476 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) { 561 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) {
477 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"), 562 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"),
478 PIPELINE_OK)); 563 PIPELINE_OK));
479 Play(); 564 Play();
480 ASSERT_TRUE(WaitUntilOnEnded()); 565 ASSERT_TRUE(WaitUntilOnEnded());
481 } 566 }
482 567
483 TEST_F(PipelineIntegrationTest, EncryptedPlayback) { 568 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) {
484 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816); 569 MockMediaSource source("bear-320x240-av_enc-av.webm", kWebM, 219816);
485 FakeEncryptedMedia encrypted_media; 570 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
486 StartPipelineWithEncryptedMedia(&source, &encrypted_media); 571 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
487 572
488 source.EndOfStream(); 573 source.EndOfStream();
574 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
575
576 Play();
577
578 ASSERT_TRUE(WaitUntilOnEnded());
579 source.Abort();
580 Stop();
581 }
582
583 TEST_F(PipelineIntegrationTest, EncryptedPlayback_ClearStart_WebM) {
584 MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm",
585 kWebM, kAppendWholeFile);
586 FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
587 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
588
589 source.EndOfStream();
590 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
591
592 Play();
593
594 ASSERT_TRUE(WaitUntilOnEnded());
595 source.Abort();
596 Stop();
597 }
598
599 TEST_F(PipelineIntegrationTest, EncryptedPlayback_NoEncryptedFrames_WebM) {
600 MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm",
601 kWebM, kAppendWholeFile);
602 FakeEncryptedMedia encrypted_media(new NoResponseApp());
603 StartPipelineWithEncryptedMedia(&source, &encrypted_media);
604
605 source.EndOfStream();
489 ASSERT_EQ(PIPELINE_OK, pipeline_status_); 606 ASSERT_EQ(PIPELINE_OK, pipeline_status_);
490 607
491 Play(); 608 Play();
492 609
493 ASSERT_TRUE(WaitUntilOnEnded()); 610 ASSERT_TRUE(WaitUntilOnEnded());
494 source.Abort(); 611 source.Abort();
495 Stop(); 612 Stop();
496 } 613 }
497 614
498 // TODO(acolwell): Fix flakiness http://crbug.com/117921 615 // TODO(acolwell): Fix flakiness http://crbug.com/117921
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 // Verify video decoder & renderer can handle aborted demuxer reads. 668 // Verify video decoder & renderer can handle aborted demuxer reads.
552 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { 669 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
553 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM, 670 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
554 32768, 671 32768,
555 base::TimeDelta::FromMilliseconds(200), 672 base::TimeDelta::FromMilliseconds(200),
556 base::TimeDelta::FromMilliseconds(1668), 673 base::TimeDelta::FromMilliseconds(1668),
557 0x1C896, 65536)); 674 0x1C896, 65536));
558 } 675 }
559 676
560 } // namespace media 677 } // namespace media
OLDNEW
« no previous file with comments | « media/crypto/aes_decryptor.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698