blob: f36928f5fcbcc0d990076812376e1a4db00ab5e7 [file] [log] [blame]
// Copyright 2016 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.
#include "garnet/bin/mediaplayer/test/fakes/fake_audio_renderer.h"
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <iomanip>
#include <iostream>
#include <limits>
#include "lib/fxl/logging.h"
#include "lib/media/timeline/timeline.h"
namespace media_player {
namespace test {
FakeAudioRenderer::FakeAudioRenderer()
: dispatcher_(async_get_default_dispatcher()), binding_(this) {}
FakeAudioRenderer::~FakeAudioRenderer() {}
void FakeAudioRenderer::Bind(
fidl::InterfaceRequest<fuchsia::media::AudioRenderer> request) {
binding_.Bind(std::move(request));
}
void FakeAudioRenderer::SetPcmStreamType(
fuchsia::media::AudioStreamType format) {
format_ = format;
}
void FakeAudioRenderer::SetStreamType(fuchsia::media::StreamType format) {
FXL_NOTIMPLEMENTED();
}
void FakeAudioRenderer::AddPayloadBuffer(uint32_t id,
::zx::vmo payload_buffer) {
FXL_DCHECK(id == 0) << "Only ID 0 is currently supported.";
vmo_mapper_.Map(std::move(payload_buffer), 0, 0, ZX_VM_PERM_READ);
}
void FakeAudioRenderer::RemovePayloadBuffer(uint32_t id) {
FXL_NOTIMPLEMENTED();
}
void FakeAudioRenderer::SetPtsUnits(uint32_t tick_per_second_numerator,
uint32_t tick_per_second_denominator) {
pts_rate_ = media::TimelineRate(tick_per_second_numerator,
tick_per_second_denominator);
}
void FakeAudioRenderer::SetPtsContinuityThreshold(float threshold_seconds) {
threshold_seconds_ = threshold_seconds;
}
void FakeAudioRenderer::SetReferenceClock(::zx::handle ref_clock) {
FXL_NOTIMPLEMENTED();
}
void FakeAudioRenderer::SendPacket(fuchsia::media::StreamPacket packet,
SendPacketCallback callback) {
if (dump_packets_) {
std::cerr << "{ " << packet.pts << ", " << packet.payload_size << ", 0x"
<< std::hex << std::setw(16) << std::setfill('0')
<< PacketInfo::Hash(
reinterpret_cast<uint8_t*>(vmo_mapper_.start()) +
packet.payload_offset,
packet.payload_size)
<< std::dec << " },\n";
}
if (!expected_packets_info_.empty()) {
if (expected_packets_info_iter_ == expected_packets_info_.end()) {
FXL_LOG(ERROR) << "packet supplied after expected packets";
expected_ = false;
}
if (expected_packets_info_iter_->pts() != packet.pts ||
expected_packets_info_iter_->size() != packet.payload_size ||
expected_packets_info_iter_->hash() !=
PacketInfo::Hash(reinterpret_cast<uint8_t*>(vmo_mapper_.start()) +
packet.payload_offset,
packet.payload_size)) {
FXL_LOG(ERROR) << "supplied packet doesn't match expected packet info";
expected_ = false;
}
++expected_packets_info_iter_;
}
packet_queue_.push(std::make_pair(packet, std::move(callback)));
if (packet_queue_.size() == 1) {
MaybeScheduleRetirement();
}
}
void FakeAudioRenderer::SendPacketNoReply(fuchsia::media::StreamPacket packet) {
SendPacket(std::move(packet), []() {});
}
void FakeAudioRenderer::EndOfStream() { FXL_NOTIMPLEMENTED(); }
void FakeAudioRenderer::DiscardAllPackets(DiscardAllPacketsCallback callback) {
while (!packet_queue_.empty()) {
packet_queue_.front().second();
packet_queue_.pop();
}
callback();
}
void FakeAudioRenderer::DiscardAllPacketsNoReply() {
DiscardAllPackets([]() {});
}
void FakeAudioRenderer::Play(int64_t reference_time, int64_t media_time,
PlayCallback callback) {
if (reference_time == fuchsia::media::NO_TIMESTAMP) {
reference_time = media::Timeline::local_now();
}
if (media_time == fuchsia::media::NO_TIMESTAMP) {
if (restart_media_time_ != fuchsia::media::NO_TIMESTAMP) {
media_time = restart_media_time_;
} else if (packet_queue_.empty()) {
media_time = 0;
} else {
media_time = packet_queue_.front().first.pts;
}
}
callback(reference_time, media_time);
timeline_function_ = media::TimelineFunction(
media_time, reference_time, pts_rate_ / media::TimelineRate::NsPerSecond);
MaybeScheduleRetirement();
}
void FakeAudioRenderer::PlayNoReply(int64_t reference_time,
int64_t media_time) {
Play(reference_time, media_time,
[](int64_t reference_time, int64_t media_time) {});
}
void FakeAudioRenderer::Pause(PauseCallback callback) {
int64_t reference_time = media::Timeline::local_now();
int64_t media_time = timeline_function_(reference_time);
timeline_function_ =
media::TimelineFunction(media_time, reference_time, 0, 1);
callback(reference_time, media_time);
}
void FakeAudioRenderer::PauseNoReply() {
Pause([](int64_t reference_time, int64_t media_time) {});
}
void FakeAudioRenderer::BindGainControl(
::fidl::InterfaceRequest<fuchsia::media::GainControl> request) {
FXL_NOTIMPLEMENTED();
}
void FakeAudioRenderer::EnableMinLeadTimeEvents(bool enabled) {
if (enabled) {
binding_.events().OnMinLeadTimeChanged(min_lead_time_ns_);
}
}
void FakeAudioRenderer::GetMinLeadTime(GetMinLeadTimeCallback callback) {
callback(min_lead_time_ns_);
}
void FakeAudioRenderer::SetGain(float gain_db) { gain_ = gain_db; }
void FakeAudioRenderer::SetMute(bool muted) { mute_ = muted; }
void FakeAudioRenderer::MaybeScheduleRetirement() {
if (!progressing() || packet_queue_.empty()) {
return;
}
int64_t reference_time =
timeline_function_.ApplyInverse(packet_queue_.front().first.pts);
async::PostTaskForTime(
dispatcher_,
[this]() {
if (!progressing() || packet_queue_.empty()) {
return;
}
int64_t reference_time =
timeline_function_.ApplyInverse(packet_queue_.front().first.pts);
if (reference_time <= media::Timeline::local_now()) {
packet_queue_.front().second();
packet_queue_.pop();
}
MaybeScheduleRetirement();
},
zx::time(reference_time));
}
} // namespace test
} // namespace media_player