blob: c18aebcc61034c1c770a450af3adf7d040679fcc [file] [log] [blame]
// Copyright 2020 The Fuchsia 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 SRC_MEDIA_AUDIO_LIB_TEST_CAPTURER_SHIM_H_
#define SRC_MEDIA_AUDIO_LIB_TEST_CAPTURER_SHIM_H_
#include <fuchsia/media/cpp/fidl.h>
#include <fuchsia/ultrasound/cpp/fidl.h>
#include <memory>
#include "src/lib/testing/loop_fixture/real_loop_fixture.h"
#include "src/media/audio/lib/format/audio_buffer.h"
#include "src/media/audio/lib/format/format.h"
#include "src/media/audio/lib/test/inspect.h"
#include "src/media/audio/lib/test/test_fixture.h"
#include "src/media/audio/lib/test/vmo_backed_buffer.h"
namespace media::audio::test {
namespace internal {
// These IDs are scoped to the lifetime of this process.
extern size_t capturer_shim_next_inspect_id;
} // namespace internal
// This class is thread hostile: none of its methods can be called concurrently.
class CapturerShimImpl {
public:
static constexpr uint32_t kPacketMs = 10;
~CapturerShimImpl() {}
fuchsia::media::AudioCapturerPtr& capturer() { return capturer_; }
VmoBackedBuffer& payload() { return payload_buffer_; }
size_t num_payload_frames() const { return payload_frame_count_; }
size_t num_payload_samples() const { return payload_frame_count_ * format_.channels(); }
size_t num_payload_bytes() const { return payload_frame_count_ * format_.bytes_per_frame(); }
// For validating properties exported by inspect.
// By default, there are no expectations.
size_t inspect_id() const { return inspect_id_; }
ExpectedInspectProperties& expected_inspect_properties() { return expected_inspect_properties_; }
protected:
CapturerShimImpl(Format format, size_t payload_frame_count)
: format_(format),
payload_frame_count_(payload_frame_count),
inspect_id_(internal::capturer_shim_next_inspect_id++),
payload_buffer_(format, payload_frame_count) {}
void CreatePayloadBuffer();
const Format format_;
const size_t payload_frame_count_;
const size_t inspect_id_;
fuchsia::media::AudioCapturerPtr capturer_;
VmoBackedBuffer payload_buffer_;
ExpectedInspectProperties expected_inspect_properties_;
};
template <fuchsia::media::AudioSampleFormat SampleFormat>
class AudioCapturerShim : public CapturerShimImpl {
public:
using SampleT = typename AudioBuffer<SampleFormat>::SampleT;
// Snapshot the current payload.
AudioBuffer<SampleFormat> SnapshotPayload() { return payload_buffer_.Snapshot<SampleFormat>(); }
// Don't call this directly. Use HermeticAudioTest::CreateAudioCapturer so the object is
// appropriately bound into the test environment.
AudioCapturerShim(TestFixture* fixture, fuchsia::media::AudioCorePtr& audio_core, Format format,
size_t payload_frame_count, fuchsia::media::AudioCapturerConfiguration config)
: CapturerShimImpl(format, payload_frame_count) {
audio_core->CreateAudioCapturerWithConfiguration(format.stream_type(), std::move(config),
capturer_.NewRequest());
fixture->AddErrorHandler(capturer_, "AudioCapturer");
capturer_->SetPcmStreamType({.sample_format = format_.sample_format(),
.channels = format_.channels(),
.frames_per_second = format_.frames_per_second()});
capturer_->AddPayloadBuffer(0, payload_buffer_.CreateAndMapVmo(true));
}
};
template <fuchsia::media::AudioSampleFormat SampleFormat>
class UltrasoundCapturerShim : public CapturerShimImpl {
public:
using SampleT = typename AudioBuffer<SampleFormat>::SampleT;
const zx::clock& reference_clock() const { return reference_clock_; }
// Snapshot the current payload.
AudioBufferSlice<SampleFormat> SnapshotPayload() {
return payload_buffer_.Snapshot<SampleFormat>();
}
// Don't call this directly. Use HermeticAudioTest::CreateUltrasoundCapturer so the object is
// appropriately bound into the test environment.
UltrasoundCapturerShim(TestFixture* fixture, fuchsia::ultrasound::FactoryPtr& ultrasound_factory,
Format format, size_t payload_frame_count)
: CapturerShimImpl(format, payload_frame_count), fixture_(fixture) {
auto vmo = payload_buffer_.CreateAndMapVmo(true);
ultrasound_factory->CreateCapturer(
capturer_.NewRequest(),
[this, vmo = std::move(vmo)](auto ref_clock, auto stream_type) mutable {
created_ = true;
reference_clock_ = std::move(ref_clock);
EXPECT_EQ(stream_type.sample_format, format_.sample_format());
EXPECT_EQ(stream_type.channels, format_.channels());
EXPECT_EQ(stream_type.frames_per_second, format_.frames_per_second());
// TODO(55243): Enable AddPayloadBuffer before the capturer is created.
capturer_->AddPayloadBuffer(0, std::move(vmo));
});
fixture->AddErrorHandler(capturer_, "UltrasoundCapturer");
}
void WaitForDevice() {
fixture_->RunLoopUntil([this] { return created_ || fixture_->ErrorOccurred(); });
}
bool created() const { return created_; }
private:
bool created_ = false;
TestFixture* fixture_;
zx::clock reference_clock_;
};
} // namespace media::audio::test
#endif // SRC_MEDIA_AUDIO_LIB_TEST_CAPTURER_SHIM_H_