#include "media/test/pipeline_integration_test_base.h"
#include <memory>
#include <utility>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/sequence_bound.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/media_tracks.h"
#include "media/base/test_data_util.h"
#include "media/filters/file_data_source.h"
#include "media/filters/memory_data_source.h"
#include "media/media_buildflags.h"
#include "media/mojo/services/gpu_mojo_media_client_test_util.h"
#include "media/renderers/audio_renderer_impl.h"
#include "media/renderers/renderer_impl.h"
#include "media/test/fake_encrypted_media.h"
#include "media/test/test_media_source.h"
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
#include "media/filters/dav1d_video_decoder.h"
#endif
#if BUILDFLAG(ENABLE_FFMPEG)
#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer.h"
#endif
#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
#include "media/filters/ffmpeg_video_decoder.h"
#endif
#if BUILDFLAG(ENABLE_LIBVPX)
#include "media/filters/vpx_video_decoder.h"
#endif
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
#include "media/filters/hls_data_source_provider_impl.h"
#include "media/filters/hls_manifest_demuxer_engine.h"
#include "media/filters/manifest_demuxer.h"
#endif
_;
AnyNumber;
AtLeast;
AtMost;
Invoke;
InvokeWithoutArgs;
InSequence;
Return;
SaveArg;
namespace media {
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
namespace {
class TestDataSourceFactory
: public HlsDataSourceProviderImpl::DataSourceFactory {
public:
~TestDataSourceFactory() override = default;
void CreateDataSource(GURL uri, DataSourceCb callback) override {
auto file_data_source = std::make_unique<FileDataSource>();
base::FilePath file_path(uri.GetContent());
CHECK(file_data_source->Initialize(file_path))
<< "Is " << file_path.value() << " missing?";
std::move(callback).Run(std::move(file_data_source));
}
};
}
#endif
static std::vector<std::unique_ptr<VideoDecoder>> CreateVideoDecodersForTest(
MediaLog* media_log,
CreateVideoDecodersCB prepend_video_decoders_cb) { … }
static std::vector<std::unique_ptr<AudioDecoder>> CreateAudioDecodersForTest(
MediaLog* media_log,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
CreateAudioDecodersCB prepend_audio_decoders_cb) { … }
const char kNullVideoHash[] = …;
const char kNullAudioHash[] = …;
PipelineIntegrationTestBase::PipelineIntegrationTestBase()
: … { … }
PipelineIntegrationTestBase::~PipelineIntegrationTestBase() { … }
void PipelineIntegrationTestBase::ParseTestTypeFlags(uint8_t flags) { … }
void PipelineIntegrationTestBase::OnSeeked(base::TimeDelta seek_time,
PipelineStatus status) { … }
void PipelineIntegrationTestBase::OnStatusCallback(
const base::RepeatingClosure& quit_run_loop_closure,
PipelineStatus status) { … }
void PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB(
EmeInitDataType type,
const std::vector<uint8_t>& init_data) { … }
void PipelineIntegrationTestBase::DemuxerMediaTracksUpdatedCB(
std::unique_ptr<MediaTracks> tracks) { … }
void PipelineIntegrationTestBase::OnEnded() { … }
bool PipelineIntegrationTestBase::WaitUntilOnEnded() { … }
PipelineStatus PipelineIntegrationTestBase::WaitUntilEndedOrError() { … }
void PipelineIntegrationTestBase::OnError(PipelineStatus status) { … }
void PipelineIntegrationTestBase::OnFallback(PipelineStatus status) { … }
void PipelineIntegrationTestBase::SetCreateRendererCB(
CreateRendererCB create_renderer_cb) { … }
#if BUILDFLAG(ENABLE_HLS_DEMUXER)
PipelineStatus PipelineIntegrationTestBase::StartPipelineWithHlsManifest(
const std::string& filename) {
hashing_enabled_ = true;
auto full_path = GetTestDataFilePath(filename);
std::string file_url = "file://" + full_path.MaybeAsASCII();
GURL manifest_root{file_url};
auto multibuffer_factory = std::make_unique<TestDataSourceFactory>();
auto hls_dsp = base::SequenceBound<HlsDataSourceProviderImpl>(
task_environment_.GetMainThreadTaskRunner(),
std::move(multibuffer_factory));
auto engine = std::make_unique<HlsManifestDemuxerEngine>(
std::move(hls_dsp), task_environment_.GetMainThreadTaskRunner(),
false, manifest_root, &media_log_);
demuxer_ = std::make_unique<ManifestDemuxer>(
task_environment_.GetMainThreadTaskRunner(), base::DoNothing(),
std::move(engine), &media_log_);
EXPECT_CALL(*this, OnMetadata(_))
.Times(AtMost(1))
.WillRepeatedly(SaveArg<0>(&metadata_));
base::RunLoop run_loop;
pipeline_->Start(
Pipeline::StartType::kNormal, demuxer_.get(), this,
base::BindOnce(&PipelineIntegrationTestBase::OnStatusCallback,
base::Unretained(this), run_loop.QuitClosure()));
RunUntilQuitOrEndedOrError(&run_loop);
return pipeline_status_;
}
#endif
PipelineStatus PipelineIntegrationTestBase::StartInternal(
std::unique_ptr<DataSource> data_source,
CdmContext* cdm_context,
uint8_t test_type,
CreateVideoDecodersCB prepend_video_decoders_cb,
CreateAudioDecodersCB prepend_audio_decoders_cb) { … }
PipelineStatus PipelineIntegrationTestBase::StartWithFile(
const std::string& filename,
CdmContext* cdm_context,
uint8_t test_type,
CreateVideoDecodersCB prepend_video_decoders_cb,
CreateAudioDecodersCB prepend_audio_decoders_cb) { … }
PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename) { … }
PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
CdmContext* cdm_context) { … }
PipelineStatus PipelineIntegrationTestBase::Start(
const std::string& filename,
uint8_t test_type,
CreateVideoDecodersCB prepend_video_decoders_cb,
CreateAudioDecodersCB prepend_audio_decoders_cb) { … }
PipelineStatus PipelineIntegrationTestBase::Start(const uint8_t* data,
size_t size,
uint8_t test_type) { … }
void PipelineIntegrationTestBase::Play() { … }
void PipelineIntegrationTestBase::Pause() { … }
void PipelineIntegrationTestBase::OnBufferingStateChangeForSeek(
BufferingState state,
BufferingStateChangeReason reason) { … }
bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) { … }
bool PipelineIntegrationTestBase::Suspend() { … }
bool PipelineIntegrationTestBase::Resume(base::TimeDelta seek_time) { … }
void PipelineIntegrationTestBase::Stop() { … }
void PipelineIntegrationTestBase::FailTest(PipelineStatus status) { … }
void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
base::TimeDelta quit_time,
base::OnceClosure quit_closure) { … }
bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
const base::TimeDelta& wait_time) { … }
void PipelineIntegrationTestBase::CreateDemuxer(
std::unique_ptr<DataSource> data_source) { … }
std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer(
std::optional<RendererType> renderer_type) { … }
std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateRendererImpl(
std::optional<RendererType> renderer_type) { … }
void PipelineIntegrationTestBase::OnVideoFramePaint(
scoped_refptr<VideoFrame> frame) { … }
void PipelineIntegrationTestBase::CheckDuration() { … }
base::TimeDelta PipelineIntegrationTestBase::GetStartTime() { … }
void PipelineIntegrationTestBase::ResetVideoHash() { … }
std::string PipelineIntegrationTestBase::GetVideoHash() { … }
const AudioHash& PipelineIntegrationTestBase::GetAudioHash() const { … }
base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() { … }
PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
TestMediaSource* source) { … }
PipelineStatus PipelineIntegrationTestBase::StartPipelineWithEncryptedMedia(
TestMediaSource* source,
FakeEncryptedMedia* encrypted_media) { … }
PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
TestMediaSource* source,
uint8_t test_type,
CreateAudioDecodersCB prepend_audio_decoders_cb) { … }
PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
TestMediaSource* source,
uint8_t test_type,
FakeEncryptedMedia* encrypted_media) { … }
void PipelineIntegrationTestBase::RunUntilQuitOrError(base::RunLoop* run_loop) { … }
void PipelineIntegrationTestBase::RunUntilQuitOrEndedOrError(
base::RunLoop* run_loop) { … }
}