| // Copyright 2019 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 "src/media/audio/audio_core/reporter.h" |
| |
| #include "src/lib/fxl/logging.h" |
| #include "src/media/audio/audio_core/audio_device.h" |
| |
| namespace media::audio { |
| |
| #if ENABLE_REPORTER |
| |
| // static |
| Reporter& Reporter::Singleton() { |
| static Reporter singleton; |
| return singleton; |
| } |
| |
| void Reporter::Init(sys::ComponentContext* component_context) { |
| FXL_DCHECK(component_context); |
| FXL_DCHECK(!component_context_); |
| component_context_ = component_context; |
| |
| inspector_ = inspect_deprecated::ComponentInspector::Initialize(component_context_); |
| inspect_deprecated::Node& root_node = inspector_->root_tree()->GetRoot(); |
| failed_to_open_device_count_ = root_node.CreateUIntMetric("count of failures to open device", 0); |
| failed_to_obtain_fdio_service_channel_count_ = |
| root_node.CreateUIntMetric("count of failures to obtain device fdio service channel", 0); |
| failed_to_obtain_stream_channel_count_ = |
| root_node.CreateUIntMetric("count of failures to obtain device stream channel", 0); |
| device_startup_failed_count_ = |
| root_node.CreateUIntMetric("count of failures to start a device", 0); |
| |
| outputs_node_ = root_node.CreateChild("output devices"); |
| inputs_node_ = root_node.CreateChild("input devices"); |
| renderers_node_ = root_node.CreateChild("renderers"); |
| capturers_node_ = root_node.CreateChild("capturers"); |
| } |
| |
| void Reporter::FailedToOpenDevice(const std::string& name, bool is_input, int err) { |
| failed_to_open_device_count_.Add(1); |
| } |
| |
| void Reporter::FailedToObtainFdioServiceChannel(const std::string& name, bool is_input, |
| zx_status_t status) { |
| failed_to_obtain_fdio_service_channel_count_.Add(1); |
| } |
| |
| void Reporter::FailedToObtainStreamChannel(const std::string& name, bool is_input, |
| zx_status_t status) { |
| failed_to_obtain_stream_channel_count_.Add(1); |
| } |
| |
| void Reporter::AddingDevice(const std::string& name, const AudioDevice& device) { |
| if (device.is_output()) { |
| outputs_.emplace(&device, Output(outputs_node_.CreateChild(name))); |
| } else { |
| FXL_DCHECK(device.is_input()); |
| inputs_.emplace(&device, Input(inputs_node_.CreateChild(name))); |
| } |
| } |
| |
| void Reporter::RemovingDevice(const AudioDevice& device) { |
| if (device.is_output()) { |
| outputs_.erase(&device); |
| } else { |
| FXL_DCHECK(device.is_input()); |
| inputs_.erase(&device); |
| } |
| } |
| |
| void Reporter::DeviceStartupFailed(const AudioDevice& device) { |
| device_startup_failed_count_.Add(1); |
| } |
| |
| void Reporter::IgnoringDevice(const AudioDevice& device) { |
| // Not reporting this via inspect. |
| } |
| |
| void Reporter::ActivatingDevice(const AudioDevice& device) { |
| // Not reporting this via inspect...devices not activated are quickly removed. |
| } |
| |
| void Reporter::SettingDeviceGainInfo(const AudioDevice& device, |
| const fuchsia::media::AudioGainInfo& gain_info, |
| uint32_t set_flags) { |
| Device* d = device.is_output() ? FindOutput(device) : FindInput(device); |
| if (d == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| if (set_flags & fuchsia::media::SetAudioGainFlag_GainValid) { |
| d->gain_db_.Set(gain_info.gain_db); |
| } |
| |
| if (set_flags & fuchsia::media::SetAudioGainFlag_MuteValid) { |
| d->muted_.Set((gain_info.flags & fuchsia::media::AudioGainInfoFlag_Mute) ? 1 : 0); |
| } |
| |
| if (set_flags & fuchsia::media::SetAudioGainFlag_AgcValid) { |
| d->agc_supported_.Set((gain_info.flags & fuchsia::media::AudioGainInfoFlag_AgcSupported) ? 1 |
| : 0); |
| d->agc_enabled_.Set((gain_info.flags & fuchsia::media::AudioGainInfoFlag_AgcEnabled) ? 1 : 0); |
| } |
| } |
| |
| void Reporter::AddingRenderer(const AudioRendererImpl& renderer) { |
| renderers_.emplace(&renderer, Renderer(renderers_node_.CreateChild(NextRendererName()))); |
| } |
| |
| void Reporter::RemovingRenderer(const AudioRendererImpl& renderer) { renderers_.erase(&renderer); } |
| |
| void Reporter::SettingRendererStreamType(const AudioRendererImpl& renderer, |
| const fuchsia::media::AudioStreamType& stream_type) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->sample_format_.Set(static_cast<uint64_t>(stream_type.sample_format)); |
| r->channels_.Set(stream_type.channels); |
| r->frames_per_second_.Set(stream_type.frames_per_second); |
| } |
| |
| void Reporter::AddingRendererPayloadBuffer(const AudioRendererImpl& renderer, uint32_t buffer_id, |
| uint64_t size) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->payload_buffers_.emplace( |
| buffer_id, |
| PayloadBuffer(r->payload_buffers_node_.CreateChild(std::to_string(buffer_id)), size)); |
| } |
| |
| void Reporter::RemovingRendererPayloadBuffer(const AudioRendererImpl& renderer, |
| uint32_t buffer_id) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| r->payload_buffers_.erase(buffer_id); |
| } |
| |
| void Reporter::SendingRendererPacket(const AudioRendererImpl& renderer, |
| const fuchsia::media::StreamPacket& packet) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| auto payload_buffer = r->payload_buffers_.find(packet.payload_buffer_id); |
| if (payload_buffer == r->payload_buffers_.end()) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| payload_buffer->second.packets_.Add(1); |
| } |
| |
| void Reporter::SettingRendererGain(const AudioRendererImpl& renderer, float gain_db) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->gain_db_.Set(gain_db); |
| } |
| |
| void Reporter::SettingRendererGainWithRamp(const AudioRendererImpl& renderer, float gain_db, |
| zx_duration_t duration_ns, |
| fuchsia::media::audio::RampType ramp_type) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| // Just counting these for now. |
| r->set_gain_with_ramp_calls_.Add(1); |
| } |
| |
| void Reporter::SettingRendererMute(const AudioRendererImpl& renderer, bool muted) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->muted_.Set(muted); |
| } |
| |
| void Reporter::SettingRendererMinClockLeadTime(const AudioRendererImpl& renderer, |
| int64_t min_clock_lead_time_ns) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->min_clock_lead_time_ns_.Set(static_cast<uint64_t>(min_clock_lead_time_ns)); |
| } |
| |
| void Reporter::SettingRendererPtsContinuityThreshold(const AudioRendererImpl& renderer, |
| float threshold_seconds) { |
| Renderer* r = FindRenderer(renderer); |
| if (r == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| r->pts_continuity_threshold_seconds_.Set(threshold_seconds); |
| } |
| |
| void Reporter::AddingCapturer(const AudioCapturerImpl& capturer) { |
| capturers_.emplace(&capturer, Capturer(capturers_node_.CreateChild(NextCapturerName()))); |
| } |
| |
| void Reporter::RemovingCapturer(const AudioCapturerImpl& capturer) { capturers_.erase(&capturer); } |
| |
| void Reporter::SettingCapturerStreamType(const AudioCapturerImpl& capturer, |
| const fuchsia::media::AudioStreamType& stream_type) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| c->sample_format_.Set(static_cast<uint64_t>(stream_type.sample_format)); |
| c->channels_.Set(stream_type.channels); |
| c->frames_per_second_.Set(stream_type.frames_per_second); |
| } |
| |
| void Reporter::AddingCapturerPayloadBuffer(const AudioCapturerImpl& capturer, uint32_t buffer_id, |
| uint64_t size) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| c->payload_buffers_.emplace( |
| buffer_id, |
| PayloadBuffer(c->payload_buffers_node_.CreateChild(std::to_string(buffer_id)), size)); |
| } |
| |
| void Reporter::SendingCapturerPacket(const AudioCapturerImpl& capturer, |
| const fuchsia::media::StreamPacket& packet) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| auto payload_buffer = c->payload_buffers_.find(packet.payload_buffer_id); |
| if (payload_buffer == c->payload_buffers_.end()) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| payload_buffer->second.packets_.Add(1); |
| } |
| |
| void Reporter::SettingCapturerGain(const AudioCapturerImpl& capturer, float gain_db) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| c->gain_db_.Set(gain_db); |
| } |
| |
| void Reporter::SettingCapturerGainWithRamp(const AudioCapturerImpl& capturer, float gain_db, |
| zx_duration_t duration_ns, |
| fuchsia::media::audio::RampType ramp_type) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| // Just counting these for now. |
| c->set_gain_with_ramp_calls_.Add(1); |
| } |
| |
| void Reporter::SettingCapturerMute(const AudioCapturerImpl& capturer, bool muted) { |
| Capturer* c = FindCapturer(capturer); |
| if (c == nullptr) { |
| FXL_DLOG(FATAL); |
| return; |
| } |
| |
| c->muted_.Set(muted); |
| } |
| |
| Reporter::Device* Reporter::FindOutput(const AudioDevice& device) { |
| auto i = outputs_.find(&device); |
| return i == outputs_.end() ? nullptr : &i->second; |
| } |
| |
| Reporter::Device* Reporter::FindInput(const AudioDevice& device) { |
| auto i = inputs_.find(&device); |
| return i == inputs_.end() ? nullptr : &i->second; |
| } |
| |
| Reporter::Renderer* Reporter::FindRenderer(const AudioRendererImpl& renderer) { |
| auto i = renderers_.find(&renderer); |
| return i == renderers_.end() ? nullptr : &i->second; |
| } |
| |
| Reporter::Capturer* Reporter::FindCapturer(const AudioCapturerImpl& capturer) { |
| auto i = capturers_.find(&capturer); |
| return i == capturers_.end() ? nullptr : &i->second; |
| } |
| |
| std::string Reporter::NextRendererName() { |
| std::ostringstream os; |
| os << ++next_renderer_name_; |
| return os.str(); |
| } |
| |
| std::string Reporter::NextCapturerName() { |
| std::ostringstream os; |
| os << ++next_capturer_name_; |
| return os.str(); |
| } |
| |
| #endif // ENABLE_REPORTER |
| |
| } // namespace media::audio |