fake_audio_capturer.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 "media/fuchsia/audio/fake_audio_capturer.h"
  5. #include <string.h>
  6. #include "base/bind.h"
  7. #include "base/fuchsia/fuchsia_logging.h"
  8. #include "base/logging.h"
  9. #include "base/notreached.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace media {
  13. FakeAudioCapturer::FakeAudioCapturer(
  14. fidl::InterfaceRequest<fuchsia::media::AudioCapturer> request)
  15. : binding_(this) {
  16. if (request)
  17. Bind(std::move(request));
  18. }
  19. FakeAudioCapturer::~FakeAudioCapturer() = default;
  20. void FakeAudioCapturer::Bind(
  21. fidl::InterfaceRequest<fuchsia::media::AudioCapturer> request) {
  22. binding_.Bind(std::move(request));
  23. }
  24. size_t FakeAudioCapturer::GetPacketSize() const {
  25. return frames_per_packet_ * stream_type_->channels * sizeof(float);
  26. }
  27. void FakeAudioCapturer::SetDataGeneration(DataGeneration data_generation) {
  28. EXPECT_TRUE(!is_active());
  29. data_generation_ = data_generation;
  30. }
  31. void FakeAudioCapturer::SendData(base::TimeTicks timestamp, void* data) {
  32. EXPECT_TRUE(buffer_vmo_);
  33. EXPECT_TRUE(is_active_);
  34. // Find unused packet.
  35. auto it = std::find(packets_usage_.begin(), packets_usage_.end(), false);
  36. // Currently tests don't try to send more than 2 packets and the buffer
  37. // always will have space for at least 2 packets.
  38. EXPECT_TRUE(it != packets_usage_.end());
  39. size_t buffer_index = it - packets_usage_.begin();
  40. size_t buffer_pos = buffer_index * GetPacketSize();
  41. packets_usage_[buffer_index] = true;
  42. // Write data to the shared VMO.
  43. zx_status_t status = buffer_vmo_.write(data, buffer_pos, GetPacketSize());
  44. ZX_CHECK(status == ZX_OK, status);
  45. // Send the new packet.
  46. fuchsia::media::StreamPacket packet;
  47. packet.payload_buffer_id = kBufferId;
  48. packet.pts = timestamp.ToZxTime();
  49. packet.payload_offset = buffer_pos;
  50. packet.payload_size = GetPacketSize();
  51. binding_.events().OnPacketProduced(std::move(packet));
  52. }
  53. // fuchsia::media::AudioCapturer implementation.
  54. void FakeAudioCapturer::SetPcmStreamType(
  55. fuchsia::media::AudioStreamType stream_type) {
  56. EXPECT_TRUE(!stream_type_.has_value());
  57. EXPECT_EQ(stream_type.sample_format,
  58. fuchsia::media::AudioSampleFormat::FLOAT);
  59. stream_type_ = std::move(stream_type);
  60. }
  61. void FakeAudioCapturer::AddPayloadBuffer(uint32_t id, zx::vmo payload_buffer) {
  62. EXPECT_EQ(id, kBufferId);
  63. EXPECT_TRUE(!buffer_vmo_);
  64. EXPECT_TRUE(stream_type_.has_value());
  65. buffer_vmo_ = std::move(payload_buffer);
  66. zx_status_t status = buffer_vmo_.get_size(&buffer_size_);
  67. ZX_CHECK(status == ZX_OK, status);
  68. }
  69. void FakeAudioCapturer::StartAsyncCapture(uint32_t frames_per_packet) {
  70. EXPECT_TRUE(buffer_vmo_);
  71. EXPECT_TRUE(!is_active_);
  72. is_active_ = true;
  73. frames_per_packet_ = frames_per_packet;
  74. size_t num_packets = buffer_size_ / GetPacketSize();
  75. // AudioCapturer protocol requires that we can fit at least 2 packets in the
  76. // buffer in async data_generation.
  77. EXPECT_GE(num_packets, 2U);
  78. packets_usage_.clear();
  79. packets_usage_.resize(num_packets, false);
  80. if (data_generation_ == DataGeneration::AUTOMATIC) {
  81. start_timestamp_ = base::TimeTicks::Now();
  82. ProducePackets();
  83. }
  84. }
  85. void FakeAudioCapturer::StopAsyncCaptureNoReply() {
  86. is_active_ = false;
  87. timer_.Stop();
  88. }
  89. void FakeAudioCapturer::ReleasePacket(fuchsia::media::StreamPacket packet) {
  90. EXPECT_EQ(packet.payload_buffer_id, kBufferId);
  91. EXPECT_EQ(packet.payload_offset % GetPacketSize(), 0U);
  92. size_t buffer_index = packet.payload_offset / GetPacketSize();
  93. EXPECT_LT(buffer_index, packets_usage_.size());
  94. EXPECT_TRUE(packets_usage_[buffer_index]);
  95. packets_usage_[buffer_index] = false;
  96. }
  97. void FakeAudioCapturer::NotImplemented_(const std::string& name) {
  98. ADD_FAILURE() << "Unexpected FakeAudioCapturer call: " << name;
  99. }
  100. void FakeAudioCapturer::ProducePackets() {
  101. if (!binding_.is_bound()) {
  102. return;
  103. }
  104. char data[GetPacketSize()];
  105. memset(data, 0, GetPacketSize());
  106. SendData(start_timestamp_ + base::Seconds(1) * packet_index_ *
  107. frames_per_packet_ /
  108. stream_type_->frames_per_second,
  109. data);
  110. packet_index_++;
  111. timer_.Start(FROM_HERE,
  112. start_timestamp_ +
  113. base::Seconds(1) * packet_index_ * frames_per_packet_ /
  114. stream_type_->frames_per_second -
  115. base::TimeTicks::Now(),
  116. this, &FakeAudioCapturer::ProducePackets);
  117. }
  118. FakeAudioCapturerFactory::FakeAudioCapturerFactory(
  119. sys::OutgoingDirectory* outgoing_directory)
  120. : binding_(outgoing_directory, this) {}
  121. FakeAudioCapturerFactory::~FakeAudioCapturerFactory() = default;
  122. std::unique_ptr<FakeAudioCapturer> FakeAudioCapturerFactory::TakeCapturer() {
  123. if (capturers_.empty())
  124. return nullptr;
  125. auto result = std::move(capturers_.front());
  126. capturers_.pop_front();
  127. return result;
  128. }
  129. void FakeAudioCapturerFactory::CreateAudioCapturer(
  130. fidl::InterfaceRequest<fuchsia::media::AudioCapturer> request,
  131. bool loopback) {
  132. capturers_.push_back(std::make_unique<FakeAudioCapturer>());
  133. capturers_.back()->Bind(std::move(request));
  134. }
  135. void FakeAudioCapturerFactory::NotImplemented_(const std::string& name) {
  136. ADD_FAILURE() << "Unexpected FakeAudioCapturerFactory call: " << name;
  137. }
  138. } // namespace media