pipeline_integration_test_base.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  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
  3. // found in the LICENSE file.
  4. #include "media/test/pipeline_integration_test_base.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/feature_list.h"
  10. #include "base/memory/ref_counted.h"
  11. #include "base/run_loop.h"
  12. #include "base/task/single_thread_task_runner.h"
  13. #include "base/time/time.h"
  14. #include "build/build_config.h"
  15. #include "media/base/media_log.h"
  16. #include "media/base/media_switches.h"
  17. #include "media/base/media_tracks.h"
  18. #include "media/base/test_data_util.h"
  19. #include "media/filters/file_data_source.h"
  20. #include "media/filters/memory_data_source.h"
  21. #include "media/media_buildflags.h"
  22. #include "media/renderers/audio_renderer_impl.h"
  23. #include "media/renderers/renderer_impl.h"
  24. #include "media/test/fake_encrypted_media.h"
  25. #include "media/test/test_media_source.h"
  26. #if BUILDFLAG(ENABLE_DAV1D_DECODER)
  27. #include "media/filters/dav1d_video_decoder.h"
  28. #endif
  29. #if BUILDFLAG(ENABLE_FFMPEG)
  30. #include "media/filters/ffmpeg_audio_decoder.h"
  31. #include "media/filters/ffmpeg_demuxer.h"
  32. #endif
  33. #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  34. #include "media/filters/ffmpeg_video_decoder.h"
  35. #endif
  36. #if BUILDFLAG(ENABLE_LIBVPX)
  37. #include "media/filters/vpx_video_decoder.h"
  38. #endif
  39. #if BUILDFLAG(ENABLE_LIBGAV1_DECODER)
  40. #include "media/filters/gav1_video_decoder.h"
  41. #endif
  42. using ::testing::_;
  43. using ::testing::AnyNumber;
  44. using ::testing::AtLeast;
  45. using ::testing::AtMost;
  46. using ::testing::Invoke;
  47. using ::testing::InvokeWithoutArgs;
  48. using ::testing::InSequence;
  49. using ::testing::Return;
  50. using ::testing::SaveArg;
  51. namespace media {
  52. static std::vector<std::unique_ptr<VideoDecoder>> CreateVideoDecodersForTest(
  53. MediaLog* media_log,
  54. CreateVideoDecodersCB prepend_video_decoders_cb) {
  55. std::vector<std::unique_ptr<VideoDecoder>> video_decoders;
  56. if (prepend_video_decoders_cb) {
  57. video_decoders = prepend_video_decoders_cb.Run();
  58. DCHECK(!video_decoders.empty());
  59. }
  60. #if BUILDFLAG(ENABLE_LIBVPX)
  61. video_decoders.push_back(std::make_unique<OffloadingVpxVideoDecoder>());
  62. #endif
  63. #if BUILDFLAG(ENABLE_LIBGAV1_DECODER)
  64. if (base::FeatureList::IsEnabled(kGav1VideoDecoder)) {
  65. video_decoders.push_back(
  66. std::make_unique<OffloadingGav1VideoDecoder>(media_log));
  67. } else
  68. #endif // BUILDFLAG(ENABLE_LIBGAV1_DECODER)
  69. {
  70. #if BUILDFLAG(ENABLE_DAV1D_DECODER)
  71. video_decoders.push_back(
  72. std::make_unique<OffloadingDav1dVideoDecoder>(media_log));
  73. #endif
  74. }
  75. #if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
  76. video_decoders.push_back(std::make_unique<FFmpegVideoDecoder>(media_log));
  77. #endif
  78. return video_decoders;
  79. }
  80. static std::vector<std::unique_ptr<AudioDecoder>> CreateAudioDecodersForTest(
  81. MediaLog* media_log,
  82. const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
  83. CreateAudioDecodersCB prepend_audio_decoders_cb) {
  84. std::vector<std::unique_ptr<AudioDecoder>> audio_decoders;
  85. if (prepend_audio_decoders_cb) {
  86. audio_decoders = prepend_audio_decoders_cb.Run();
  87. DCHECK(!audio_decoders.empty());
  88. }
  89. #if BUILDFLAG(ENABLE_FFMPEG)
  90. audio_decoders.push_back(
  91. std::make_unique<FFmpegAudioDecoder>(media_task_runner, media_log));
  92. #endif
  93. return audio_decoders;
  94. }
  95. const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e";
  96. const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,";
  97. PipelineIntegrationTestBase::PipelineIntegrationTestBase()
  98. :
  99. // Use a UI type message loop on macOS, because it doesn't seem to schedule
  100. // callbacks with enough precision to drive our fake audio output. See
  101. // https://crbug.com/1014646 for more details.
  102. #if BUILDFLAG(IS_MAC)
  103. task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
  104. #endif
  105. hashing_enabled_(false),
  106. clockless_playback_(false),
  107. webaudio_attached_(false),
  108. mono_output_(false),
  109. fuzzing_(false),
  110. ended_(false),
  111. pipeline_status_(PIPELINE_OK),
  112. last_video_frame_format_(PIXEL_FORMAT_UNKNOWN),
  113. current_duration_(kInfiniteDuration) {
  114. pipeline_ = std::make_unique<PipelineImpl>(
  115. task_environment_.GetMainThreadTaskRunner(),
  116. task_environment_.GetMainThreadTaskRunner(),
  117. base::BindRepeating(&PipelineIntegrationTestBase::CreateRenderer,
  118. base::Unretained(this)),
  119. &media_log_);
  120. ResetVideoHash();
  121. EXPECT_CALL(*this, OnVideoAverageKeyframeDistanceUpdate()).Times(AnyNumber());
  122. }
  123. PipelineIntegrationTestBase::~PipelineIntegrationTestBase() {
  124. if (pipeline_->IsRunning())
  125. Stop();
  126. demuxer_.reset();
  127. pipeline_.reset();
  128. base::RunLoop().RunUntilIdle();
  129. }
  130. void PipelineIntegrationTestBase::ParseTestTypeFlags(uint8_t flags) {
  131. hashing_enabled_ = flags & kHashed;
  132. clockless_playback_ = !(flags & kNoClockless);
  133. webaudio_attached_ = flags & kWebAudio;
  134. mono_output_ = flags & kMonoOutput;
  135. fuzzing_ = flags & kFuzzing;
  136. }
  137. // TODO(xhwang): Method definitions in this file needs to be reordered.
  138. void PipelineIntegrationTestBase::OnSeeked(base::TimeDelta seek_time,
  139. PipelineStatus status) {
  140. // When fuzzing, sometimes a seek to 0 results in an actual media time > 0.
  141. if (fuzzing_)
  142. EXPECT_LE(seek_time, pipeline_->GetMediaTime());
  143. else
  144. EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
  145. pipeline_status_ = status;
  146. }
  147. void PipelineIntegrationTestBase::OnStatusCallback(
  148. const base::RepeatingClosure& quit_run_loop_closure,
  149. PipelineStatus status) {
  150. pipeline_status_ = status;
  151. if (pipeline_status_ != PIPELINE_OK && pipeline_->IsRunning())
  152. pipeline_->Stop();
  153. quit_run_loop_closure.Run();
  154. }
  155. void PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB(
  156. EmeInitDataType type,
  157. const std::vector<uint8_t>& init_data) {
  158. DCHECK(!init_data.empty());
  159. CHECK(encrypted_media_init_data_cb_);
  160. encrypted_media_init_data_cb_.Run(type, init_data);
  161. }
  162. void PipelineIntegrationTestBase::DemuxerMediaTracksUpdatedCB(
  163. std::unique_ptr<MediaTracks> tracks) {
  164. CHECK(tracks);
  165. CHECK_GT(tracks->tracks().size(), 0u);
  166. // Verify that track ids are unique.
  167. std::set<MediaTrack::Id> track_ids;
  168. for (const auto& track : tracks->tracks()) {
  169. EXPECT_EQ(track_ids.end(), track_ids.find(track->id()));
  170. track_ids.insert(track->id());
  171. }
  172. }
  173. void PipelineIntegrationTestBase::OnEnded() {
  174. DCHECK(!ended_);
  175. ended_ = true;
  176. pipeline_status_ = PIPELINE_OK;
  177. if (on_ended_closure_)
  178. std::move(on_ended_closure_).Run();
  179. }
  180. bool PipelineIntegrationTestBase::WaitUntilOnEnded() {
  181. EXPECT_EQ(pipeline_status_, PIPELINE_OK);
  182. PipelineStatus status = WaitUntilEndedOrError();
  183. EXPECT_TRUE(ended_);
  184. EXPECT_EQ(pipeline_status_, PIPELINE_OK);
  185. return ended_ && (status == PIPELINE_OK);
  186. }
  187. PipelineStatus PipelineIntegrationTestBase::WaitUntilEndedOrError() {
  188. if (!ended_ && pipeline_status_ == PIPELINE_OK) {
  189. base::RunLoop run_loop;
  190. RunUntilQuitOrEndedOrError(&run_loop);
  191. } else {
  192. task_environment_.RunUntilIdle();
  193. }
  194. return pipeline_status_;
  195. }
  196. void PipelineIntegrationTestBase::OnError(PipelineStatus status) {
  197. DCHECK(status != PIPELINE_OK);
  198. pipeline_status_ = status;
  199. pipeline_->Stop();
  200. if (on_error_closure_)
  201. std::move(on_error_closure_).Run();
  202. }
  203. void PipelineIntegrationTestBase::OnFallback(PipelineStatus status) {
  204. DCHECK(status != PIPELINE_OK);
  205. }
  206. void PipelineIntegrationTestBase::SetCreateRendererCB(
  207. CreateRendererCB create_renderer_cb) {
  208. create_renderer_cb_ = std::move(create_renderer_cb);
  209. }
  210. PipelineStatus PipelineIntegrationTestBase::StartInternal(
  211. std::unique_ptr<DataSource> data_source,
  212. CdmContext* cdm_context,
  213. uint8_t test_type,
  214. CreateVideoDecodersCB prepend_video_decoders_cb,
  215. CreateAudioDecodersCB prepend_audio_decoders_cb) {
  216. prepend_video_decoders_cb_ = std::move(prepend_video_decoders_cb);
  217. prepend_audio_decoders_cb_ = std::move(prepend_audio_decoders_cb);
  218. ParseTestTypeFlags(test_type);
  219. EXPECT_CALL(*this, OnMetadata(_))
  220. .Times(AtMost(1))
  221. .WillRepeatedly(SaveArg<0>(&metadata_));
  222. EXPECT_CALL(*this, OnBufferingStateChange(_, _)).Times(AnyNumber());
  223. // If the test is expected to have reliable duration information, permit at
  224. // most two calls to OnDurationChange. CheckDuration will make sure that no
  225. // more than one of them is a finite duration. This allows the pipeline to
  226. // call back at the end of the media with the known duration.
  227. //
  228. // In the event of unreliable duration information, just set the expectation
  229. // that it's called at least once. Such streams may repeatedly update their
  230. // duration as new packets are demuxed.
  231. if (test_type & kUnreliableDuration) {
  232. EXPECT_CALL(*this, OnDurationChange()).Times(AnyNumber());
  233. } else {
  234. EXPECT_CALL(*this, OnDurationChange())
  235. .Times(AtMost(2))
  236. .WillRepeatedly(
  237. Invoke(this, &PipelineIntegrationTestBase::CheckDuration));
  238. }
  239. EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(AnyNumber());
  240. EXPECT_CALL(*this, OnVideoOpacityChange(_)).WillRepeatedly(Return());
  241. EXPECT_CALL(*this, OnVideoFrameRateChange(_)).Times(AnyNumber());
  242. EXPECT_CALL(*this, OnAudioPipelineInfoChange(_)).Times(AnyNumber());
  243. EXPECT_CALL(*this, OnVideoPipelineInfoChange(_)).Times(AnyNumber());
  244. CreateDemuxer(std::move(data_source));
  245. if (cdm_context) {
  246. EXPECT_CALL(*this, DecryptorAttached(true));
  247. pipeline_->SetCdm(
  248. cdm_context,
  249. base::BindOnce(&PipelineIntegrationTestBase::DecryptorAttached,
  250. base::Unretained(this)));
  251. }
  252. // Should never be called as the required decryption keys for the encrypted
  253. // media files are provided in advance.
  254. EXPECT_CALL(*this, OnWaiting(WaitingReason::kNoDecryptionKey)).Times(0);
  255. // DemuxerStreams may signal config changes.
  256. // In practice, this doesn't happen for FFmpegDemuxer, but it's allowed for
  257. // SRC= demuxers in general.
  258. EXPECT_CALL(*this, OnAudioConfigChange(_)).Times(AnyNumber());
  259. EXPECT_CALL(*this, OnVideoConfigChange(_)).Times(AnyNumber());
  260. base::RunLoop run_loop;
  261. pipeline_->Start(
  262. Pipeline::StartType::kNormal, demuxer_.get(), this,
  263. base::BindOnce(&PipelineIntegrationTestBase::OnStatusCallback,
  264. base::Unretained(this), run_loop.QuitClosure()));
  265. RunUntilQuitOrEndedOrError(&run_loop);
  266. return pipeline_status_;
  267. }
  268. PipelineStatus PipelineIntegrationTestBase::StartWithFile(
  269. const std::string& filename,
  270. CdmContext* cdm_context,
  271. uint8_t test_type,
  272. CreateVideoDecodersCB prepend_video_decoders_cb,
  273. CreateAudioDecodersCB prepend_audio_decoders_cb) {
  274. std::unique_ptr<FileDataSource> file_data_source(new FileDataSource());
  275. base::FilePath file_path(GetTestDataFilePath(filename));
  276. CHECK(file_data_source->Initialize(file_path)) << "Is " << file_path.value()
  277. << " missing?";
  278. return StartInternal(std::move(file_data_source), cdm_context, test_type,
  279. prepend_video_decoders_cb, prepend_audio_decoders_cb);
  280. }
  281. PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename) {
  282. return StartWithFile(filename, nullptr, kNormal);
  283. }
  284. PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
  285. CdmContext* cdm_context) {
  286. return StartWithFile(filename, cdm_context, kNormal);
  287. }
  288. PipelineStatus PipelineIntegrationTestBase::Start(
  289. const std::string& filename,
  290. uint8_t test_type,
  291. CreateVideoDecodersCB prepend_video_decoders_cb,
  292. CreateAudioDecodersCB prepend_audio_decoders_cb) {
  293. return StartWithFile(filename, nullptr, test_type, prepend_video_decoders_cb,
  294. prepend_audio_decoders_cb);
  295. }
  296. PipelineStatus PipelineIntegrationTestBase::Start(const uint8_t* data,
  297. size_t size,
  298. uint8_t test_type) {
  299. return StartInternal(std::make_unique<MemoryDataSource>(data, size), nullptr,
  300. test_type);
  301. }
  302. void PipelineIntegrationTestBase::Play() {
  303. pipeline_->SetPlaybackRate(1);
  304. }
  305. void PipelineIntegrationTestBase::Pause() {
  306. pipeline_->SetPlaybackRate(0);
  307. }
  308. bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
  309. // Enforce that BUFFERING_HAVE_ENOUGH is the first call below.
  310. ::testing::InSequence dummy;
  311. ended_ = false;
  312. base::RunLoop run_loop;
  313. // Should always transition to HAVE_ENOUGH once the seek completes.
  314. EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
  315. .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
  316. // After initial HAVE_ENOUGH, any buffering state change is allowed as
  317. // playback may cause any number of underflow/preroll events.
  318. EXPECT_CALL(*this, OnBufferingStateChange(_, _)).Times(AnyNumber());
  319. pipeline_->Seek(seek_time,
  320. base::BindOnce(&PipelineIntegrationTestBase::OnSeeked,
  321. base::Unretained(this), seek_time));
  322. RunUntilQuitOrError(&run_loop);
  323. return (pipeline_status_ == PIPELINE_OK);
  324. }
  325. bool PipelineIntegrationTestBase::Suspend() {
  326. base::RunLoop run_loop;
  327. pipeline_->Suspend(
  328. base::BindOnce(&PipelineIntegrationTestBase::OnStatusCallback,
  329. base::Unretained(this), run_loop.QuitClosure()));
  330. RunUntilQuitOrError(&run_loop);
  331. return (pipeline_status_ == PIPELINE_OK);
  332. }
  333. bool PipelineIntegrationTestBase::Resume(base::TimeDelta seek_time) {
  334. ended_ = false;
  335. base::RunLoop run_loop;
  336. EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _))
  337. .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
  338. pipeline_->Resume(seek_time,
  339. base::BindOnce(&PipelineIntegrationTestBase::OnSeeked,
  340. base::Unretained(this), seek_time));
  341. RunUntilQuitOrError(&run_loop);
  342. return (pipeline_status_ == PIPELINE_OK);
  343. }
  344. void PipelineIntegrationTestBase::Stop() {
  345. DCHECK(pipeline_->IsRunning());
  346. pipeline_->Stop();
  347. base::RunLoop().RunUntilIdle();
  348. }
  349. void PipelineIntegrationTestBase::FailTest(PipelineStatus status) {
  350. DCHECK(status != PIPELINE_OK);
  351. OnError(status);
  352. }
  353. void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
  354. base::TimeDelta quit_time,
  355. base::OnceClosure quit_closure) {
  356. if (!pipeline_ || pipeline_->GetMediaTime() >= quit_time ||
  357. pipeline_status_ != PIPELINE_OK) {
  358. std::move(quit_closure).Run();
  359. return;
  360. }
  361. task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
  362. FROM_HERE,
  363. base::BindOnce(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
  364. base::Unretained(this), quit_time,
  365. std::move(quit_closure)),
  366. base::Milliseconds(10));
  367. }
  368. bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
  369. const base::TimeDelta& wait_time) {
  370. DCHECK(pipeline_->IsRunning());
  371. DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
  372. DCHECK(wait_time <= pipeline_->GetMediaDuration());
  373. base::RunLoop run_loop;
  374. task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
  375. FROM_HERE,
  376. base::BindOnce(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
  377. base::Unretained(this), wait_time, run_loop.QuitClosure()),
  378. base::Milliseconds(10));
  379. RunUntilQuitOrEndedOrError(&run_loop);
  380. return (pipeline_status_ == PIPELINE_OK);
  381. }
  382. void PipelineIntegrationTestBase::CreateDemuxer(
  383. std::unique_ptr<DataSource> data_source) {
  384. data_source_ = std::move(data_source);
  385. #if BUILDFLAG(ENABLE_FFMPEG)
  386. demuxer_ = std::unique_ptr<Demuxer>(new FFmpegDemuxer(
  387. task_environment_.GetMainThreadTaskRunner(), data_source_.get(),
  388. base::BindRepeating(
  389. &PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB,
  390. base::Unretained(this)),
  391. base::BindRepeating(
  392. &PipelineIntegrationTestBase::DemuxerMediaTracksUpdatedCB,
  393. base::Unretained(this)),
  394. &media_log_, true));
  395. #endif
  396. }
  397. std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer(
  398. absl::optional<RendererType> renderer_type) {
  399. if (create_renderer_cb_)
  400. return create_renderer_cb_.Run(renderer_type);
  401. return CreateDefaultRenderer(renderer_type);
  402. }
  403. std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateDefaultRenderer(
  404. absl::optional<RendererType> renderer_type) {
  405. if (renderer_type && *renderer_type != RendererType::kDefault) {
  406. DVLOG(1) << __func__ << ": renderer_type not supported";
  407. return nullptr;
  408. }
  409. // Simulate a 60Hz rendering sink.
  410. video_sink_ = std::make_unique<NullVideoSink>(
  411. clockless_playback_, base::Seconds(1.0 / 60),
  412. base::BindRepeating(&PipelineIntegrationTestBase::OnVideoFramePaint,
  413. base::Unretained(this)),
  414. task_environment_.GetMainThreadTaskRunner());
  415. // Disable frame dropping if hashing is enabled.
  416. auto video_renderer = std::make_unique<VideoRendererImpl>(
  417. task_environment_.GetMainThreadTaskRunner(), video_sink_.get(),
  418. base::BindRepeating(&CreateVideoDecodersForTest, &media_log_,
  419. prepend_video_decoders_cb_),
  420. false, &media_log_, nullptr);
  421. if (!clockless_playback_) {
  422. DCHECK(!mono_output_) << " NullAudioSink doesn't specify output parameters";
  423. audio_sink_ =
  424. new NullAudioSink(task_environment_.GetMainThreadTaskRunner());
  425. } else {
  426. ChannelLayout output_layout =
  427. mono_output_ ? CHANNEL_LAYOUT_MONO : CHANNEL_LAYOUT_STEREO;
  428. clockless_audio_sink_ = new ClocklessAudioSink(
  429. OutputDeviceInfo("", OUTPUT_DEVICE_STATUS_OK,
  430. AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
  431. output_layout, 44100, 512)));
  432. // Say "not optimized for hardware parameters" to disallow renderer
  433. // resampling. Hashed tests need this avoid platform dependent floating
  434. // point precision differences.
  435. if (webaudio_attached_ || hashing_enabled_) {
  436. clockless_audio_sink_->SetIsOptimizedForHardwareParametersForTesting(
  437. false);
  438. }
  439. }
  440. auto audio_renderer = std::make_unique<AudioRendererImpl>(
  441. task_environment_.GetMainThreadTaskRunner(),
  442. (clockless_playback_)
  443. ? static_cast<AudioRendererSink*>(clockless_audio_sink_.get())
  444. : audio_sink_.get(),
  445. base::BindRepeating(&CreateAudioDecodersForTest, &media_log_,
  446. task_environment_.GetMainThreadTaskRunner(),
  447. prepend_audio_decoders_cb_),
  448. &media_log_, nullptr);
  449. if (hashing_enabled_) {
  450. if (clockless_playback_)
  451. clockless_audio_sink_->StartAudioHashForTesting();
  452. else
  453. audio_sink_->StartAudioHashForTesting();
  454. }
  455. static_cast<AudioRendererImpl*>(audio_renderer.get())
  456. ->SetPlayDelayCBForTesting(std::move(audio_play_delay_cb_));
  457. std::unique_ptr<RendererImpl> renderer_impl = std::make_unique<RendererImpl>(
  458. task_environment_.GetMainThreadTaskRunner(), std::move(audio_renderer),
  459. std::move(video_renderer));
  460. // Prevent non-deterministic buffering state callbacks from firing (e.g., slow
  461. // machine, valgrind).
  462. renderer_impl->DisableUnderflowForTesting();
  463. if (clockless_playback_)
  464. renderer_impl->EnableClocklessVideoPlaybackForTesting();
  465. return renderer_impl;
  466. }
  467. void PipelineIntegrationTestBase::OnVideoFramePaint(
  468. scoped_refptr<VideoFrame> frame) {
  469. last_video_frame_format_ = frame->format();
  470. last_video_frame_color_space_ = frame->ColorSpace();
  471. if (!hashing_enabled_ || last_frame_ == frame)
  472. return;
  473. DVLOG(3) << __func__ << " pts=" << frame->timestamp().InSecondsF();
  474. VideoFrame::HashFrameForTesting(&md5_context_, *frame);
  475. last_frame_ = std::move(frame);
  476. }
  477. void PipelineIntegrationTestBase::CheckDuration() {
  478. // Allow the pipeline to specify indefinite duration, then reduce it once
  479. // it becomes known.
  480. ASSERT_EQ(kInfiniteDuration, current_duration_);
  481. base::TimeDelta new_duration = pipeline_->GetMediaDuration();
  482. current_duration_ = new_duration;
  483. }
  484. base::TimeDelta PipelineIntegrationTestBase::GetStartTime() {
  485. return demuxer_->GetStartTime();
  486. }
  487. void PipelineIntegrationTestBase::ResetVideoHash() {
  488. DVLOG(1) << __func__;
  489. base::MD5Init(&md5_context_);
  490. }
  491. std::string PipelineIntegrationTestBase::GetVideoHash() {
  492. DCHECK(hashing_enabled_);
  493. base::MD5Digest digest;
  494. base::MD5Final(&digest, &md5_context_);
  495. return base::MD5DigestToBase16(digest);
  496. }
  497. std::string PipelineIntegrationTestBase::GetAudioHash() {
  498. DCHECK(hashing_enabled_);
  499. if (clockless_playback_)
  500. return clockless_audio_sink_->GetAudioHashForTesting();
  501. return audio_sink_->GetAudioHashForTesting();
  502. }
  503. base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() {
  504. DCHECK(clockless_playback_);
  505. return clockless_audio_sink_->render_time();
  506. }
  507. PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
  508. TestMediaSource* source) {
  509. return StartPipelineWithMediaSource(source, kNormal, nullptr);
  510. }
  511. PipelineStatus PipelineIntegrationTestBase::StartPipelineWithEncryptedMedia(
  512. TestMediaSource* source,
  513. FakeEncryptedMedia* encrypted_media) {
  514. return StartPipelineWithMediaSource(source, kNormal, encrypted_media);
  515. }
  516. PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
  517. TestMediaSource* source,
  518. uint8_t test_type,
  519. CreateAudioDecodersCB prepend_audio_decoders_cb) {
  520. prepend_audio_decoders_cb_ = prepend_audio_decoders_cb;
  521. return StartPipelineWithMediaSource(source, test_type, nullptr);
  522. }
  523. PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
  524. TestMediaSource* source,
  525. uint8_t test_type,
  526. FakeEncryptedMedia* encrypted_media) {
  527. ParseTestTypeFlags(test_type);
  528. if (fuzzing_) {
  529. EXPECT_CALL(*source, InitSegmentReceivedMock(_)).Times(AnyNumber());
  530. EXPECT_CALL(*source, OnParseWarningMock(_)).Times(AnyNumber());
  531. } else if (!(test_type & kExpectDemuxerFailure)) {
  532. EXPECT_CALL(*source, InitSegmentReceivedMock(_)).Times(AtLeast(1));
  533. }
  534. EXPECT_CALL(*this, OnMetadata(_))
  535. .Times(AtMost(1))
  536. .WillRepeatedly(SaveArg<0>(&metadata_));
  537. EXPECT_CALL(*this, OnBufferingStateChange(_, _)).Times(AnyNumber());
  538. EXPECT_CALL(*this, OnDurationChange()).Times(AnyNumber());
  539. EXPECT_CALL(*this, OnVideoNaturalSizeChange(_)).Times(AnyNumber());
  540. EXPECT_CALL(*this, OnVideoOpacityChange(_)).Times(AtMost(1));
  541. EXPECT_CALL(*this, OnVideoFrameRateChange(_)).Times(AnyNumber());
  542. EXPECT_CALL(*this, OnAudioPipelineInfoChange(_)).Times(AnyNumber());
  543. EXPECT_CALL(*this, OnVideoPipelineInfoChange(_)).Times(AnyNumber());
  544. base::RunLoop run_loop;
  545. source->set_demuxer_failure_cb(
  546. base::BindRepeating(&PipelineIntegrationTestBase::OnStatusCallback,
  547. base::Unretained(this), run_loop.QuitClosure()));
  548. demuxer_ = source->GetDemuxer();
  549. // DemuxerStreams may signal config changes.
  550. // Config change tests should set more specific expectations about the number
  551. // of calls.
  552. EXPECT_CALL(*this, OnAudioConfigChange(_)).Times(AnyNumber());
  553. EXPECT_CALL(*this, OnVideoConfigChange(_)).Times(AnyNumber());
  554. if (encrypted_media) {
  555. EXPECT_CALL(*this, DecryptorAttached(true));
  556. // Encrypted content used but keys provided in advance, so this is
  557. // never called.
  558. EXPECT_CALL(*this, OnWaiting(WaitingReason::kNoDecryptionKey)).Times(0);
  559. pipeline_->SetCdm(
  560. encrypted_media->GetCdmContext(),
  561. base::BindOnce(&PipelineIntegrationTestBase::DecryptorAttached,
  562. base::Unretained(this)));
  563. } else {
  564. // Encrypted content not used, so this is never called.
  565. EXPECT_CALL(*this, OnWaiting(WaitingReason::kNoDecryptionKey)).Times(0);
  566. }
  567. pipeline_->Start(
  568. Pipeline::StartType::kNormal, demuxer_.get(), this,
  569. base::BindOnce(&PipelineIntegrationTestBase::OnStatusCallback,
  570. base::Unretained(this), run_loop.QuitClosure()));
  571. if (encrypted_media) {
  572. source->set_encrypted_media_init_data_cb(
  573. base::BindRepeating(&FakeEncryptedMedia::OnEncryptedMediaInitData,
  574. base::Unretained(encrypted_media)));
  575. }
  576. RunUntilQuitOrEndedOrError(&run_loop);
  577. for (auto* stream : demuxer_->GetAllStreams()) {
  578. EXPECT_TRUE(stream->SupportsConfigChanges());
  579. }
  580. return pipeline_status_;
  581. }
  582. void PipelineIntegrationTestBase::RunUntilQuitOrError(base::RunLoop* run_loop) {
  583. // We always install an error handler to avoid test hangs.
  584. on_error_closure_ = run_loop->QuitClosure();
  585. run_loop->Run();
  586. on_ended_closure_ = base::OnceClosure();
  587. on_error_closure_ = base::OnceClosure();
  588. task_environment_.RunUntilIdle();
  589. }
  590. void PipelineIntegrationTestBase::RunUntilQuitOrEndedOrError(
  591. base::RunLoop* run_loop) {
  592. DCHECK(on_ended_closure_.is_null());
  593. DCHECK(on_error_closure_.is_null());
  594. on_ended_closure_ = run_loop->QuitClosure();
  595. RunUntilQuitOrError(run_loop);
  596. }
  597. } // namespace media