web_engine_audio_renderer_test.cc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. // Copyright 2021 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 "fuchsia_web/webengine/renderer/web_engine_audio_renderer.h"
  5. #include <fuchsia/media/audio/cpp/fidl_test_base.h>
  6. #include <fuchsia/media/cpp/fidl_test_base.h>
  7. #include <lib/fidl/cpp/binding.h>
  8. #include "base/containers/queue.h"
  9. #include "base/fuchsia/fuchsia_logging.h"
  10. #include "base/logging.h"
  11. #include "base/test/bind.h"
  12. #include "base/test/task_environment.h"
  13. #include "base/threading/thread_task_runner_handle.h"
  14. #include "base/time/time.h"
  15. #include "media/base/cdm_context.h"
  16. #include "media/base/decoder_buffer.h"
  17. #include "media/base/renderer_client.h"
  18. #include "media/fuchsia/cdm/fuchsia_cdm_context.h"
  19. #include "media/fuchsia/common/passthrough_sysmem_buffer_stream.h"
  20. #include "media/fuchsia/common/sysmem_client.h"
  21. #include "testing/gtest/include/gtest/gtest.h"
  22. #include "third_party/abseil-cpp/absl/types/optional.h"
  23. namespace {
  24. constexpr int kDefaultSampleRate = 48000;
  25. constexpr base::TimeDelta kPacketDuration = base::Milliseconds(20);
  26. constexpr base::TimeDelta kMinLeadTime = base::Milliseconds(100);
  27. constexpr base::TimeDelta kMaxLeadTime = base::Milliseconds(500);
  28. const base::TimeDelta kTimeStep = base::Milliseconds(2);
  29. class TestDemuxerStream : public media::DemuxerStream {
  30. public:
  31. struct ReadResult {
  32. explicit ReadResult(scoped_refptr<media::DecoderBuffer> buffer)
  33. : buffer(buffer) {}
  34. explicit ReadResult(const media::AudioDecoderConfig& config)
  35. : config(config) {}
  36. absl::optional<media::AudioDecoderConfig> config;
  37. scoped_refptr<media::DecoderBuffer> buffer;
  38. };
  39. explicit TestDemuxerStream(const media::AudioDecoderConfig& config)
  40. : config_(config) {}
  41. ~TestDemuxerStream() override {}
  42. void QueueReadResult(ReadResult read_result) {
  43. CHECK(read_result.config.has_value() == !read_result.buffer);
  44. read_queue_.push(std::move(read_result));
  45. SatisfyRead();
  46. }
  47. void DiscardQueueAndAbortRead() {
  48. while (!read_queue_.empty())
  49. read_queue_.pop();
  50. if (read_cb_)
  51. std::move(read_cb_).Run(kAborted, nullptr);
  52. }
  53. bool is_read_pending() const { return !!read_cb_; }
  54. // DemuxerStream implementation.
  55. void Read(ReadCB read_cb) override {
  56. read_cb_ = std::move(read_cb);
  57. SatisfyRead();
  58. }
  59. media::AudioDecoderConfig audio_decoder_config() override { return config_; }
  60. media::VideoDecoderConfig video_decoder_config() override {
  61. NOTREACHED();
  62. return media::VideoDecoderConfig();
  63. }
  64. Type type() const override { return AUDIO; }
  65. media::StreamLiveness liveness() const override {
  66. return media::StreamLiveness::kRecorded;
  67. }
  68. bool SupportsConfigChanges() override { return true; }
  69. private:
  70. void SatisfyRead() {
  71. if (read_queue_.empty() || !read_cb_)
  72. return;
  73. auto result = std::move(read_queue_.front());
  74. read_queue_.pop();
  75. Status status;
  76. if (result.config) {
  77. config_ = result.config.value();
  78. status = kConfigChanged;
  79. } else {
  80. status = kOk;
  81. }
  82. std::move(read_cb_).Run(status, result.buffer);
  83. }
  84. media::AudioDecoderConfig config_;
  85. ReadCB read_cb_;
  86. base::queue<ReadResult> read_queue_;
  87. };
  88. class TestStreamSink : public fuchsia::media::testing::StreamSink_TestBase {
  89. public:
  90. TestStreamSink(
  91. std::vector<zx::vmo> buffers,
  92. fuchsia::media::AudioStreamType stream_type,
  93. std::unique_ptr<fuchsia::media::Compression> compression,
  94. fidl::InterfaceRequest<fuchsia::media::StreamSink> stream_sink_request)
  95. : binding_(this, std::move(stream_sink_request)),
  96. buffers_(std::move(buffers)),
  97. stream_type_(std::move(stream_type)),
  98. compression_(std::move(compression)) {}
  99. const std::vector<zx::vmo>& buffers() const { return buffers_; }
  100. const fuchsia::media::AudioStreamType& stream_type() const {
  101. return stream_type_;
  102. }
  103. const fuchsia::media::Compression* compression() const {
  104. return compression_.get();
  105. }
  106. std::vector<fuchsia::media::StreamPacket>* received_packets() {
  107. return &received_packets_;
  108. }
  109. std::vector<fuchsia::media::StreamPacket>* discarded_packets() {
  110. return &discarded_packets_;
  111. }
  112. bool received_end_of_stream() const { return received_end_of_stream_; }
  113. // fuchsia::media::StreamSink overrides.
  114. void SendPacket(fuchsia::media::StreamPacket packet,
  115. SendPacketCallback callback) override {
  116. EXPECT_FALSE(received_end_of_stream_);
  117. received_packets_.push_back(std::move(packet));
  118. callback();
  119. }
  120. void EndOfStream() override {
  121. EXPECT_FALSE(received_end_of_stream_);
  122. received_end_of_stream_ = true;
  123. }
  124. void DiscardAllPackets(DiscardAllPacketsCallback callback) override {
  125. DiscardAllPacketsNoReply();
  126. received_end_of_stream_ = false;
  127. callback();
  128. }
  129. void DiscardAllPacketsNoReply() override {
  130. std::move(std::begin(received_packets_), std::end(received_packets_),
  131. std::back_inserter(discarded_packets_));
  132. received_packets_.clear();
  133. }
  134. // Other methods are not expected to be called.
  135. void NotImplemented_(const std::string& name) final {
  136. FAIL() << ": " << name;
  137. }
  138. private:
  139. fidl::Binding<fuchsia::media::StreamSink> binding_;
  140. std::vector<zx::vmo> buffers_;
  141. fuchsia::media::AudioStreamType stream_type_;
  142. std::unique_ptr<fuchsia::media::Compression> compression_;
  143. std::vector<fuchsia::media::StreamPacket> received_packets_;
  144. std::vector<fuchsia::media::StreamPacket> discarded_packets_;
  145. bool received_end_of_stream_ = false;
  146. };
  147. class TestAudioConsumer
  148. : public fuchsia::media::testing::AudioConsumer_TestBase,
  149. public fuchsia::media::audio::testing::VolumeControl_TestBase {
  150. public:
  151. explicit TestAudioConsumer(
  152. fidl::InterfaceRequest<fuchsia::media::AudioConsumer> request)
  153. : binding_(this, std::move(request)), volume_control_binding_(this) {}
  154. std::unique_ptr<TestStreamSink> TakeStreamSink() {
  155. return std::move(stream_sink_);
  156. }
  157. std::unique_ptr<TestStreamSink> WaitStreamSinkConnected() {
  158. if (!stream_sink_) {
  159. base::RunLoop run_loop;
  160. wait_stream_sink_created_loop_ = &run_loop;
  161. run_loop.Run();
  162. wait_stream_sink_created_loop_ = nullptr;
  163. }
  164. EXPECT_TRUE(stream_sink_);
  165. return TakeStreamSink();
  166. }
  167. void WaitStarted() {
  168. if (started_)
  169. return;
  170. base::RunLoop run_loop;
  171. wait_started_loop_ = &run_loop;
  172. run_loop.Run();
  173. wait_started_loop_ = nullptr;
  174. EXPECT_TRUE(started_);
  175. }
  176. void UpdateStatus(absl::optional<base::TimeTicks> reference_time,
  177. absl::optional<base::TimeDelta> media_time) {
  178. fuchsia::media::AudioConsumerStatus status;
  179. if (reference_time) {
  180. CHECK(media_time);
  181. fuchsia::media::TimelineFunction timeline;
  182. timeline.reference_time = reference_time->ToZxTime();
  183. timeline.subject_time = media_time->ToZxDuration();
  184. timeline.reference_delta = 1000;
  185. timeline.subject_delta = static_cast<int>(playback_rate_ * 1000.0);
  186. status.set_presentation_timeline(std::move(timeline));
  187. }
  188. status.set_min_lead_time(kMinLeadTime.ToZxDuration());
  189. status.set_max_lead_time(kMaxLeadTime.ToZxDuration());
  190. status_update_ = std::move(status);
  191. if (status_callback_)
  192. CallStatusCallback();
  193. }
  194. void SignalEndOfStream() { binding_.events().OnEndOfStream(); }
  195. bool started() const { return started_; }
  196. base::TimeDelta start_media_time() const { return start_media_time_; }
  197. float playback_rate() const { return playback_rate_; }
  198. float volume() const { return volume_; }
  199. // fuchsia::media::AudioConsumer overrides.
  200. void CreateStreamSink(
  201. std::vector<zx::vmo> buffers,
  202. fuchsia::media::AudioStreamType stream_type,
  203. std::unique_ptr<fuchsia::media::Compression> compression,
  204. fidl::InterfaceRequest<fuchsia::media::StreamSink> stream_sink_request)
  205. override {
  206. create_stream_sink_called_ = true;
  207. stream_sink_ = std::make_unique<TestStreamSink>(
  208. std::move(buffers), std::move(stream_type), std::move(compression),
  209. std::move(stream_sink_request));
  210. if (wait_stream_sink_created_loop_)
  211. wait_stream_sink_created_loop_->Quit();
  212. }
  213. void Start(fuchsia::media::AudioConsumerStartFlags flags,
  214. int64_t reference_time,
  215. int64_t media_time) override {
  216. EXPECT_TRUE(create_stream_sink_called_);
  217. EXPECT_FALSE(started_);
  218. EXPECT_EQ(reference_time, fuchsia::media::NO_TIMESTAMP);
  219. started_ = true;
  220. start_media_time_ = base::TimeDelta::FromZxDuration(media_time);
  221. if (wait_started_loop_)
  222. wait_started_loop_->Quit();
  223. }
  224. void Stop() override {
  225. EXPECT_TRUE(started_);
  226. started_ = false;
  227. }
  228. void SetRate(float rate) override { playback_rate_ = rate; }
  229. void BindVolumeControl(
  230. fidl::InterfaceRequest<fuchsia::media::audio::VolumeControl>
  231. volume_control_request) override {
  232. volume_control_binding_.Bind(std::move(volume_control_request));
  233. }
  234. void WatchStatus(WatchStatusCallback callback) override {
  235. EXPECT_FALSE(!!status_callback_);
  236. status_callback_ = std::move(callback);
  237. if (status_update_) {
  238. CallStatusCallback();
  239. }
  240. }
  241. // fuchsia::media::audio::VolumeControl overrides.
  242. void SetVolume(float volume) override { volume_ = volume; }
  243. // Other methods are not expected to be called.
  244. void NotImplemented_(const std::string& name) final {
  245. FAIL() << ": " << name;
  246. }
  247. private:
  248. void CallStatusCallback() {
  249. EXPECT_TRUE(status_callback_);
  250. EXPECT_TRUE(status_update_);
  251. std::move(status_callback_)(std::move(status_update_.value()));
  252. status_callback_ = {};
  253. status_update_ = absl::nullopt;
  254. }
  255. fidl::Binding<fuchsia::media::AudioConsumer> binding_;
  256. fidl::Binding<fuchsia::media::audio::VolumeControl> volume_control_binding_;
  257. std::unique_ptr<TestStreamSink> stream_sink_;
  258. base::RunLoop* wait_stream_sink_created_loop_ = nullptr;
  259. base::RunLoop* wait_started_loop_ = nullptr;
  260. bool create_stream_sink_called_ = false;
  261. WatchStatusCallback status_callback_;
  262. absl::optional<fuchsia::media::AudioConsumerStatus> status_update_;
  263. bool started_ = false;
  264. base::TimeDelta start_media_time_;
  265. float playback_rate_ = 1.0;
  266. float volume_ = 1.0;
  267. };
  268. class TestRendererClient : public media::RendererClient {
  269. public:
  270. TestRendererClient() = default;
  271. ~TestRendererClient() {
  272. EXPECT_EQ(expected_error_, media::PIPELINE_OK);
  273. EXPECT_FALSE(expect_eos_);
  274. }
  275. void ExpectError(media::PipelineStatus expected_error) {
  276. EXPECT_EQ(expected_error_, media::PIPELINE_OK);
  277. expected_error_ = expected_error;
  278. }
  279. void ExpectEos() {
  280. EXPECT_FALSE(expect_eos_);
  281. expect_eos_ = true;
  282. }
  283. media::BufferingState buffering_state() const { return buffering_state_; }
  284. absl::optional<media::AudioDecoderConfig> last_config_change() const {
  285. return last_config_change_;
  286. }
  287. // RendererClient implementation.
  288. void OnError(media::PipelineStatus status) override {
  289. EXPECT_EQ(status, expected_error_);
  290. EXPECT_FALSE(have_error_);
  291. have_error_ = true;
  292. expected_error_ = media::PIPELINE_OK;
  293. }
  294. void OnFallback(media::PipelineStatus status) override {}
  295. void OnEnded() override {
  296. EXPECT_TRUE(expect_eos_);
  297. expect_eos_ = false;
  298. }
  299. void OnStatisticsUpdate(const media::PipelineStatistics& stats) override {
  300. bytes_decoded_ += stats.audio_bytes_decoded;
  301. }
  302. void OnBufferingStateChange(
  303. media::BufferingState state,
  304. media::BufferingStateChangeReason reason) override {
  305. buffering_state_ = state;
  306. }
  307. void OnWaiting(media::WaitingReason reason) override {}
  308. void OnAudioConfigChange(const media::AudioDecoderConfig& config) override {
  309. last_config_change_ = config;
  310. }
  311. void OnVideoConfigChange(const media::VideoDecoderConfig& config) override {
  312. FAIL();
  313. }
  314. void OnVideoNaturalSizeChange(const gfx::Size& size) override { FAIL(); }
  315. void OnVideoOpacityChange(bool opaque) override { FAIL(); }
  316. void OnVideoFrameRateChange(absl::optional<int> fps) override { FAIL(); }
  317. private:
  318. media::PipelineStatus expected_error_ = media::PIPELINE_OK;
  319. bool have_error_ = false;
  320. bool expect_eos_ = false;
  321. media::BufferingState buffering_state_ = media::BUFFERING_HAVE_NOTHING;
  322. size_t bytes_decoded_ = 0;
  323. absl::optional<media::AudioDecoderConfig> last_config_change_;
  324. };
  325. // media::SysmemBufferStream that asynchronously decouples buffer production
  326. // from buffer consumption. Used to simulate stream decryptor.
  327. class AsyncSysmemBufferStream : public media::SysmemBufferStream {
  328. public:
  329. AsyncSysmemBufferStream();
  330. ~AsyncSysmemBufferStream() override;
  331. AsyncSysmemBufferStream(const AsyncSysmemBufferStream&) = delete;
  332. AsyncSysmemBufferStream& operator=(const AsyncSysmemBufferStream&) = delete;
  333. // media::SysmemBufferStream implementation:
  334. void Initialize(Sink* sink,
  335. size_t min_buffer_size,
  336. size_t min_buffer_count) override;
  337. void EnqueueBuffer(scoped_refptr<media::DecoderBuffer> buffer) override;
  338. void Reset() override;
  339. private:
  340. void DoEnqueueBuffer(scoped_refptr<media::DecoderBuffer> buffer);
  341. media::SysmemAllocatorClient sysmem_allocator_;
  342. media::PassthroughSysmemBufferStream passthrough_stream_;
  343. bool is_at_end_of_stream_ = false;
  344. base::WeakPtrFactory<AsyncSysmemBufferStream> weak_factory_{this};
  345. };
  346. AsyncSysmemBufferStream::AsyncSysmemBufferStream()
  347. : sysmem_allocator_("AsyncSysmemBufferStream"),
  348. passthrough_stream_(&sysmem_allocator_) {}
  349. AsyncSysmemBufferStream::~AsyncSysmemBufferStream() = default;
  350. void AsyncSysmemBufferStream::Initialize(Sink* sink,
  351. size_t min_buffer_size,
  352. size_t min_buffer_count) {
  353. passthrough_stream_.Initialize(sink, min_buffer_size, min_buffer_count);
  354. }
  355. void AsyncSysmemBufferStream::EnqueueBuffer(
  356. scoped_refptr<media::DecoderBuffer> buffer) {
  357. if (buffer->end_of_stream()) {
  358. EXPECT_FALSE(is_at_end_of_stream_);
  359. is_at_end_of_stream_ = true;
  360. }
  361. base::ThreadTaskRunnerHandle::Get()->PostTask(
  362. FROM_HERE, base::BindOnce(&AsyncSysmemBufferStream::DoEnqueueBuffer,
  363. weak_factory_.GetWeakPtr(), std::move(buffer)));
  364. }
  365. void AsyncSysmemBufferStream::Reset() {
  366. passthrough_stream_.Reset();
  367. // Drop pending DoEnqueueBuffer tasks.
  368. weak_factory_.InvalidateWeakPtrs();
  369. is_at_end_of_stream_ = false;
  370. }
  371. void AsyncSysmemBufferStream::DoEnqueueBuffer(
  372. scoped_refptr<media::DecoderBuffer> buffer) {
  373. passthrough_stream_.EnqueueBuffer(std::move(buffer));
  374. }
  375. class TestFuchsiaCdmContext : public media::CdmContext,
  376. public media::FuchsiaCdmContext {
  377. public:
  378. // CdmContext overrides.
  379. media::FuchsiaCdmContext* GetFuchsiaCdmContext() override { return this; }
  380. // media::FuchsiaCdmContext implementation.
  381. std::unique_ptr<media::SysmemBufferStream> CreateStreamDecryptor(
  382. bool secure_mode) override {
  383. ++num_decryptors_;
  384. return std::make_unique<AsyncSysmemBufferStream>();
  385. }
  386. size_t num_decryptors() { return num_decryptors_; }
  387. private:
  388. size_t num_decryptors_ = 0;
  389. };
  390. } // namespace
  391. class WebEngineAudioRendererTestBase : public testing::Test {
  392. public:
  393. WebEngineAudioRendererTestBase() = default;
  394. ~WebEngineAudioRendererTestBase() override = default;
  395. void CreateUninitializedRenderer();
  396. void InitializeRenderer();
  397. void CreateAndInitializeRenderer();
  398. void ProduceDemuxerPacket(base::TimeDelta duration);
  399. void FillDemuxerStream(base::TimeDelta end_pos);
  400. void FillBuffer();
  401. void StartPlayback(base::TimeDelta start_time = base::TimeDelta());
  402. void CheckGetWallClockTimes(absl::optional<base::TimeDelta> media_timestamp,
  403. base::TimeTicks expected_wall_clock,
  404. bool is_time_moving);
  405. void TestPcmStream(media::SampleFormat sample_format,
  406. size_t bytes_per_sample_input,
  407. fuchsia::media::AudioSampleFormat fuchsia_sample_format,
  408. size_t bytes_per_sample_output);
  409. // Starts playback from `start_time` at the specified `playback_rate` and
  410. // verifies that the clock works correctly.
  411. void StartPlaybackAndVerifyClock(base::TimeDelta start_time,
  412. float playback_rate);
  413. // Returns initial config for the `demuxer_stream_`.
  414. virtual media::AudioDecoderConfig GetStreamConfig() = 0;
  415. protected:
  416. base::test::SingleThreadTaskEnvironment task_environment_{
  417. base::test::SingleThreadTaskEnvironment::MainThreadType::IO,
  418. base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  419. TestFuchsiaCdmContext cdm_context_;
  420. std::unique_ptr<TestAudioConsumer> audio_consumer_;
  421. std::unique_ptr<TestStreamSink> stream_sink_;
  422. std::unique_ptr<TestDemuxerStream> demuxer_stream_;
  423. TestRendererClient client_;
  424. std::unique_ptr<media::AudioRenderer> audio_renderer_;
  425. media::TimeSource* time_source_;
  426. base::TimeDelta demuxer_stream_pos_;
  427. };
  428. void WebEngineAudioRendererTestBase::CreateUninitializedRenderer() {
  429. fidl::InterfaceHandle<fuchsia::media::AudioConsumer> audio_consumer_handle;
  430. audio_consumer_ =
  431. std::make_unique<TestAudioConsumer>(audio_consumer_handle.NewRequest());
  432. audio_renderer_ = std::make_unique<WebEngineAudioRenderer>(
  433. /*media_log=*/nullptr, std::move(audio_consumer_handle));
  434. time_source_ = audio_renderer_->GetTimeSource();
  435. }
  436. void WebEngineAudioRendererTestBase::InitializeRenderer() {
  437. if (!demuxer_stream_) {
  438. demuxer_stream_ = std::make_unique<TestDemuxerStream>(GetStreamConfig());
  439. }
  440. base::RunLoop run_loop;
  441. media::PipelineStatus pipeline_status;
  442. audio_renderer_->Initialize(
  443. demuxer_stream_.get(), &cdm_context_, &client_,
  444. base::BindLambdaForTesting(
  445. [&run_loop, &pipeline_status](media::PipelineStatus s) {
  446. pipeline_status = s;
  447. run_loop.Quit();
  448. }));
  449. run_loop.Run();
  450. ASSERT_EQ(pipeline_status, media::PIPELINE_OK);
  451. audio_consumer_->UpdateStatus(absl::nullopt, absl::nullopt);
  452. task_environment_.RunUntilIdle();
  453. }
  454. void WebEngineAudioRendererTestBase::CreateAndInitializeRenderer() {
  455. CreateUninitializedRenderer();
  456. InitializeRenderer();
  457. }
  458. void WebEngineAudioRendererTestBase::ProduceDemuxerPacket(
  459. base::TimeDelta duration) {
  460. // Create a dummy packet that contains just 1 byte.
  461. const size_t kBufferSize = 1;
  462. scoped_refptr<media::DecoderBuffer> buffer =
  463. new media::DecoderBuffer(kBufferSize);
  464. buffer->set_timestamp(demuxer_stream_pos_);
  465. buffer->set_duration(duration);
  466. demuxer_stream_pos_ += duration;
  467. demuxer_stream_->QueueReadResult(TestDemuxerStream::ReadResult(buffer));
  468. }
  469. void WebEngineAudioRendererTestBase::FillDemuxerStream(
  470. base::TimeDelta end_pos) {
  471. EXPECT_LT(demuxer_stream_pos_, end_pos);
  472. while (demuxer_stream_pos_ < end_pos) {
  473. ProduceDemuxerPacket(kPacketDuration);
  474. }
  475. }
  476. void WebEngineAudioRendererTestBase::FillBuffer() {
  477. if (!stream_sink_) {
  478. stream_sink_ = audio_consumer_->WaitStreamSinkConnected();
  479. }
  480. // The renderer expects one extra packet after reaching kMinLeadTime to get
  481. // to the media::BUFFERING_HAVE_ENOUGH state.
  482. const size_t kNumPackets = kMinLeadTime / kPacketDuration + 1;
  483. for (size_t i = 0; i < kNumPackets; ++i) {
  484. ProduceDemuxerPacket(kPacketDuration);
  485. }
  486. task_environment_.RunUntilIdle();
  487. // Renderer should not start reading demuxer untile StartPlaying() is
  488. // called.
  489. EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_NOTHING);
  490. EXPECT_EQ(stream_sink_->received_packets()->size(), 0U);
  491. // Start playback. The renderer should push queued packets to the
  492. // AudioConsumer and updated buffering state.
  493. audio_renderer_->StartPlaying();
  494. task_environment_.RunUntilIdle();
  495. EXPECT_EQ(stream_sink_->received_packets()->size(), kNumPackets);
  496. EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_ENOUGH);
  497. }
  498. void WebEngineAudioRendererTestBase::StartPlayback(base::TimeDelta start_time) {
  499. EXPECT_FALSE(audio_consumer_->started());
  500. time_source_->SetMediaTime(start_time);
  501. ASSERT_NO_FATAL_FAILURE(FillBuffer());
  502. time_source_->StartTicking();
  503. task_environment_.RunUntilIdle();
  504. EXPECT_TRUE(audio_consumer_->started());
  505. EXPECT_EQ(audio_consumer_->start_media_time(), start_time);
  506. audio_consumer_->UpdateStatus(base::TimeTicks::Now(), start_time);
  507. task_environment_.RunUntilIdle();
  508. }
  509. void WebEngineAudioRendererTestBase::CheckGetWallClockTimes(
  510. absl::optional<base::TimeDelta> media_timestamp,
  511. base::TimeTicks expected_wall_clock,
  512. bool is_time_moving) {
  513. std::vector<base::TimeDelta> media_timestamps;
  514. if (media_timestamp)
  515. media_timestamps.push_back(media_timestamp.value());
  516. std::vector<base::TimeTicks> wall_clock;
  517. bool result = time_source_->GetWallClockTimes(media_timestamps, &wall_clock);
  518. EXPECT_EQ(wall_clock[0], expected_wall_clock);
  519. EXPECT_EQ(result, is_time_moving);
  520. }
  521. void WebEngineAudioRendererTestBase::StartPlaybackAndVerifyClock(
  522. base::TimeDelta start_time,
  523. float playback_rate) {
  524. time_source_->SetMediaTime(start_time);
  525. time_source_->SetPlaybackRate(playback_rate);
  526. demuxer_stream_pos_ = start_time;
  527. ASSERT_NO_FATAL_FAILURE(FillBuffer());
  528. EXPECT_FALSE(audio_consumer_->started());
  529. time_source_->StartTicking();
  530. task_environment_.RunUntilIdle();
  531. EXPECT_TRUE(audio_consumer_->started());
  532. // Start position should be reported before updated status is received.
  533. EXPECT_EQ(time_source_->CurrentMediaTime(), start_time);
  534. task_environment_.FastForwardBy(kTimeStep);
  535. EXPECT_EQ(time_source_->CurrentMediaTime(), start_time);
  536. CheckGetWallClockTimes(absl::nullopt, base::TimeTicks(), false);
  537. CheckGetWallClockTimes(start_time + kTimeStep,
  538. base::TimeTicks::Now() + kTimeStep, false);
  539. // MediaTime will start moving once AudioConsumer updates timeline.
  540. const base::TimeDelta kStartDelay = base::Milliseconds(3);
  541. base::TimeTicks start_wall_clock = base::TimeTicks::Now() + kStartDelay;
  542. audio_consumer_->UpdateStatus(start_wall_clock, start_time);
  543. task_environment_.RunUntilIdle();
  544. EXPECT_EQ(time_source_->CurrentMediaTime(),
  545. start_time - kStartDelay * playback_rate);
  546. task_environment_.FastForwardBy(kTimeStep);
  547. EXPECT_EQ(time_source_->CurrentMediaTime(),
  548. start_time + (-kStartDelay + kTimeStep) * playback_rate);
  549. CheckGetWallClockTimes(absl::nullopt, base::TimeTicks::Now(), true);
  550. CheckGetWallClockTimes(start_time + kTimeStep,
  551. start_wall_clock + kTimeStep / playback_rate, true);
  552. CheckGetWallClockTimes(start_time + 2 * kTimeStep,
  553. start_wall_clock + 2.0 * kTimeStep / playback_rate,
  554. true);
  555. }
  556. void WebEngineAudioRendererTestBase::TestPcmStream(
  557. media::SampleFormat sample_format,
  558. size_t bytes_per_sample_input,
  559. fuchsia::media::AudioSampleFormat fuchsia_sample_format,
  560. size_t bytes_per_sample_output) {
  561. media::AudioDecoderConfig config(
  562. media::AudioCodec::kPCM, sample_format, media::CHANNEL_LAYOUT_STEREO,
  563. kDefaultSampleRate, {}, media::EncryptionScheme::kUnencrypted);
  564. demuxer_stream_ = std::make_unique<TestDemuxerStream>(config);
  565. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  566. stream_sink_ = audio_consumer_->WaitStreamSinkConnected();
  567. EXPECT_EQ(stream_sink_->stream_type().sample_format, fuchsia_sample_format);
  568. // Create a dummy packet that contains 1 sample.
  569. const size_t kNumSamples = 10;
  570. const size_t kChannels = 2;
  571. size_t input_buffer_size = kNumSamples * kChannels * bytes_per_sample_input;
  572. scoped_refptr<media::DecoderBuffer> buffer =
  573. new media::DecoderBuffer(input_buffer_size);
  574. buffer->set_timestamp(demuxer_stream_pos_);
  575. buffer->set_duration(kPacketDuration);
  576. for (size_t i = 0; i < input_buffer_size; ++i) {
  577. buffer->writable_data()[i] = i;
  578. }
  579. demuxer_stream_->QueueReadResult(TestDemuxerStream::ReadResult(buffer));
  580. // Start playback. The renderer will process the packet queued above.
  581. audio_renderer_->StartPlaying();
  582. task_environment_.RunUntilIdle();
  583. ASSERT_EQ(stream_sink_->received_packets()->size(), 1U);
  584. auto packet = stream_sink_->received_packets()->at(0);
  585. // Read and verify packet content
  586. size_t output_size = kNumSamples * kChannels * bytes_per_sample_output;
  587. EXPECT_EQ(packet.payload_size, output_size);
  588. uint8_t data[output_size];
  589. zx_status_t result = stream_sink_->buffers()[packet.payload_buffer_id].read(
  590. data, 0, output_size);
  591. ZX_CHECK(result == ZX_OK, result);
  592. for (size_t i = 0; i < output_size; ++i) {
  593. size_t pos_within_sample = i % bytes_per_sample_output;
  594. uint8_t expected_value =
  595. (pos_within_sample < bytes_per_sample_input)
  596. ? (i / bytes_per_sample_output * bytes_per_sample_input +
  597. pos_within_sample)
  598. : 0;
  599. EXPECT_EQ(data[i], expected_value);
  600. }
  601. }
  602. struct RendererTestConfig {
  603. bool simulate_fuchsia_cdm;
  604. };
  605. class WebEngineAudioRendererTest
  606. : public WebEngineAudioRendererTestBase,
  607. public testing::WithParamInterface<RendererTestConfig> {
  608. public:
  609. media::AudioDecoderConfig GetStreamConfig() final {
  610. auto encryption_scheme = GetParam().simulate_fuchsia_cdm
  611. ? media::EncryptionScheme::kCenc
  612. : media::EncryptionScheme::kUnencrypted;
  613. return media::AudioDecoderConfig(
  614. media::AudioCodec::kPCM, media::kSampleFormatF32,
  615. media::CHANNEL_LAYOUT_MONO, kDefaultSampleRate, {}, encryption_scheme);
  616. }
  617. };
  618. // Run all WebEngineAudioRendererTests with CDM enabled and disabled.
  619. INSTANTIATE_TEST_SUITE_P(Unencrypted,
  620. WebEngineAudioRendererTest,
  621. testing::Values(RendererTestConfig{false}));
  622. INSTANTIATE_TEST_SUITE_P(Encrypted,
  623. WebEngineAudioRendererTest,
  624. testing::Values(RendererTestConfig{true}));
  625. TEST_P(WebEngineAudioRendererTest, Initialize) {
  626. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  627. }
  628. TEST_P(WebEngineAudioRendererTest, InitializeAndBuffer) {
  629. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  630. ASSERT_NO_FATAL_FAILURE(FillBuffer());
  631. // Extra packets should be sent to AudioConsumer immediately.
  632. stream_sink_->received_packets()->clear();
  633. ProduceDemuxerPacket(base::Milliseconds(10));
  634. task_environment_.RunUntilIdle();
  635. EXPECT_EQ(stream_sink_->received_packets()->size(), 1U);
  636. }
  637. TEST_P(WebEngineAudioRendererTest, StartPlaybackBeforeStreamSinkConnected) {
  638. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  639. // Start playing immediately after initialization. The renderer should wait
  640. // for buffers to be allocated before it starts reading from the demuxer.
  641. audio_renderer_->StartPlaying();
  642. ProduceDemuxerPacket(base::Milliseconds(10));
  643. task_environment_.RunUntilIdle();
  644. stream_sink_ = audio_consumer_->WaitStreamSinkConnected();
  645. task_environment_.RunUntilIdle();
  646. EXPECT_EQ(stream_sink_->received_packets()->size(), 1U);
  647. }
  648. TEST_P(WebEngineAudioRendererTest, StartTicking) {
  649. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  650. ASSERT_NO_FATAL_FAILURE(StartPlaybackAndVerifyClock(
  651. /*start_pos=*/base::Milliseconds(123),
  652. /*playback_rate=*/1.0));
  653. }
  654. TEST_P(WebEngineAudioRendererTest, StartTickingRate1_5) {
  655. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  656. ASSERT_NO_FATAL_FAILURE(StartPlaybackAndVerifyClock(
  657. /*start_pos=*/base::Milliseconds(123),
  658. /*playback_rate=*/1.5));
  659. }
  660. TEST_P(WebEngineAudioRendererTest, StartTickingRate0_5) {
  661. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  662. ASSERT_NO_FATAL_FAILURE(StartPlaybackAndVerifyClock(
  663. /*start_pos=*/base::Milliseconds(123),
  664. /*playback_rate=*/0.5));
  665. }
  666. // Verify that the renderer doesn't send packets more than kMaxLeadTime ahead of
  667. // time.
  668. TEST_P(WebEngineAudioRendererTest, MaxLeadTime) {
  669. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  670. ASSERT_NO_FATAL_FAILURE(FillBuffer());
  671. // Queue packets up to kMaxLeadTime with 10 extra packets. The Renderer
  672. // shouldn't read these extra packets at the end.
  673. FillDemuxerStream(kMaxLeadTime + kPacketDuration * 10);
  674. task_environment_.RunUntilIdle();
  675. // Verify that the renderer has filled the buffer to kMaxLeadTime.
  676. size_t expected_packets = kMaxLeadTime / kPacketDuration;
  677. EXPECT_EQ(expected_packets, stream_sink_->received_packets()->size());
  678. }
  679. TEST_P(WebEngineAudioRendererTest, Seek) {
  680. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  681. constexpr base::TimeDelta kStartPos = base::TimeDelta();
  682. ASSERT_NO_FATAL_FAILURE(StartPlayback(kStartPos));
  683. task_environment_.FastForwardBy(kTimeStep);
  684. time_source_->StopTicking();
  685. demuxer_stream_->DiscardQueueAndAbortRead();
  686. // Media time should be stopped after StopTicking().
  687. EXPECT_EQ(time_source_->CurrentMediaTime(), kStartPos + kTimeStep);
  688. task_environment_.FastForwardBy(kTimeStep);
  689. EXPECT_EQ(time_source_->CurrentMediaTime(), kStartPos + kTimeStep);
  690. // Flush the renderer.
  691. base::RunLoop run_loop;
  692. audio_renderer_->Flush(run_loop.QuitClosure());
  693. run_loop.Run();
  694. // Restart playback from a new position.
  695. const base::TimeDelta kSeekPos = base::Milliseconds(123);
  696. ASSERT_NO_FATAL_FAILURE(StartPlaybackAndVerifyClock(kSeekPos,
  697. /*playback_rate=*/1.0));
  698. ProduceDemuxerPacket(kPacketDuration);
  699. // Verify that old packets were discarded and StreamSink started received
  700. // packets at the correct position.
  701. EXPECT_GT(stream_sink_->discarded_packets()->size(), 0u);
  702. EXPECT_EQ(stream_sink_->received_packets()->at(0).pts,
  703. kSeekPos.ToZxDuration());
  704. }
  705. TEST_F(WebEngineAudioRendererTest, PcmU8Stream) {
  706. TestPcmStream(media::kSampleFormatU8, 1,
  707. fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1);
  708. }
  709. TEST_F(WebEngineAudioRendererTest, PcmS16Stream) {
  710. TestPcmStream(media::kSampleFormatS16, 2,
  711. fuchsia::media::AudioSampleFormat::SIGNED_16, 2);
  712. }
  713. TEST_F(WebEngineAudioRendererTest, PcmS24Stream) {
  714. TestPcmStream(media::kSampleFormatS24, 3,
  715. fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32, 4);
  716. }
  717. TEST_F(WebEngineAudioRendererTest, PcmF32Stream) {
  718. TestPcmStream(media::kSampleFormatF32, 4,
  719. fuchsia::media::AudioSampleFormat::FLOAT, 4);
  720. }
  721. struct ConfigChangeTestConfig {
  722. bool encrypted_head;
  723. bool encrypted_tail;
  724. };
  725. class WebEngineAudioRendererConfgChangeTest
  726. : public WebEngineAudioRendererTestBase,
  727. public testing::WithParamInterface<ConfigChangeTestConfig> {
  728. media::AudioDecoderConfig GetStreamConfig() final {
  729. auto encryption_scheme = GetParam().encrypted_head
  730. ? media::EncryptionScheme::kCenc
  731. : media::EncryptionScheme::kUnencrypted;
  732. return media::AudioDecoderConfig(
  733. media::AudioCodec::kPCM, media::kSampleFormatF32,
  734. media::CHANNEL_LAYOUT_MONO, kDefaultSampleRate, {}, encryption_scheme);
  735. }
  736. };
  737. // Run all WebEngineAudioRendererTests with CDM enabled and disabled.
  738. INSTANTIATE_TEST_SUITE_P(ConfigChange,
  739. WebEngineAudioRendererConfgChangeTest,
  740. testing::Values(ConfigChangeTestConfig{false, false},
  741. ConfigChangeTestConfig{false, true},
  742. ConfigChangeTestConfig{true, false},
  743. ConfigChangeTestConfig{true, true}));
  744. TEST_P(WebEngineAudioRendererConfgChangeTest, ConfigChange) {
  745. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  746. ASSERT_NO_FATAL_FAILURE(StartPlayback());
  747. const auto kConfigChangePos = base::Seconds(1);
  748. // Queue packets up to kConfigChangePos.
  749. FillDemuxerStream(kConfigChangePos);
  750. // Verify that decryptor was initialized only if the beginning of the stream
  751. // is encrypted.
  752. EXPECT_EQ(cdm_context_.num_decryptors(), GetParam().encrypted_head ? 1U : 0U);
  753. // New Config
  754. const size_t kNewSampleRate = 44100;
  755. const std::vector<uint8_t> kArbitraryExtraData = {1, 2, 3};
  756. auto mew_encryption_scheme = GetParam().encrypted_tail
  757. ? media::EncryptionScheme::kCenc
  758. : media::EncryptionScheme::kUnencrypted;
  759. media::AudioDecoderConfig updated_config(
  760. media::AudioCodec::kOpus, media::kSampleFormatF32,
  761. media::CHANNEL_LAYOUT_STEREO, kNewSampleRate, kArbitraryExtraData,
  762. mew_encryption_scheme);
  763. demuxer_stream_->QueueReadResult(
  764. TestDemuxerStream::ReadResult(updated_config));
  765. // Queue one more packet with the new config.
  766. ProduceDemuxerPacket(kPacketDuration * 2);
  767. task_environment_.FastForwardBy(kConfigChangePos);
  768. // The renderer should have created new StreamSink when config was changed.
  769. auto new_stream_sink = audio_consumer_->WaitStreamSinkConnected();
  770. ASSERT_TRUE(new_stream_sink);
  771. task_environment_.RunUntilIdle();
  772. // Verify that decryptor was re-created if the stream is encrypted after
  773. // the config change.
  774. EXPECT_EQ(cdm_context_.num_decryptors(),
  775. (GetParam().encrypted_head ? 1U : 0U) +
  776. (GetParam().encrypted_tail ? 1U : 0U));
  777. ASSERT_TRUE(client_.last_config_change().has_value());
  778. EXPECT_TRUE(client_.last_config_change()->Matches(updated_config));
  779. EXPECT_EQ(stream_sink_->stream_type().channels, 1U);
  780. EXPECT_EQ(stream_sink_->stream_type().frames_per_second,
  781. static_cast<uint32_t>(kDefaultSampleRate));
  782. EXPECT_EQ(stream_sink_->received_packets()->size(),
  783. kConfigChangePos / kPacketDuration);
  784. EXPECT_EQ(new_stream_sink->stream_type().channels,
  785. static_cast<uint32_t>(updated_config.channels()));
  786. EXPECT_EQ(new_stream_sink->stream_type().frames_per_second, kNewSampleRate);
  787. EXPECT_TRUE(new_stream_sink->compression());
  788. EXPECT_EQ(new_stream_sink->compression()->type,
  789. fuchsia::media::AUDIO_ENCODING_OPUS);
  790. EXPECT_EQ(new_stream_sink->compression()->parameters, kArbitraryExtraData);
  791. EXPECT_EQ(new_stream_sink->received_packets()->size(), 1U);
  792. EXPECT_EQ(new_stream_sink->received_packets()->at(0).pts,
  793. kConfigChangePos.ToZxDuration());
  794. }
  795. TEST_P(WebEngineAudioRendererTest, UpdateTimeline) {
  796. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  797. ASSERT_NO_FATAL_FAILURE(StartPlayback());
  798. FillDemuxerStream(base::Seconds(2));
  799. const auto kTimelineChangePos = base::Seconds(1);
  800. task_environment_.FastForwardBy(kTimelineChangePos);
  801. // Shift the timeline by 2ms.
  802. const auto kMediaDelta = base::Milliseconds(2);
  803. audio_consumer_->UpdateStatus(base::TimeTicks::Now(),
  804. kTimelineChangePos + kMediaDelta);
  805. task_environment_.RunUntilIdle();
  806. EXPECT_EQ(time_source_->CurrentMediaTime(), kTimelineChangePos + kMediaDelta);
  807. task_environment_.FastForwardBy(kTimeStep);
  808. EXPECT_EQ(time_source_->CurrentMediaTime(),
  809. kTimelineChangePos + kMediaDelta + kTimeStep);
  810. }
  811. TEST_P(WebEngineAudioRendererTest, PauseAndResume) {
  812. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  813. ASSERT_NO_FATAL_FAILURE(StartPlayback());
  814. const auto kPauseTimestamp = base::Seconds(1);
  815. const auto kStreamLength = base::Seconds(2);
  816. FillDemuxerStream(kStreamLength);
  817. task_environment_.FastForwardBy(kPauseTimestamp);
  818. // Pause playback by setting playback rate to 0.0.
  819. time_source_->SetPlaybackRate(0.0);
  820. task_environment_.RunUntilIdle();
  821. EXPECT_EQ(audio_consumer_->playback_rate(), 0.0);
  822. task_environment_.FastForwardBy(kTimeStep);
  823. audio_consumer_->UpdateStatus(base::TimeTicks::Now(), kPauseTimestamp);
  824. task_environment_.RunUntilIdle();
  825. const size_t kExpectedQueuedPackets =
  826. (kPauseTimestamp + kMaxLeadTime) / kPacketDuration + 1;
  827. EXPECT_EQ(stream_sink_->received_packets()->size(), kExpectedQueuedPackets);
  828. EXPECT_EQ(time_source_->CurrentMediaTime(), kPauseTimestamp);
  829. // Keep the stream paused for 10 seconds. The Renderer should not be sending
  830. // new packets
  831. task_environment_.FastForwardBy(base::Seconds(10));
  832. EXPECT_EQ(stream_sink_->received_packets()->size(), kExpectedQueuedPackets);
  833. EXPECT_EQ(time_source_->CurrentMediaTime(), kPauseTimestamp);
  834. // Resume playback.
  835. time_source_->SetPlaybackRate(1.0);
  836. task_environment_.RunUntilIdle();
  837. EXPECT_EQ(audio_consumer_->playback_rate(), 1.0);
  838. audio_consumer_->UpdateStatus(base::TimeTicks::Now(), kPauseTimestamp);
  839. task_environment_.RunUntilIdle();
  840. EXPECT_EQ(time_source_->CurrentMediaTime(), kPauseTimestamp);
  841. // The renderer should start sending packets again.
  842. task_environment_.FastForwardBy(kPacketDuration);
  843. EXPECT_EQ(stream_sink_->received_packets()->size(),
  844. kExpectedQueuedPackets + 1);
  845. EXPECT_EQ(time_source_->CurrentMediaTime(),
  846. kPauseTimestamp + kPacketDuration);
  847. }
  848. // Verify that end-of-stream is handled correctly when the renderer is buffered.
  849. TEST_P(WebEngineAudioRendererTest, EndOfStreamBuffered) {
  850. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  851. ASSERT_NO_FATAL_FAILURE(StartPlayback());
  852. const auto kStreamLength = base::Seconds(1);
  853. FillDemuxerStream(kStreamLength);
  854. demuxer_stream_->QueueReadResult(
  855. TestDemuxerStream::ReadResult(media::DecoderBuffer::CreateEOSBuffer()));
  856. // Queue second EOS buffer. The renderer should not read it.
  857. demuxer_stream_->QueueReadResult(
  858. TestDemuxerStream::ReadResult(media::DecoderBuffer::CreateEOSBuffer()));
  859. task_environment_.FastForwardBy(kStreamLength);
  860. EXPECT_EQ(stream_sink_->received_packets()->size(),
  861. kStreamLength / kPacketDuration);
  862. EXPECT_TRUE(stream_sink_->received_end_of_stream());
  863. client_.ExpectEos();
  864. audio_consumer_->SignalEndOfStream();
  865. task_environment_.RunUntilIdle();
  866. }
  867. // Verifies that buffering state is updated after reaching EOS. See
  868. // https://crbug.com/1162503 .
  869. TEST_P(WebEngineAudioRendererTest, EndOfStreamWhenBuffering) {
  870. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  871. stream_sink_ = audio_consumer_->WaitStreamSinkConnected();
  872. // Produce stream shorter than kMinLeadTime.
  873. const auto kStreamLength = kMinLeadTime / 2;
  874. FillDemuxerStream(kStreamLength);
  875. demuxer_stream_->QueueReadResult(
  876. TestDemuxerStream::ReadResult(media::DecoderBuffer::CreateEOSBuffer()));
  877. task_environment_.RunUntilIdle();
  878. // Start playback. The renderer should push queued packets to the
  879. // AudioConsumer and updated buffering state when it reaches EOS.
  880. audio_renderer_->StartPlaying();
  881. task_environment_.RunUntilIdle();
  882. EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_ENOUGH);
  883. EXPECT_TRUE(stream_sink_->received_end_of_stream());
  884. }
  885. TEST_P(WebEngineAudioRendererTest, EndOfStreamStart) {
  886. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  887. stream_sink_ = audio_consumer_->WaitStreamSinkConnected();
  888. // Queue EOS without any preceding packets.
  889. demuxer_stream_->QueueReadResult(
  890. TestDemuxerStream::ReadResult(media::DecoderBuffer::CreateEOSBuffer()));
  891. task_environment_.RunUntilIdle();
  892. // Start playback. The renderer should push queued packets to the
  893. // AudioConsumer and updated buffering state when it reaches EOS.
  894. audio_renderer_->StartPlaying();
  895. task_environment_.RunUntilIdle();
  896. EXPECT_EQ(client_.buffering_state(), media::BUFFERING_HAVE_ENOUGH);
  897. EXPECT_TRUE(stream_sink_->received_end_of_stream());
  898. }
  899. TEST_P(WebEngineAudioRendererTest, SetVolume) {
  900. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  901. audio_renderer_->SetVolume(0.5);
  902. task_environment_.RunUntilIdle();
  903. EXPECT_EQ(audio_consumer_->volume(), 0.5);
  904. }
  905. TEST_P(WebEngineAudioRendererTest, SetVolumeBeforeInitialize) {
  906. ASSERT_NO_FATAL_FAILURE(CreateUninitializedRenderer());
  907. // SetVolume() may be called before media::AudioRenderer is initialized. It
  908. // should still be handled.
  909. audio_renderer_->SetVolume(0.5);
  910. ASSERT_NO_FATAL_FAILURE(InitializeRenderer());
  911. EXPECT_EQ(audio_consumer_->volume(), 0.5);
  912. }
  913. // Verify that the case when StartTicking() is called shortly after
  914. // StartPlaying() is handled correctly. AudioConsumer::Start() should be sent
  915. // only after CreateStreamSink(). See crbug.com/1219147 .
  916. TEST_P(WebEngineAudioRendererTest, PlaybackBeforeSinkCreation) {
  917. demuxer_stream_ = std::make_unique<TestDemuxerStream>(GetStreamConfig());
  918. const auto kStreamLength = base::Milliseconds(100);
  919. FillDemuxerStream(kStreamLength);
  920. demuxer_stream_->QueueReadResult(
  921. TestDemuxerStream::ReadResult(media::DecoderBuffer::CreateEOSBuffer()));
  922. ASSERT_NO_FATAL_FAILURE(CreateAndInitializeRenderer());
  923. // Call StartTicking() shortly after StartPlayback(). At this point sysmem
  924. // buffer allocation hasn't been complete, so AudioConsumer::Start() should be
  925. // delayed until the buffer are allocated.
  926. audio_renderer_->StartPlaying();
  927. time_source_->StartTicking();
  928. // Wait until the stream is started. Start() should be called only after
  929. // StreamSink() is connected and the packets are buffered.
  930. audio_consumer_->WaitStarted();
  931. stream_sink_ = audio_consumer_->TakeStreamSink();
  932. EXPECT_GT(stream_sink_->received_packets()->size(), 0U);
  933. EXPECT_FALSE(stream_sink_->received_end_of_stream());
  934. }