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

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

Issue 2808583002: RELAND: Media Remoting end to end integration tests. (Closed)
Patch Set: Rebased. Created 3 years, 8 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
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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <memory> 8 #include <memory>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
16 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/string_split.h" 17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
20 #include "build/build_config.h" 20 #include "build/build_config.h"
21 #include "media/base/cdm_callback_promise.h" 21 #include "media/base/cdm_callback_promise.h"
22 #include "media/base/cdm_context.h"
23 #include "media/base/cdm_key_information.h" 22 #include "media/base/cdm_key_information.h"
24 #include "media/base/content_decryption_module.h"
25 #include "media/base/decoder_buffer.h" 23 #include "media/base/decoder_buffer.h"
26 #include "media/base/media.h" 24 #include "media/base/media.h"
27 #include "media/base/media_switches.h" 25 #include "media/base/media_switches.h"
28 #include "media/base/media_tracks.h" 26 #include "media/base/media_tracks.h"
29 #include "media/base/test_data_util.h" 27 #include "media/base/test_data_util.h"
30 #include "media/base/timestamp_constants.h" 28 #include "media/base/timestamp_constants.h"
31 #include "media/cdm/aes_decryptor.h" 29 #include "media/cdm/aes_decryptor.h"
32 #include "media/cdm/json_web_key.h" 30 #include "media/cdm/json_web_key.h"
33 #include "media/filters/chunk_demuxer.h"
34 #include "media/media_features.h" 31 #include "media/media_features.h"
35 #include "media/renderers/renderer_impl.h" 32 #include "media/renderers/renderer_impl.h"
36 #include "media/test/pipeline_integration_test_base.h" 33 #include "media/test/pipeline_integration_test_base.h"
37 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gmock/include/gmock/gmock.h"
38 #include "url/gurl.h" 35 #include "url/gurl.h"
39 36
40 #if defined(MOJO_RENDERER) 37 #if defined(MOJO_RENDERER)
41 #include "media/mojo/clients/mojo_renderer.h" 38 #include "media/mojo/clients/mojo_renderer.h"
42 #include "media/mojo/interfaces/interface_factory.mojom.h" 39 #include "media/mojo/interfaces/interface_factory.mojom.h"
43 #include "media/mojo/interfaces/renderer.mojom.h" 40 #include "media/mojo/interfaces/renderer.mojom.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 #endif 84 #endif
88 85
89 using testing::_; 86 using testing::_;
90 using testing::AnyNumber; 87 using testing::AnyNumber;
91 using testing::AtLeast; 88 using testing::AtLeast;
92 using testing::AtMost; 89 using testing::AtMost;
93 using testing::SaveArg; 90 using testing::SaveArg;
94 91
95 namespace media { 92 namespace media {
96 93
97 const char kSourceId[] = "SourceId"; 94 namespace {
DaleCurtis 2017/04/20 18:24:51 We don't generally use anonymous namespace in the
xjz 2017/04/20 21:26:10 Done.
98 95
99 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\""; 96 const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\"";
100 const char kWebMVP9[] = "video/webm; codecs=\"vp9\""; 97 const char kWebMVP9[] = "video/webm; codecs=\"vp9\"";
101 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\""; 98 const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\"";
102 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\""; 99 const char kOpusAudioOnlyWebM[] = "video/webm; codecs=\"opus\"";
103 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\""; 100 const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\"";
104 #if BUILDFLAG(USE_PROPRIETARY_CODECS) 101 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
105 const char kADTS[] = "audio/aac"; 102 const char kADTS[] = "audio/aac";
106 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\""; 103 const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\"";
107 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\""; 104 const char kMP4VideoAVC3[] = "video/mp4; codecs=\"avc3.64001f\"";
108 const char kMP4VideoVP9[] = "video/mp4; codecs=\"vp09.00.10.08.01.05.01\""; 105 const char kMP4VideoVP9[] = "video/mp4; codecs=\"vp09.00.10.08.01.05.01\"";
109 const char kMP4VideoHEVC1[] = "video/mp4; codecs=\"hvc1.1.6.L93.B0\""; 106 const char kMP4VideoHEVC1[] = "video/mp4; codecs=\"hvc1.1.6.L93.B0\"";
110 const char kMP4VideoHEVC2[] = "video/mp4; codecs=\"hev1.1.6.L93.B0\""; 107 const char kMP4VideoHEVC2[] = "video/mp4; codecs=\"hev1.1.6.L93.B0\"";
111 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\""; 108 const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\"";
112 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\""; 109 const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
113 const char kMP3[] = "audio/mpeg"; 110 const char kMP3[] = "audio/mpeg";
114 const char kMP2AudioSBR[] = "video/mp2t; codecs=\"avc1.4D4041,mp4a.40.5\""; 111 const char kMP2AudioSBR[] = "video/mp2t; codecs=\"avc1.4D4041,mp4a.40.5\"";
115 #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) 112 #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
116 113
117 const size_t kAppendWholeFile = std::numeric_limits<size_t>::max();
118
119 // Constants for the Media Source config change tests. 114 // Constants for the Media Source config change tests.
120 const int kAppendTimeSec = 1; 115 const int kAppendTimeSec = 1;
121 const int kAppendTimeMs = kAppendTimeSec * 1000; 116 const int kAppendTimeMs = kAppendTimeSec * 1000;
122 const int k320WebMFileDurationMs = 2736; 117 const int k320WebMFileDurationMs = 2736;
123 const int k640WebMFileDurationMs = 2749; 118 const int k640WebMFileDurationMs = 2749;
124 const int kOpusEndTrimmingWebMFileDurationMs = 2741; 119 const int kOpusEndTrimmingWebMFileDurationMs = 2741;
125 const int kVP9WebMFileDurationMs = 2736; 120 const int kVP9WebMFileDurationMs = 2736;
126 const int kVP8AWebMFileDurationMs = 2734; 121 const int kVP8AWebMFileDurationMs = 2734;
127 122
128 #if !defined(MOJO_RENDERER) 123 #if !defined(MOJO_RENDERER)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 exploded_time.second = 56; 175 exploded_time.second = 56;
181 exploded_time.millisecond = 789; 176 exploded_time.millisecond = 789;
182 base::Time timeline_offset; 177 base::Time timeline_offset;
183 EXPECT_TRUE(base::Time::FromUTCExploded(exploded_time, &timeline_offset)); 178 EXPECT_TRUE(base::Time::FromUTCExploded(exploded_time, &timeline_offset));
184 179
185 timeline_offset += base::TimeDelta::FromMicroseconds(123); 180 timeline_offset += base::TimeDelta::FromMicroseconds(123);
186 181
187 return timeline_offset; 182 return timeline_offset;
188 } 183 }
189 184
190 // Note: Tests using this class only exercise the DecryptingDemuxerStream path.
191 // They do not exercise the Decrypting{Audio|Video}Decoder path.
192 class FakeEncryptedMedia {
193 public:
194 // Defines the behavior of the "app" that responds to EME events.
195 class AppBase {
196 public:
197 virtual ~AppBase() {}
198
199 virtual void OnSessionMessage(
200 const std::string& session_id,
201 ContentDecryptionModule::MessageType message_type,
202 const std::vector<uint8_t>& message,
203 AesDecryptor* decryptor) = 0;
204
205 virtual void OnSessionClosed(const std::string& session_id) = 0;
206
207 virtual void OnSessionKeysChange(const std::string& session_id,
208 bool has_additional_usable_key,
209 CdmKeysInfo keys_info) = 0;
210
211 virtual void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
212 const std::vector<uint8_t>& init_data,
213 AesDecryptor* decryptor) = 0;
214 };
215
216 FakeEncryptedMedia(AppBase* app)
217 : decryptor_(new AesDecryptor(
218 GURL::EmptyGURL(),
219 base::Bind(&FakeEncryptedMedia::OnSessionMessage,
220 base::Unretained(this)),
221 base::Bind(&FakeEncryptedMedia::OnSessionClosed,
222 base::Unretained(this)),
223 base::Bind(&FakeEncryptedMedia::OnSessionKeysChange,
224 base::Unretained(this)))),
225 cdm_context_(decryptor_.get()),
226 app_(app) {}
227
228 CdmContext* GetCdmContext() { return &cdm_context_; }
229
230 // Callbacks for firing session events. Delegate to |app_|.
231 void OnSessionMessage(const std::string& session_id,
232 ContentDecryptionModule::MessageType message_type,
233 const std::vector<uint8_t>& message) {
234 app_->OnSessionMessage(session_id, message_type, message, decryptor_.get());
235 }
236
237 void OnSessionClosed(const std::string& session_id) {
238 app_->OnSessionClosed(session_id);
239 }
240
241 void OnSessionKeysChange(const std::string& session_id,
242 bool has_additional_usable_key,
243 CdmKeysInfo keys_info) {
244 app_->OnSessionKeysChange(session_id, has_additional_usable_key,
245 std::move(keys_info));
246 }
247
248 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
249 const std::vector<uint8_t>& init_data) {
250 app_->OnEncryptedMediaInitData(init_data_type, init_data, decryptor_.get());
251 }
252
253 private:
254 class TestCdmContext : public CdmContext {
255 public:
256 TestCdmContext(Decryptor* decryptor) : decryptor_(decryptor) {}
257
258 Decryptor* GetDecryptor() final { return decryptor_; }
259 int GetCdmId() const final { return kInvalidCdmId; }
260
261 private:
262 Decryptor* decryptor_;
263 };
264
265 scoped_refptr<AesDecryptor> decryptor_;
266 TestCdmContext cdm_context_;
267 std::unique_ptr<AppBase> app_;
268 };
269
270 enum PromiseResult { RESOLVED, REJECTED }; 185 enum PromiseResult { RESOLVED, REJECTED };
271 186
272 // Provides the test key in response to the encrypted event. 187 // Provides the test key in response to the encrypted event.
273 class KeyProvidingApp : public FakeEncryptedMedia::AppBase { 188 class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
274 public: 189 public:
275 KeyProvidingApp() {} 190 KeyProvidingApp() {}
276 191
277 void OnResolveWithSession(PromiseResult expected, 192 void OnResolveWithSession(PromiseResult expected,
278 const std::string& session_id) { 193 const std::string& session_id) {
279 EXPECT_EQ(expected, RESOLVED); 194 EXPECT_EQ(expected, RESOLVED);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 CdmKeysInfo keys_info) override { 350 CdmKeysInfo keys_info) override {
436 EXPECT_FALSE(session_id.empty()); 351 EXPECT_FALSE(session_id.empty());
437 EXPECT_EQ(has_additional_usable_key, true); 352 EXPECT_EQ(has_additional_usable_key, true);
438 } 353 }
439 354
440 void OnEncryptedMediaInitData(EmeInitDataType init_data_type, 355 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
441 const std::vector<uint8_t>& init_data, 356 const std::vector<uint8_t>& init_data,
442 AesDecryptor* decryptor) override {} 357 AesDecryptor* decryptor) override {}
443 }; 358 };
444 359
445 // Helper class that emulates calls made on the ChunkDemuxer by the
446 // Media Source API.
447 class MockMediaSource {
448 public:
449 MockMediaSource(const std::string& filename,
450 const std::string& mimetype,
451 size_t initial_append_size)
452 : current_position_(0),
453 initial_append_size_(initial_append_size),
454 mimetype_(mimetype),
455 chunk_demuxer_(new ChunkDemuxer(
456 base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
457 base::Bind(&MockMediaSource::OnEncryptedMediaInitData,
458 base::Unretained(this)),
459 &media_log_)),
460 owned_chunk_demuxer_(chunk_demuxer_) {
461 file_data_ = ReadTestDataFile(filename);
462
463 if (initial_append_size_ == kAppendWholeFile)
464 initial_append_size_ = file_data_->data_size();
465
466 DCHECK_GT(initial_append_size_, 0u);
467 DCHECK_LE(initial_append_size_, file_data_->data_size());
468 }
469
470 virtual ~MockMediaSource() {}
471
472 std::unique_ptr<Demuxer> GetDemuxer() {
473 return std::move(owned_chunk_demuxer_);
474 }
475
476 void set_encrypted_media_init_data_cb(
477 const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) {
478 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
479 }
480
481 void set_demuxer_failure_cb(const PipelineStatusCB& demuxer_failure_cb) {
482 demuxer_failure_cb_ = demuxer_failure_cb;
483 }
484
485 void Seek(base::TimeDelta seek_time,
486 size_t new_position,
487 size_t seek_append_size) {
488 chunk_demuxer_->StartWaitingForSeek(seek_time);
489
490 chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(),
491 kInfiniteDuration,
492 &last_timestamp_offset_);
493
494 DCHECK_LT(new_position, file_data_->data_size());
495 current_position_ = new_position;
496
497 AppendData(seek_append_size);
498 }
499
500 void Seek(base::TimeDelta seek_time) {
501 chunk_demuxer_->StartWaitingForSeek(seek_time);
502 }
503
504 void AppendData(size_t size) {
505 DCHECK(chunk_demuxer_);
506 DCHECK_LT(current_position_, file_data_->data_size());
507 DCHECK_LE(current_position_ + size, file_data_->data_size());
508
509 ASSERT_TRUE(chunk_demuxer_->AppendData(
510 kSourceId, file_data_->data() + current_position_, size,
511 base::TimeDelta(), kInfiniteDuration, &last_timestamp_offset_));
512 current_position_ += size;
513 }
514
515 bool AppendAtTime(base::TimeDelta timestamp_offset,
516 const uint8_t* pData,
517 int size) {
518 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
519 bool success =
520 chunk_demuxer_->AppendData(kSourceId, pData, size, base::TimeDelta(),
521 kInfiniteDuration, &timestamp_offset);
522 last_timestamp_offset_ = timestamp_offset;
523 return success;
524 }
525
526 void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset,
527 base::TimeDelta append_window_start,
528 base::TimeDelta append_window_end,
529 const uint8_t* pData,
530 int size) {
531 CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
532 ASSERT_TRUE(
533 chunk_demuxer_->AppendData(kSourceId, pData, size, append_window_start,
534 append_window_end, &timestamp_offset));
535 last_timestamp_offset_ = timestamp_offset;
536 }
537
538 void SetMemoryLimits(size_t limit_bytes) {
539 chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, limit_bytes);
540 chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, limit_bytes);
541 }
542
543 void EvictCodedFrames(base::TimeDelta currentMediaTime, size_t newDataSize) {
544 chunk_demuxer_->EvictCodedFrames(kSourceId, currentMediaTime, newDataSize);
545 }
546
547 void RemoveRange(base::TimeDelta start, base::TimeDelta end) {
548 chunk_demuxer_->Remove(kSourceId, start, end);
549 }
550
551 void EndOfStream() { chunk_demuxer_->MarkEndOfStream(PIPELINE_OK); }
552
553 void Shutdown() {
554 if (!chunk_demuxer_)
555 return;
556 chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(),
557 kInfiniteDuration,
558 &last_timestamp_offset_);
559 chunk_demuxer_->Shutdown();
560 chunk_demuxer_ = NULL;
561 }
562
563 void DemuxerOpened() {
564 base::ThreadTaskRunnerHandle::Get()->PostTask(
565 FROM_HERE, base::Bind(&MockMediaSource::DemuxerOpenedTask,
566 base::Unretained(this)));
567 }
568
569 void DemuxerOpenedTask() {
570 ChunkDemuxer::Status status = AddId();
571 if (status != ChunkDemuxer::kOk) {
572 CHECK(!demuxer_failure_cb_.is_null());
573 demuxer_failure_cb_.Run(DEMUXER_ERROR_COULD_NOT_OPEN);
574 return;
575 }
576 chunk_demuxer_->SetTracksWatcher(
577 kSourceId, base::Bind(&MockMediaSource::InitSegmentReceived,
578 base::Unretained(this)));
579
580 AppendData(initial_append_size_);
581 }
582
583 ChunkDemuxer::Status AddId() {
584 // This code assumes that |mimetype_| is one of the following forms.
585 // 1. audio/mpeg
586 // 2. video/webm;codec="vorbis,vp8".
587 size_t semicolon = mimetype_.find(";");
588 std::string type = mimetype_;
589 std::string codecs_param = "";
590 if (semicolon != std::string::npos) {
591 type = mimetype_.substr(0, semicolon);
592 size_t codecs_param_start = mimetype_.find("codecs=\"", semicolon);
593
594 CHECK_NE(codecs_param_start, std::string::npos);
595
596 codecs_param_start += 8; // Skip over the codecs=".
597
598 size_t codecs_param_end = mimetype_.find("\"", codecs_param_start);
599
600 CHECK_NE(codecs_param_end, std::string::npos);
601
602 codecs_param = mimetype_.substr(codecs_param_start,
603 codecs_param_end - codecs_param_start);
604 }
605
606 return chunk_demuxer_->AddId(kSourceId, type, codecs_param);
607 }
608
609 void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
610 const std::vector<uint8_t>& init_data) {
611 DCHECK(!init_data.empty());
612 CHECK(!encrypted_media_init_data_cb_.is_null());
613 encrypted_media_init_data_cb_.Run(init_data_type, init_data);
614 }
615
616 base::TimeDelta last_timestamp_offset() const {
617 return last_timestamp_offset_;
618 }
619
620 void InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
621 CHECK(tracks.get());
622 EXPECT_GT(tracks->tracks().size(), 0u);
623 CHECK(chunk_demuxer_);
624 // Verify that track ids are unique.
625 std::set<MediaTrack::Id> track_ids;
626 for (const auto& track : tracks->tracks()) {
627 EXPECT_EQ(track_ids.end(), track_ids.find(track->id()));
628 track_ids.insert(track->id());
629 }
630 InitSegmentReceivedMock(tracks);
631 }
632
633 MOCK_METHOD1(InitSegmentReceivedMock, void(std::unique_ptr<MediaTracks>&));
634
635 private:
636 MediaLog media_log_;
637 scoped_refptr<DecoderBuffer> file_data_;
638 size_t current_position_;
639 size_t initial_append_size_;
640 std::string mimetype_;
641 ChunkDemuxer* chunk_demuxer_;
642 std::unique_ptr<Demuxer> owned_chunk_demuxer_;
643 PipelineStatusCB demuxer_failure_cb_;
644 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
645 base::TimeDelta last_timestamp_offset_;
646 };
647
648 // A rough simulation of GpuVideoDecoder that fails every Decode() request. This 360 // A rough simulation of GpuVideoDecoder that fails every Decode() request. This
649 // is used to test post-Initialize() fallback paths. 361 // is used to test post-Initialize() fallback paths.
650 class FailingVideoDecoder : public VideoDecoder { 362 class FailingVideoDecoder : public VideoDecoder {
651 public: 363 public:
652 std::string GetDisplayName() const override { return "FailingVideoDecoder"; } 364 std::string GetDisplayName() const override { return "FailingVideoDecoder"; }
653 void Initialize(const VideoDecoderConfig& config, 365 void Initialize(const VideoDecoderConfig& config,
654 bool low_delay, 366 bool low_delay,
655 CdmContext* cdm_context, 367 CdmContext* cdm_context,
656 const InitCB& init_cb, 368 const InitCB& init_cb,
657 const OutputCB& output_cb) override { 369 const OutputCB& output_cb) override {
658 init_cb.Run(true); 370 init_cb.Run(true);
659 } 371 }
660 void Decode(const scoped_refptr<DecoderBuffer>& buffer, 372 void Decode(const scoped_refptr<DecoderBuffer>& buffer,
661 const DecodeCB& decode_cb) override { 373 const DecodeCB& decode_cb) override {
662 base::ThreadTaskRunnerHandle::Get()->PostTask( 374 base::ThreadTaskRunnerHandle::Get()->PostTask(
663 FROM_HERE, base::Bind(decode_cb, DecodeStatus::DECODE_ERROR)); 375 FROM_HERE, base::Bind(decode_cb, DecodeStatus::DECODE_ERROR));
664 } 376 }
665 void Reset(const base::Closure& closure) override { closure.Run(); } 377 void Reset(const base::Closure& closure) override { closure.Run(); }
666 bool NeedsBitstreamConversion() const override { return true; } 378 bool NeedsBitstreamConversion() const override { return true; }
667 }; 379 };
668 380
381 } // namespace
382
669 // TODO(xhwang): These tests have been disabled for some time as apptests and no 383 // TODO(xhwang): These tests have been disabled for some time as apptests and no
670 // longer pass. They need to be reconstituted as shell tests. 384 // longer pass. They need to be reconstituted as shell tests.
671 // Currently there are compile issues which must be resolved, 385 // Currently there are compile issues which must be resolved,
672 // preferably by eliminating multiple inheritance here which is 386 // preferably by eliminating multiple inheritance here which is
673 // banned by Google C++ style. 387 // banned by Google C++ style.
674 #if defined(MOJO_RENDERER) && defined(ENABLE_MOJO_PIPELINE_INTEGRATION_TEST) 388 #if defined(MOJO_RENDERER) && defined(ENABLE_MOJO_PIPELINE_INTEGRATION_TEST)
675 class PipelineIntegrationTestHost : public service_manager::test::ServiceTest, 389 class PipelineIntegrationTest : public service_manager::test::ServiceTest,
676 public PipelineIntegrationTestBase { 390 public PipelineIntegrationTestBase {
677 public: 391 public:
678 PipelineIntegrationTestHost() 392 PipelineIntegrationTest()
679 : service_manager::test::ServiceTest( 393 : service_manager::test::ServiceTest(
680 "media_pipeline_integration_shelltests") {} 394 "media_pipeline_integration_shelltests") {}
681 395
682 void SetUp() override { 396 void SetUp() override {
683 ServiceTest::SetUp(); 397 ServiceTest::SetUp();
684 InitializeMediaLibrary(); 398 InitializeMediaLibrary();
685 } 399 }
686 400
687 protected: 401 protected:
688 std::unique_ptr<Renderer> CreateRenderer( 402 std::unique_ptr<Renderer> CreateRenderer(
689 CreateVideoDecodersCB prepend_video_decoders_cb, 403 CreateVideoDecodersCB prepend_video_decoders_cb,
690 CreateAudioDecodersCB prepend_audio_decoders_cb) override { 404 CreateAudioDecodersCB prepend_audio_decoders_cb) override {
691 connector()->BindInterface("media", &media_interface_factory_); 405 connector()->BindInterface("media", &media_interface_factory_);
692 406
693 mojom::RendererPtr mojo_renderer; 407 mojom::RendererPtr mojo_renderer;
694 media_interface_factory_->CreateRenderer(std::string(), 408 media_interface_factory_->CreateRenderer(std::string(),
695 mojo::MakeRequest(&mojo_renderer)); 409 mojo::MakeRequest(&mojo_renderer));
696 410
697 return base::MakeUnique<MojoRenderer>(message_loop_.task_runner(), 411 return base::MakeUnique<MojoRenderer>(message_loop_.task_runner(),
698 std::move(mojo_renderer)); 412 std::move(mojo_renderer));
699 } 413 }
700 414
701 private: 415 private:
702 mojom::InterfaceFactoryPtr media_interface_factory_; 416 mojom::InterfaceFactoryPtr media_interface_factory_;
703 }; 417 };
704 #else 418 #else
705 class PipelineIntegrationTestHost : public testing::Test, 419 class PipelineIntegrationTest : public testing::Test,
706 public PipelineIntegrationTestBase {}; 420 public PipelineIntegrationTestBase {};
707 #endif // defined(MOJO_RENDERER) 421 #endif // defined(MOJO_RENDERER)
708 422
709 class PipelineIntegrationTest : public PipelineIntegrationTestHost {
710 public:
711 PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source) {
712 return StartPipelineWithMediaSource(source, kNormal, nullptr);
713 }
714
715 PipelineStatus StartPipelineWithEncryptedMedia(
716 MockMediaSource* source,
717 FakeEncryptedMedia* encrypted_media) {
718 return StartPipelineWithMediaSource(source, kNormal, encrypted_media);
719 }
720
721 PipelineStatus StartPipelineWithMediaSource(
722 MockMediaSource* source,
723 uint8_t test_type,
724 FakeEncryptedMedia* encrypted_media) {
725 hashing_enabled_ = test_type & kHashed;
726 clockless_playback_ = test_type & kClockless;
727
728 if (!(test_type & kExpectDemuxerFailure))
729 EXPECT_CALL(*source, InitSegmentReceivedMock(_)).Times(AtLeast(1));
730
731 EXPECT_CALL(*this, OnMetadata(_))
732 .Times(AtMost(1))
733 .WillRepeatedly(SaveArg<0>(&metadata_));
734 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH))
735 .Times(AnyNumber());
736 EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING))
737 .Times(AnyNumber());
738 EXPECT_CALL(*this, OnDurationChange()).Times(AnyNumber());
739 EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(AtMost(1));
740 EXPECT_CALL(*this, OnVideoOpacityChange(_)).Times(AtMost(1));
741
742 source->set_demuxer_failure_cb(base::Bind(
743 &PipelineIntegrationTest::OnStatusCallback, base::Unretained(this)));
744 demuxer_ = source->GetDemuxer();
745
746 if (encrypted_media) {
747 EXPECT_CALL(*this, DecryptorAttached(true));
748
749 // Encrypted content used but keys provided in advance, so this is
750 // never called.
751 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
752 pipeline_->SetCdm(encrypted_media->GetCdmContext(),
753 base::Bind(&PipelineIntegrationTest::DecryptorAttached,
754 base::Unretained(this)));
755 } else {
756 // Encrypted content not used, so this is never called.
757 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
758 }
759
760 pipeline_->Start(demuxer_.get(), CreateRenderer(), this,
761 base::Bind(&PipelineIntegrationTest::OnStatusCallback,
762 base::Unretained(this)));
763
764 if (encrypted_media) {
765 source->set_encrypted_media_init_data_cb(
766 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData,
767 base::Unretained(encrypted_media)));
768 }
769 base::RunLoop().Run();
770 return pipeline_status_;
771 }
772
773 // Verifies that seeking works properly for ChunkDemuxer when the
774 // seek happens while there is a pending read on the ChunkDemuxer
775 // and no data is available.
776 bool TestSeekDuringRead(const std::string& filename,
777 const std::string& mimetype,
778 int initial_append_size,
779 base::TimeDelta start_seek_time,
780 base::TimeDelta seek_time,
781 int seek_file_position,
782 int seek_append_size) {
783 MockMediaSource source(filename, mimetype, initial_append_size);
784
785 if (StartPipelineWithMediaSource(&source) != PIPELINE_OK)
786 return false;
787
788 Play();
789 if (!WaitUntilCurrentTimeIsAfter(start_seek_time))
790 return false;
791
792 source.Seek(seek_time, seek_file_position, seek_append_size);
793 if (!Seek(seek_time))
794 return false;
795
796 source.EndOfStream();
797
798 source.Shutdown();
799 Stop();
800 return true;
801 }
802 };
803
804 struct PlaybackTestData { 423 struct PlaybackTestData {
805 const std::string filename; 424 const std::string filename;
806 const uint32_t start_time_ms; 425 const uint32_t start_time_ms;
807 const uint32_t duration_ms; 426 const uint32_t duration_ms;
808 }; 427 };
809 428
810 struct MSEPlaybackTestData { 429 struct MSEPlaybackTestData {
811 const std::string filename; 430 const std::string filename;
812 const std::string mimetype; 431 const std::string mimetype;
813 const size_t append_bytes; 432 const size_t append_bytes;
(...skipping 1858 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 2291
2673 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) { 2292 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) {
2674 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm")); 2293 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm"));
2675 Play(); 2294 Play();
2676 ASSERT_TRUE(WaitUntilOnEnded()); 2295 ASSERT_TRUE(WaitUntilOnEnded());
2677 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000), 2296 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000),
2678 demuxer_->GetStartTime()); 2297 demuxer_->GetStartTime());
2679 } 2298 }
2680 2299
2681 } // namespace media 2300 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698