Chromium Code Reviews| Index: media/test/pipeline_integration_test_base.h |
| diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h |
| index a39eb3ffe447318ba17792f5ec5b53639cd1b4a5..9bac11f5d00143bbce476eb55886979c0d34fe3c 100644 |
| --- a/media/test/pipeline_integration_test_base.h |
| +++ b/media/test/pipeline_integration_test_base.h |
| @@ -13,6 +13,8 @@ |
| #include "base/test/scoped_task_scheduler.h" |
| #include "media/audio/clockless_audio_sink.h" |
| #include "media/audio/null_audio_sink.h" |
| +#include "media/base/cdm_context.h" |
| +#include "media/base/content_decryption_module.h" |
| #include "media/base/demuxer.h" |
| #include "media/base/null_video_sink.h" |
| #include "media/base/pipeline_impl.h" |
| @@ -20,12 +22,13 @@ |
| #include "media/base/text_track.h" |
| #include "media/base/text_track_config.h" |
| #include "media/base/video_frame.h" |
| +#include "media/filters/chunk_demuxer.h" |
| #include "media/renderers/video_renderer_impl.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| namespace media { |
| -class CdmContext; |
| +class AesDecryptor; |
| // Empty MD5 hash string. Used to verify empty video tracks. |
| extern const char kNullVideoHash[]; |
| @@ -33,6 +36,9 @@ extern const char kNullVideoHash[]; |
| // Empty hash string. Used to verify empty audio tracks. |
| extern const char kNullAudioHash[]; |
| +// Indicates that the whole file should be appended. |
| +extern const size_t kAppendWholeFile; |
| + |
| // Dummy tick clock which advances extremely quickly (1 minute every time |
| // NowTicks() is called). |
| class DummyTickClock : public base::TickClock { |
| @@ -45,6 +51,129 @@ class DummyTickClock : public base::TickClock { |
| base::TimeTicks now_; |
| }; |
| +class PipelineTestRendererFactory { |
| + public: |
| + virtual ~PipelineTestRendererFactory() {} |
| + // Creates and returns a Renderer. |
| + virtual std::unique_ptr<Renderer> CreateRenderer( |
| + CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(), |
| + CreateAudioDecodersCB prepend_audio_decoders_cb = |
| + CreateAudioDecodersCB()) = 0; |
| +}; |
| + |
| +// Helper class that emulates calls made on the ChunkDemuxer by the |
|
DaleCurtis
2017/04/20 18:24:51
Should be extracted to a mock_media_source.{h,cc}
xjz
2017/04/20 21:26:10
Done.
|
| +// Media Source API. |
| +class MockMediaSource { |
| + public: |
| + MockMediaSource(const std::string& filename, |
| + const std::string& mimetype, |
| + size_t initial_append_size); |
| + ~MockMediaSource(); |
| + |
| + std::unique_ptr<Demuxer> GetDemuxer(); |
| + void set_encrypted_media_init_data_cb( |
| + const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb); |
| + void set_demuxer_failure_cb(const PipelineStatusCB& demuxer_failure_cb); |
| + void Seek(base::TimeDelta seek_time, |
| + size_t new_position, |
| + size_t seek_append_size); |
| + void Seek(base::TimeDelta seek_time); |
| + void AppendData(size_t size); |
| + bool AppendAtTime(base::TimeDelta timestamp_offset, |
| + const uint8_t* pData, |
| + int size); |
| + void AppendAtTimeWithWindow(base::TimeDelta timestamp_offset, |
| + base::TimeDelta append_window_start, |
| + base::TimeDelta append_window_end, |
| + const uint8_t* pData, |
| + int size); |
| + void SetMemoryLimits(size_t limit_bytes); |
| + void EvictCodedFrames(base::TimeDelta currentMediaTime, size_t newDataSize); |
| + void RemoveRange(base::TimeDelta start, base::TimeDelta end); |
| + void EndOfStream(); |
| + void Shutdown(); |
| + void DemuxerOpened(); |
| + void DemuxerOpenedTask(); |
| + ChunkDemuxer::Status AddId(); |
| + void OnEncryptedMediaInitData(EmeInitDataType init_data_type, |
| + const std::vector<uint8_t>& init_data); |
| + base::TimeDelta last_timestamp_offset() const; |
| + void InitSegmentReceived(std::unique_ptr<MediaTracks> tracks); |
| + MOCK_METHOD1(InitSegmentReceivedMock, void(std::unique_ptr<MediaTracks>&)); |
| + |
| + private: |
| + MediaLog media_log_; |
| + scoped_refptr<DecoderBuffer> file_data_; |
| + size_t current_position_; |
| + size_t initial_append_size_; |
| + std::string mimetype_; |
| + ChunkDemuxer* chunk_demuxer_; |
| + std::unique_ptr<Demuxer> owned_chunk_demuxer_; |
| + PipelineStatusCB demuxer_failure_cb_; |
| + Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_; |
| + base::TimeDelta last_timestamp_offset_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockMediaSource); |
| +}; |
| + |
| +// Note: Tests using this class only exercise the DecryptingDemuxerStream path. |
|
DaleCurtis
2017/04/20 18:24:51
Ditto.
xjz
2017/04/20 21:26:10
Done.
|
| +// They do not exercise the Decrypting{Audio|Video}Decoder path. |
| +class FakeEncryptedMedia { |
| + public: |
| + // Defines the behavior of the "app" that responds to EME events. |
| + class AppBase { |
| + public: |
| + virtual ~AppBase() {} |
| + |
| + virtual void OnSessionMessage( |
| + const std::string& session_id, |
| + ContentDecryptionModule::MessageType message_type, |
| + const std::vector<uint8_t>& message, |
| + AesDecryptor* decryptor) = 0; |
| + |
| + virtual void OnSessionClosed(const std::string& session_id) = 0; |
| + |
| + virtual void OnSessionKeysChange(const std::string& session_id, |
| + bool has_additional_usable_key, |
| + CdmKeysInfo keys_info) = 0; |
| + |
| + virtual void OnEncryptedMediaInitData(EmeInitDataType init_data_type, |
| + const std::vector<uint8_t>& init_data, |
| + AesDecryptor* decryptor) = 0; |
| + }; |
| + |
| + FakeEncryptedMedia(AppBase* app); |
| + ~FakeEncryptedMedia(); |
| + CdmContext* GetCdmContext(); |
| + // Callbacks for firing session events. Delegate to |app_|. |
| + void OnSessionMessage(const std::string& session_id, |
| + ContentDecryptionModule::MessageType message_type, |
| + const std::vector<uint8_t>& message); |
| + void OnSessionClosed(const std::string& session_id); |
| + void OnSessionKeysChange(const std::string& session_id, |
| + bool has_additional_usable_key, |
| + CdmKeysInfo keys_info); |
| + void OnEncryptedMediaInitData(EmeInitDataType init_data_type, |
| + const std::vector<uint8_t>& init_data); |
| + |
| + private: |
| + class TestCdmContext : public CdmContext { |
| + public: |
| + TestCdmContext(Decryptor* decryptor); |
| + Decryptor* GetDecryptor() final; |
| + int GetCdmId() const final; |
| + |
| + private: |
| + Decryptor* decryptor_; |
| + }; |
| + |
| + scoped_refptr<AesDecryptor> decryptor_; |
| + TestCdmContext cdm_context_; |
| + std::unique_ptr<AppBase> app_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(FakeEncryptedMedia); |
| +}; |
| + |
| // Integration tests for Pipeline. Real demuxers, real decoders, and |
| // base renderer implementations are used to verify pipeline functionality. The |
| // renderers used in these tests rely heavily on the AudioRendererBase & |
| @@ -126,6 +255,10 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| encrypted_media_init_data_cb_ = encrypted_media_init_data_cb; |
| } |
| + std::unique_ptr<Renderer> CreateRenderer( |
| + CreateVideoDecodersCB prepend_video_decoders_cb, |
| + CreateAudioDecodersCB prepend_audio_decoders_cb); |
| + |
| protected: |
| MediaLog media_log_; |
| base::MessageLoop message_loop_; |
| @@ -150,6 +283,7 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| PipelineMetadata metadata_; |
| scoped_refptr<VideoFrame> last_frame_; |
| base::TimeDelta current_duration_; |
| + std::unique_ptr<PipelineTestRendererFactory> renderer_factory_; |
| PipelineStatus StartInternal( |
| std::unique_ptr<DataSource> data_source, |
| @@ -167,6 +301,15 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| CreateAudioDecodersCB prepend_audio_decoders_cb = |
| CreateAudioDecodersCB()); |
| + PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source); |
| + PipelineStatus StartPipelineWithEncryptedMedia( |
| + MockMediaSource* source, |
| + FakeEncryptedMedia* encrypted_media); |
| + PipelineStatus StartPipelineWithMediaSource( |
| + MockMediaSource* source, |
| + uint8_t test_type, |
| + FakeEncryptedMedia* encrypted_media); |
| + |
| void OnSeeked(base::TimeDelta seek_time, PipelineStatus status); |
| void OnStatusCallback(PipelineStatus status); |
| void DemuxerEncryptedMediaInitDataCB(EmeInitDataType type, |
| @@ -179,12 +322,6 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| // Creates Demuxer and sets |demuxer_|. |
| void CreateDemuxer(std::unique_ptr<DataSource> data_source); |
| - // Creates and returns a Renderer. |
| - virtual std::unique_ptr<Renderer> CreateRenderer( |
| - CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(), |
| - CreateAudioDecodersCB prepend_audio_decoders_cb = |
| - CreateAudioDecodersCB()); |
| - |
| void OnVideoFramePaint(const scoped_refptr<VideoFrame>& frame); |
| void CheckDuration(); |
| @@ -192,6 +329,14 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| // Return the media start time from |demuxer_|. |
| base::TimeDelta GetStartTime(); |
| + bool TestSeekDuringRead(const std::string& filename, |
|
DaleCurtis
2017/04/20 18:24:51
This should be on the normal PIT since you can dro
xjz
2017/04/20 21:26:10
Done.
|
| + const std::string& mimetype, |
| + int initial_append_size, |
| + base::TimeDelta start_seek_time, |
| + base::TimeDelta seek_time, |
| + int seek_file_position, |
| + int seek_append_size); |
| + |
| MOCK_METHOD1(DecryptorAttached, void(bool)); |
| // Pipeline::Client overrides. |
| void OnError(PipelineStatus status) override; |
| @@ -206,6 +351,9 @@ class PipelineIntegrationTestBase : public Pipeline::Client { |
| MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&)); |
| MOCK_METHOD1(OnVideoOpacityChange, void(bool)); |
| MOCK_METHOD0(OnVideoAverageKeyframeDistanceUpdate, void()); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(PipelineIntegrationTestBase); |
| }; |
| } // namespace media |