123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef MEDIA_TEST_PIPELINE_INTEGRATION_TEST_BASE_H_
- #define MEDIA_TEST_PIPELINE_INTEGRATION_TEST_BASE_H_
- #include <stdint.h>
- #include <memory>
- #include "base/callback_forward.h"
- #include "base/hash/md5.h"
- #include "base/run_loop.h"
- #include "base/test/scoped_run_loop_timeout.h"
- #include "base/test/task_environment.h"
- #include "base/time/time.h"
- #include "media/audio/clockless_audio_sink.h"
- #include "media/audio/null_audio_sink.h"
- #include "media/base/demuxer.h"
- #include "media/base/mock_media_log.h"
- #include "media/base/null_video_sink.h"
- #include "media/base/pipeline_impl.h"
- #include "media/base/pipeline_status.h"
- #include "media/base/text_track.h"
- #include "media/base/text_track_config.h"
- #include "media/base/video_frame.h"
- #include "media/renderers/audio_renderer_impl.h"
- #include "media/renderers/video_renderer_impl.h"
- #include "testing/gmock/include/gmock/gmock.h"
- using ::testing::NiceMock;
- namespace base {
- class RunLoop;
- }
- namespace media {
- class FakeEncryptedMedia;
- class TestMediaSource;
- // Empty MD5 hash string. Used to verify empty video tracks.
- extern const char kNullVideoHash[];
- // Empty hash string. Used to verify empty audio tracks.
- extern const char kNullAudioHash[];
- // 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 &
- // VideoRendererImpl implementations which contain a majority of the code used
- // in the real AudioRendererImpl & PaintCanvasVideoRenderer implementations used
- // in the browser. The renderers in this test don't actually write data to a
- // display or audio device. Both of these devices are simulated since they have
- // little effect on verifying pipeline behavior and allow tests to run faster
- // than real-time.
- class PipelineIntegrationTestBase : public Pipeline::Client {
- public:
- PipelineIntegrationTestBase();
- PipelineIntegrationTestBase(const PipelineIntegrationTestBase&) = delete;
- PipelineIntegrationTestBase& operator=(const PipelineIntegrationTestBase&) =
- delete;
- virtual ~PipelineIntegrationTestBase();
- // Test types for advanced testing and benchmarking (e.g., underflow is
- // disabled to ensure consistent hashes). May be combined using the bitwise
- // or operator (and as such must have values that are powers of two).
- enum TestTypeFlags {
- kNormal = 0,
- kHashed = 1,
- kNoClockless = 2,
- kExpectDemuxerFailure = 4,
- kUnreliableDuration = 8,
- kWebAudio = 16,
- kMonoOutput = 32,
- kFuzzing = 64,
- };
- // Setup method to intialize various state according to flags.
- void ParseTestTypeFlags(uint8_t flags);
- // Starts the pipeline with a file specified by |filename|, optionally with a
- // CdmContext or a |test_type|, returning the final status code after it has
- // started. |filename| points at a test file located under media/test/data/.
- PipelineStatus Start(const std::string& filename);
- PipelineStatus Start(const std::string& filename, CdmContext* cdm_context);
- PipelineStatus Start(
- const std::string& filename,
- uint8_t test_type,
- CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(),
- CreateAudioDecodersCB prepend_audio_decoders_cb =
- CreateAudioDecodersCB());
- // Starts the pipeline with |data| (with |size| bytes). The |data| will be
- // valid throughtout the lifetime of this test.
- PipelineStatus Start(const uint8_t* data, size_t size, uint8_t test_type);
- void Play();
- void Pause();
- bool Seek(base::TimeDelta seek_time);
- bool Suspend();
- bool Resume(base::TimeDelta seek_time);
- void Stop();
- // Fails the test with |status|.
- void FailTest(PipelineStatus status);
- bool WaitUntilCurrentTimeIsAfter(const base::TimeDelta& wait_time);
- bool WaitUntilOnEnded();
- PipelineStatus WaitUntilEndedOrError();
- // Returns the MD5 hash of all video frames seen. Should only be called once
- // after playback completes. First time hashes should be generated with
- // --video-threads=1 to ensure correctness. Pipeline must have been started
- // with hashing enabled.
- std::string GetVideoHash();
- // Returns the hash of all audio frames seen. Should only be called once
- // after playback completes. Pipeline must have been started with hashing
- // enabled.
- std::string GetAudioHash();
- // Reset video hash to restart hashing from scratch (e.g. after a seek or
- // after disabling a media track).
- void ResetVideoHash();
- // Returns the time taken to render the complete audio file.
- // Pipeline must have been started with clockless playback enabled.
- base::TimeDelta GetAudioTime();
- // Sets a callback to handle EME "encrypted" event. Must be called to test
- // potentially encrypted media.
- void set_encrypted_media_init_data_cb(
- const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) {
- encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
- }
- // Saves a test callback, ownership of which will be transferred to the next
- // AudioRendererImpl created by CreateDefaultRenderer().
- void set_audio_play_delay_cb(AudioRendererImpl::PlayDelayCBForTesting cb) {
- audio_play_delay_cb_ = std::move(cb);
- }
- std::unique_ptr<Renderer> CreateRenderer(
- absl::optional<RendererType> renderer_type);
- protected:
- NiceMock<MockMediaLog> media_log_;
- base::test::TaskEnvironment task_environment_;
- base::MD5Context md5_context_;
- bool hashing_enabled_;
- bool clockless_playback_;
- bool webaudio_attached_;
- bool mono_output_;
- bool fuzzing_;
- #if defined(ADDRESS_SANITIZER) || defined(UNDEFINED_SANITIZER)
- // TODO(https://crbug.com/924030): ASAN causes Run() timeouts to be reached.
- const base::test::ScopedDisableRunLoopTimeout disable_run_timeout_;
- #endif
- std::unique_ptr<Demuxer> demuxer_;
- std::unique_ptr<DataSource> data_source_;
- std::unique_ptr<PipelineImpl> pipeline_;
- scoped_refptr<NullAudioSink> audio_sink_;
- scoped_refptr<ClocklessAudioSink> clockless_audio_sink_;
- std::unique_ptr<NullVideoSink> video_sink_;
- bool ended_;
- PipelineStatus pipeline_status_;
- Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_;
- VideoPixelFormat last_video_frame_format_;
- gfx::ColorSpace last_video_frame_color_space_;
- PipelineMetadata metadata_;
- scoped_refptr<VideoFrame> last_frame_;
- base::TimeDelta current_duration_;
- AudioRendererImpl::PlayDelayCBForTesting audio_play_delay_cb_;
- // By default RendererImpl will be created using CreateDefaultRenderer(). But
- // if |create_renderer_cb_| is set, it'll be used to create the Renderer
- // instead.
- using CreateRendererCB = base::RepeatingCallback<std::unique_ptr<Renderer>(
- absl::optional<RendererType> renderer_type)>;
- CreateRendererCB create_renderer_cb_;
- std::unique_ptr<Renderer> CreateDefaultRenderer(
- absl::optional<RendererType> renderer_type);
- // Sets |create_renderer_cb_| which will be used to wrap the Renderer created
- // by CreateDefaultRenderer().
- void SetCreateRendererCB(CreateRendererCB create_renderer_cb);
- PipelineStatus StartInternal(
- std::unique_ptr<DataSource> data_source,
- CdmContext* cdm_context,
- uint8_t test_type,
- CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(),
- CreateAudioDecodersCB prepend_audio_decoders_cb =
- CreateAudioDecodersCB());
- PipelineStatus StartWithFile(
- const std::string& filename,
- CdmContext* cdm_context,
- uint8_t test_type,
- CreateVideoDecodersCB prepend_video_decoders_cb = CreateVideoDecodersCB(),
- CreateAudioDecodersCB prepend_audio_decoders_cb =
- CreateAudioDecodersCB());
- PipelineStatus StartPipelineWithMediaSource(TestMediaSource* source);
- PipelineStatus StartPipelineWithEncryptedMedia(
- TestMediaSource* source,
- FakeEncryptedMedia* encrypted_media);
- PipelineStatus StartPipelineWithMediaSource(
- TestMediaSource* source,
- uint8_t test_type,
- FakeEncryptedMedia* encrypted_media);
- PipelineStatus StartPipelineWithMediaSource(
- TestMediaSource* source,
- uint8_t test_type,
- CreateAudioDecodersCB prepend_audio_decoders_cb);
- void OnSeeked(base::TimeDelta seek_time, PipelineStatus status);
- void OnStatusCallback(const base::RepeatingClosure& quit_run_loop_closure,
- PipelineStatus status);
- void DemuxerEncryptedMediaInitDataCB(EmeInitDataType type,
- const std::vector<uint8_t>& init_data);
- void DemuxerMediaTracksUpdatedCB(std::unique_ptr<MediaTracks> tracks);
- void QuitAfterCurrentTimeTask(base::TimeDelta quit_time,
- base::OnceClosure quit_closure);
- // Creates Demuxer and sets |demuxer_|.
- void CreateDemuxer(std::unique_ptr<DataSource> data_source);
- void OnVideoFramePaint(scoped_refptr<VideoFrame> frame);
- void CheckDuration();
- // Return the media start time from |demuxer_|.
- base::TimeDelta GetStartTime();
- MOCK_METHOD1(DecryptorAttached, void(bool));
- // Pipeline::Client overrides.
- void OnError(PipelineStatus status) override;
- void OnFallback(PipelineStatus status) override;
- void OnEnded() override;
- MOCK_METHOD1(OnMetadata, void(const PipelineMetadata&));
- MOCK_METHOD2(OnBufferingStateChange,
- void(BufferingState, BufferingStateChangeReason));
- MOCK_METHOD0(OnDurationChange, void());
- MOCK_METHOD2(OnAddTextTrack,
- void(const TextTrackConfig& config, AddTextTrackDoneCB done_cb));
- MOCK_METHOD1(OnWaiting, void(WaitingReason));
- MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&));
- MOCK_METHOD1(OnVideoConfigChange, void(const VideoDecoderConfig&));
- MOCK_METHOD1(OnAudioConfigChange, void(const AudioDecoderConfig&));
- MOCK_METHOD1(OnVideoOpacityChange, void(bool));
- MOCK_METHOD1(OnVideoFrameRateChange, void(absl::optional<int>));
- MOCK_METHOD0(OnVideoAverageKeyframeDistanceUpdate, void());
- MOCK_METHOD1(OnAudioPipelineInfoChange, void(const AudioPipelineInfo&));
- MOCK_METHOD1(OnVideoPipelineInfoChange, void(const VideoPipelineInfo&));
- MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
- private:
- // Runs |run_loop| until it is explicitly Quit() by some part of the calling
- // test fixture or when an error occurs (by setting |on_error_closure_|). The
- // |task_environment_| is RunUntilIdle() after the RunLoop finishes
- // running, before returning to the caller.
- void RunUntilQuitOrError(base::RunLoop* run_loop);
- // Configures |on_ended_closure_| to quit |run_loop| and then calls
- // RunUntilQuitOrError() on it.
- void RunUntilQuitOrEndedOrError(base::RunLoop* run_loop);
- CreateVideoDecodersCB prepend_video_decoders_cb_;
- CreateAudioDecodersCB prepend_audio_decoders_cb_;
- base::OnceClosure on_ended_closure_;
- base::OnceClosure on_error_closure_;
- };
- } // namespace media
- #endif // MEDIA_TEST_PIPELINE_INTEGRATION_TEST_BASE_H_
|