| // Copyright 2018 The Chromium 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 <algorithm> |
| #include <cstdint> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/logging.h" |
| #include "chromecast/public/cast_media_shlib.h" |
| #include "chromecast/public/media/external_audio_pipeline_shlib.h" |
| #include "chromecast/public/media/mixer_output_stream.h" |
| |
| using ExternalMediaMetadataChangeObserver = chromecast::media:: |
| ExternalAudioPipelineShlib::ExternalMediaMetadataChangeObserver; |
| |
| namespace chromecast { |
| namespace media { |
| |
| class TestLoopBack { |
| public: |
| void OnData(const float* data, |
| int data_size, |
| MixerOutputStream* stream, |
| int channels) { |
| auto delay = stream->GetRenderingDelay(); |
| int64_t delay_ms = delay.timestamp_microseconds + delay.delay_microseconds; |
| for (auto* observer : observers_) { |
| observer->OnLoopbackAudio( |
| delay_ms, kSampleFormatF32, stream->GetSampleRate(), channels, |
| reinterpret_cast<uint8_t*>(const_cast<float*>(data)), |
| data_size * sizeof(float)); |
| } |
| } |
| |
| void AddObserver(CastMediaShlib::LoopbackAudioObserver* observer) { |
| observers_.push_back(observer); |
| } |
| |
| void RemoveObserver(CastMediaShlib::LoopbackAudioObserver* observer) { |
| auto it = std::find(observers_.begin(), observers_.end(), observer); |
| if (it != observers_.end()) { |
| observers_.erase(it); |
| } |
| } |
| |
| private: |
| std::vector<CastMediaShlib::LoopbackAudioObserver*> observers_; |
| }; |
| |
| TestLoopBack g_test_loop_back; |
| |
| class MixerOutputStreamTest : public MixerOutputStream { |
| public: |
| MixerOutputStreamTest(TestLoopBack* test_loop_back) |
| : stream_(MixerOutputStream::Create()), test_loop_back_(test_loop_back) { |
| DCHECK(test_loop_back_); |
| } |
| |
| bool Start(int requested_sample_rate, int channels) override { |
| channels_ = channels; |
| return stream_->Start(requested_sample_rate, channels); |
| } |
| |
| int GetSampleRate() override { return stream_->GetSampleRate(); } |
| |
| MediaPipelineBackend::AudioDecoder::RenderingDelay GetRenderingDelay() |
| override { |
| return stream_->GetRenderingDelay(); |
| } |
| |
| int OptimalWriteFramesCount() override { |
| return stream_->OptimalWriteFramesCount(); |
| } |
| |
| bool Write(const float* data, |
| int data_size, |
| bool* out_playback_interrupted) override { |
| test_loop_back_->OnData(data, data_size, this, channels_); |
| return stream_->Write(data, data_size, out_playback_interrupted); |
| } |
| |
| void Stop() override { return stream_->Stop(); } |
| |
| private: |
| std::unique_ptr<MixerOutputStream> stream_; |
| TestLoopBack* test_loop_back_; |
| int channels_ = 0; |
| }; |
| |
| bool ExternalAudioPipelineShlib::IsSupported() { |
| return true; |
| } |
| |
| void ExternalAudioPipelineShlib::AddExternalMediaVolumeChangeRequestObserver( |
| ExternalMediaVolumeChangeRequestObserver* observer) {} |
| |
| void ExternalAudioPipelineShlib::RemoveExternalMediaVolumeChangeRequestObserver( |
| ExternalMediaVolumeChangeRequestObserver* observer) {} |
| |
| void ExternalAudioPipelineShlib::SetExternalMediaVolume(float level) {} |
| |
| void ExternalAudioPipelineShlib::SetExternalMediaMuted(bool muted) {} |
| |
| void ExternalAudioPipelineShlib::AddExternalLoopbackAudioObserver( |
| CastMediaShlib::LoopbackAudioObserver* observer) { |
| g_test_loop_back.AddObserver(observer); |
| } |
| |
| void ExternalAudioPipelineShlib::RemoveExternalLoopbackAudioObserver( |
| CastMediaShlib::LoopbackAudioObserver* observer) { |
| g_test_loop_back.RemoveObserver(observer); |
| } |
| |
| void ExternalAudioPipelineShlib::AddExternalMediaMetadataChangeObserver( |
| ExternalMediaMetadataChangeObserver* observer) {} |
| |
| void ExternalAudioPipelineShlib::RemoveExternalMediaMetadataChangeObserver( |
| ExternalMediaMetadataChangeObserver* observer) {} |
| |
| std::unique_ptr<MixerOutputStream> |
| ExternalAudioPipelineShlib::CreateMixerOutputStream() { |
| return std::make_unique<MixerOutputStreamTest>(&g_test_loop_back); |
| } |
| |
| } // namespace media |
| } // namespace chromecast |