Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/memory/scoped_ptr.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| 11 #include "media/base/decoder_buffer.h" | 11 #include "media/base/decoder_buffer.h" |
| 12 #include "media/base/test_data_util.h" | 12 #include "media/base/test_data_util.h" |
| 13 #include "media/crypto/aes_decryptor.h" | 13 #include "media/crypto/aes_decryptor.h" |
| 14 | 14 |
| 15 using testing::AtMost; | 15 using testing::AtMost; |
| 16 | 16 |
| 17 namespace media { | 17 namespace media { |
| 18 | 18 |
| 19 static const char kSourceId[] = "SourceId"; | 19 static const char kSourceId[] = "SourceId"; |
| 20 static const char kClearKeySystem[] = "org.w3.clearkey"; | 20 static const char kClearKeySystem[] = "org.w3.clearkey"; |
| 21 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 }; | 21 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 }; |
| 22 | 22 |
| 23 static const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\""; | 23 static const char kWebM[] = "video/webm; codecs=\"vp8,vorbis\""; |
| 24 static const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\""; | 24 static const char kAudioOnlyWebM[] = "video/webm; codecs=\"vorbis\""; |
| 25 static const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\""; | 25 static const char kVideoOnlyWebM[] = "video/webm; codecs=\"vp8\""; |
| 26 static const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\""; | 26 static const char kMP4[] = "video/mp4; codecs=\"avc1.4D4041,mp4a.40.2\""; |
| 27 static const char kMP4Video[] = "video/mp4; codecs=\"avc1.4D4041\""; | |
| 28 static const char kMP4Audio[] = "audio/mp4; codecs=\"mp4a.40.2\""; | |
| 27 | 29 |
| 28 // Key used to encrypt test files. | 30 // Key used to encrypt test files. |
| 29 static const uint8 kSecretKey[] = { | 31 static const uint8 kSecretKey[] = { |
| 30 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, | 32 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, |
| 31 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c | 33 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c |
| 32 }; | 34 }; |
| 33 | 35 |
| 34 // The key ID for all encrypted files. | 36 // The key ID for all encrypted files. |
| 35 static const uint8 kKeyId[] = { | 37 static const uint8 kKeyId[] = { |
| 36 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, | 38 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
| 37 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35 | 39 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35 |
| 38 }; | 40 }; |
| 39 | 41 |
| 40 static const int kAppendWholeFile = -1; | 42 static const int kAppendWholeFile = -1; |
| 41 | 43 |
| 42 // Constants for the Media Source config change tests. | 44 // Constants for the Media Source config change tests. |
| 43 static const int kAppendTimeSec = 1; | 45 static const int kAppendTimeSec = 1; |
| 44 static const int kAppendTimeMs = kAppendTimeSec * 1000; | 46 static const int kAppendTimeMs = kAppendTimeSec * 1000; |
| 45 static const int k320WebMFileDurationMs = 2737; | 47 static const int k320WebMFileDurationMs = 2737; |
| 46 static const int k640WebMFileDurationMs = 2763; | 48 static const int k640WebMFileDurationMs = 2763; |
| 49 static const int k640IsoFileDurationMs = 2737; | |
| 50 static const int k640IsoCencFileDurationMs = 2736; | |
| 47 static const int k1280IsoFileDurationMs = 2736; | 51 static const int k1280IsoFileDurationMs = 2736; |
| 48 | 52 |
| 49 // Note: Tests using this class only exercise the DecryptingDemuxerStream path. | 53 // Note: Tests using this class only exercise the DecryptingDemuxerStream path. |
| 50 // They do not exercise the Decrypting{Audio|Video}Decoder path. | 54 // They do not exercise the Decrypting{Audio|Video}Decoder path. |
| 51 class FakeEncryptedMedia { | 55 class FakeEncryptedMedia { |
| 52 public: | 56 public: |
| 53 // Defines the behavior of the "app" that responds to EME events. | 57 // Defines the behavior of the "app" that responds to EME events. |
| 54 class AppBase { | 58 class AppBase { |
| 55 public: | 59 public: |
| 56 virtual ~AppBase() {} | 60 virtual ~AppBase() {} |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 // In this case, we need to call GenerateKeyRequest() to initialize a | 163 // In this case, we need to call GenerateKeyRequest() to initialize a |
| 160 // session (which will call KeyMessage). | 164 // session (which will call KeyMessage). |
| 161 if (current_key_system_.empty()) { | 165 if (current_key_system_.empty()) { |
| 162 EXPECT_TRUE(current_session_id_.empty()); | 166 EXPECT_TRUE(current_session_id_.empty()); |
| 163 EXPECT_TRUE(decryptor->GenerateKeyRequest( | 167 EXPECT_TRUE(decryptor->GenerateKeyRequest( |
| 164 kClearKeySystem, type, kInitData, arraysize(kInitData))); | 168 kClearKeySystem, type, kInitData, arraysize(kInitData))); |
| 165 } | 169 } |
| 166 | 170 |
| 167 EXPECT_FALSE(current_key_system_.empty()); | 171 EXPECT_FALSE(current_key_system_.empty()); |
| 168 EXPECT_FALSE(current_session_id_.empty()); | 172 EXPECT_FALSE(current_session_id_.empty()); |
| 173 | |
| 174 // Clear Key really needs the key ID in |init_data|. For WebM, they are the | |
| 175 // same, but this is not the case for ISO CENC. Therefore, provide the | |
| 176 // correct key ID. | |
| 177 const uint8* key_id = init_data.get(); | |
| 178 int key_id_length = init_data_length; | |
| 179 if (type == "video/mp4") { | |
|
xhwang
2013/01/11 18:04:08
How about audio, is audio not encrypted? How about
ddorwin
2013/01/11 18:30:39
Done.
| |
| 180 key_id = kKeyId; | |
| 181 key_id_length = arraysize(kKeyId); | |
| 182 } | |
| 183 | |
| 169 decryptor->AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey), | 184 decryptor->AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey), |
| 170 init_data.get(), init_data_length, current_session_id_); | 185 key_id, key_id_length, current_session_id_); |
| 171 } | 186 } |
| 172 | 187 |
| 173 std::string current_key_system_; | 188 std::string current_key_system_; |
| 174 std::string current_session_id_; | 189 std::string current_session_id_; |
| 175 }; | 190 }; |
| 176 | 191 |
| 177 // Ignores needkey and does not perform a license request | 192 // Ignores needkey and does not perform a license request |
| 178 class NoResponseApp : public FakeEncryptedMedia::AppBase { | 193 class NoResponseApp : public FakeEncryptedMedia::AppBase { |
| 179 public: | 194 public: |
| 180 virtual void KeyAdded(const std::string& key_system, | 195 virtual void KeyAdded(const std::string& key_system, |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); | 564 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); |
| 550 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs, | 565 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs, |
| 551 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); | 566 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); |
| 552 | 567 |
| 553 Play(); | 568 Play(); |
| 554 | 569 |
| 555 EXPECT_TRUE(WaitUntilOnEnded()); | 570 EXPECT_TRUE(WaitUntilOnEnded()); |
| 556 source.Abort(); | 571 source.Abort(); |
| 557 Stop(); | 572 Stop(); |
| 558 } | 573 } |
| 574 | |
| 575 TEST_F(PipelineIntegrationTest, | |
| 576 MediaSource_ConfigChange_Encrypted_MP4_CENC_VideoOnly) { | |
| 577 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", | |
| 578 kMP4Video, kAppendWholeFile); | |
| 579 FakeEncryptedMedia encrypted_media(new KeyProvidingApp()); | |
| 580 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 581 | |
| 582 scoped_refptr<DecoderBuffer> second_file = | |
| 583 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4"); | |
| 584 | |
| 585 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), | |
| 586 second_file->GetData(), second_file->GetDataSize()); | |
| 587 | |
| 588 source.EndOfStream(); | |
| 589 | |
| 590 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); | |
| 591 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); | |
| 592 EXPECT_EQ(kAppendTimeMs + k1280IsoFileDurationMs, | |
| 593 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); | |
| 594 | |
| 595 Play(); | |
| 596 | |
| 597 EXPECT_TRUE(WaitUntilOnEnded()); | |
| 598 source.Abort(); | |
| 599 Stop(); | |
| 600 } | |
| 601 | |
| 602 // Config changes from encrypted to clear are not currently supported. | |
| 603 // TODO(ddorwin): Figure out why this CHECKs in AppendAtTime(). | |
| 604 TEST_F(PipelineIntegrationTest, | |
| 605 DISABLED_MediaSource_ConfigChange_ClearThenEncrypted_MP4_CENC) { | |
|
xhwang
2013/01/11 18:04:08
comment says this test is "enctyped to clear" but
ddorwin
2013/01/11 18:30:39
Done.
| |
| 606 MockMediaSource source("bear-640x360-av_frag.mp4", kMP4Video, | |
| 607 kAppendWholeFile); | |
| 608 FakeEncryptedMedia encrypted_media(new KeyProvidingApp()); | |
| 609 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 610 | |
| 611 scoped_refptr<DecoderBuffer> second_file = | |
| 612 ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4"); | |
| 613 | |
| 614 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), | |
| 615 second_file->GetData(), second_file->GetDataSize()); | |
| 616 | |
| 617 source.EndOfStream(); | |
| 618 | |
| 619 message_loop_.Run(); | |
| 620 EXPECT_EQ(PIPELINE_ERROR_DECODE, pipeline_status_); | |
| 621 | |
| 622 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); | |
| 623 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); | |
| 624 // The second video was not added, so its time has not been added. | |
| 625 EXPECT_EQ(k640IsoFileDurationMs, | |
| 626 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); | |
| 627 | |
| 628 Play(); | |
| 629 | |
| 630 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); | |
| 631 source.Abort(); | |
| 632 } | |
| 633 | |
| 634 // Config changes from clear to encrypted are not currently supported. | |
| 635 TEST_F(PipelineIntegrationTest, | |
| 636 MediaSource_ConfigChange_EncryptedThenClear_MP4_CENC) { | |
|
xhwang
2013/01/11 18:04:08
ditto for comment and test name
ddorwin
2013/01/11 18:30:39
Done.
| |
| 637 MockMediaSource source("bear-640x360-v_frag-cenc.mp4", | |
| 638 kMP4Video, kAppendWholeFile); | |
| 639 FakeEncryptedMedia encrypted_media(new KeyProvidingApp()); | |
| 640 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 641 | |
| 642 scoped_refptr<DecoderBuffer> second_file = | |
| 643 ReadTestDataFile("bear-1280x720-av_frag.mp4"); | |
| 644 | |
| 645 source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec), | |
| 646 second_file->GetData(), second_file->GetDataSize()); | |
| 647 | |
| 648 source.EndOfStream(); | |
| 649 | |
| 650 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); | |
| 651 EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds()); | |
| 652 // The second video was not added, so its time has not been added. | |
| 653 EXPECT_EQ(k640IsoCencFileDurationMs, | |
| 654 pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds()); | |
| 655 | |
| 656 Play(); | |
| 657 | |
| 658 EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); | |
| 659 source.Abort(); | |
| 660 } | |
| 559 #endif | 661 #endif |
| 560 | 662 |
| 561 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) { | 663 TEST_F(PipelineIntegrationTest, BasicPlayback_16x9AspectRatio) { |
| 562 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"), | 664 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240-16x9-aspect.webm"), |
| 563 PIPELINE_OK)); | 665 PIPELINE_OK)); |
| 564 Play(); | 666 Play(); |
| 565 ASSERT_TRUE(WaitUntilOnEnded()); | 667 ASSERT_TRUE(WaitUntilOnEnded()); |
| 566 } | 668 } |
| 567 | 669 |
| 568 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) { | 670 TEST_F(PipelineIntegrationTest, EncryptedPlayback_WebM) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 source.EndOfStream(); | 707 source.EndOfStream(); |
| 606 ASSERT_EQ(PIPELINE_OK, pipeline_status_); | 708 ASSERT_EQ(PIPELINE_OK, pipeline_status_); |
| 607 | 709 |
| 608 Play(); | 710 Play(); |
| 609 | 711 |
| 610 ASSERT_TRUE(WaitUntilOnEnded()); | 712 ASSERT_TRUE(WaitUntilOnEnded()); |
| 611 source.Abort(); | 713 source.Abort(); |
| 612 Stop(); | 714 Stop(); |
| 613 } | 715 } |
| 614 | 716 |
| 717 #if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) | |
| 718 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_VideoOnly) { | |
|
xhwang
2013/01/11 18:04:08
why this test needs proprietary codecs but the abo
ddorwin
2013/01/11 18:30:39
The ifdef is at 550. :)
xhwang
2013/01/11 18:51:55
Ah, okey then.
| |
| 719 MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", | |
| 720 kMP4Video, kAppendWholeFile); | |
| 721 FakeEncryptedMedia encrypted_media(new KeyProvidingApp()); | |
| 722 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 723 | |
| 724 source.EndOfStream(); | |
| 725 ASSERT_EQ(PIPELINE_OK, pipeline_status_); | |
| 726 | |
| 727 Play(); | |
| 728 | |
| 729 ASSERT_TRUE(WaitUntilOnEnded()); | |
| 730 source.Abort(); | |
| 731 Stop(); | |
| 732 } | |
| 733 | |
| 734 TEST_F(PipelineIntegrationTest, EncryptedPlayback_MP4_CENC_AudioOnly) { | |
| 735 MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", | |
| 736 kMP4Audio, kAppendWholeFile); | |
| 737 FakeEncryptedMedia encrypted_media(new KeyProvidingApp()); | |
| 738 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 739 | |
| 740 source.EndOfStream(); | |
| 741 ASSERT_EQ(PIPELINE_OK, pipeline_status_); | |
| 742 | |
| 743 Play(); | |
| 744 | |
| 745 ASSERT_TRUE(WaitUntilOnEnded()); | |
| 746 source.Abort(); | |
| 747 Stop(); | |
| 748 } | |
| 749 | |
| 750 TEST_F(PipelineIntegrationTest, | |
| 751 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly) { | |
| 752 MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4", | |
| 753 kMP4Video, kAppendWholeFile); | |
| 754 FakeEncryptedMedia encrypted_media(new NoResponseApp()); | |
| 755 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 756 | |
| 757 source.EndOfStream(); | |
| 758 ASSERT_EQ(PIPELINE_OK, pipeline_status_); | |
| 759 | |
| 760 Play(); | |
| 761 | |
| 762 ASSERT_TRUE(WaitUntilOnEnded()); | |
| 763 source.Abort(); | |
| 764 Stop(); | |
| 765 } | |
| 766 | |
| 767 TEST_F(PipelineIntegrationTest, | |
| 768 EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly) { | |
| 769 MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4", | |
| 770 kMP4Audio, kAppendWholeFile); | |
| 771 FakeEncryptedMedia encrypted_media(new NoResponseApp()); | |
| 772 StartPipelineWithEncryptedMedia(&source, &encrypted_media); | |
| 773 | |
| 774 source.EndOfStream(); | |
| 775 ASSERT_EQ(PIPELINE_OK, pipeline_status_); | |
| 776 | |
| 777 Play(); | |
| 778 | |
| 779 ASSERT_TRUE(WaitUntilOnEnded()); | |
| 780 source.Abort(); | |
| 781 Stop(); | |
| 782 } | |
| 783 #endif | |
| 784 | |
| 615 // TODO(acolwell): Fix flakiness http://crbug.com/117921 | 785 // TODO(acolwell): Fix flakiness http://crbug.com/117921 |
| 616 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) { | 786 TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePaused) { |
| 617 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK)); | 787 ASSERT_TRUE(Start(GetTestDataFilePath("bear-320x240.webm"), PIPELINE_OK)); |
| 618 | 788 |
| 619 base::TimeDelta duration(pipeline_->GetMediaDuration()); | 789 base::TimeDelta duration(pipeline_->GetMediaDuration()); |
| 620 base::TimeDelta start_seek_time(duration / 4); | 790 base::TimeDelta start_seek_time(duration / 4); |
| 621 base::TimeDelta seek_time(duration * 3 / 4); | 791 base::TimeDelta seek_time(duration * 3 / 4); |
| 622 | 792 |
| 623 Play(); | 793 Play(); |
| 624 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time)); | 794 ASSERT_TRUE(WaitUntilCurrentTimeIsAfter(start_seek_time)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 668 // Verify video decoder & renderer can handle aborted demuxer reads. | 838 // Verify video decoder & renderer can handle aborted demuxer reads. |
| 669 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { | 839 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) { |
| 670 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM, | 840 ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM, |
| 671 32768, | 841 32768, |
| 672 base::TimeDelta::FromMilliseconds(200), | 842 base::TimeDelta::FromMilliseconds(200), |
| 673 base::TimeDelta::FromMilliseconds(1668), | 843 base::TimeDelta::FromMilliseconds(1668), |
| 674 0x1C896, 65536)); | 844 0x1C896, 65536)); |
| 675 } | 845 } |
| 676 | 846 |
| 677 } // namespace media | 847 } // namespace media |
| OLD | NEW |