| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <math.h> | 5 #include <math.h> |
| 6 #include <memory> | 6 #include <memory> |
| 7 | 7 |
| 8 #include "mojo/public/c/system/main.h" | 8 #include "mojo/public/c/system/main.h" |
| 9 #include "mojo/public/cpp/application/application_delegate.h" | 9 #include "mojo/public/cpp/application/application_delegate.h" |
| 10 #include "mojo/public/cpp/application/application_impl.h" | 10 #include "mojo/public/cpp/application/application_impl.h" |
| 11 #include "mojo/public/cpp/application/application_runner.h" | 11 #include "mojo/public/cpp/application/application_runner.h" |
| 12 #include "mojo/public/cpp/application/connect.h" | 12 #include "mojo/public/cpp/application/connect.h" |
| 13 #include "mojo/public/cpp/utility/run_loop.h" | 13 #include "mojo/public/cpp/utility/run_loop.h" |
| 14 #include "mojo/services/media/audio/interfaces/audio_server.mojom.h" | 14 #include "mojo/services/media/audio/interfaces/audio_server.mojom.h" |
| 15 #include "mojo/services/media/audio/interfaces/audio_track.mojom.h" | 15 #include "mojo/services/media/audio/interfaces/audio_track.mojom.h" |
| 16 #include "mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h" | 16 #include "mojo/services/media/common/cpp/circular_buffer_media_pipe_adapter.h" |
| 17 #include "mojo/services/media/common/cpp/linear_transform.h" | 17 #include "mojo/services/media/common/cpp/linear_transform.h" |
| 18 #include "mojo/services/media/common/cpp/local_time.h" | 18 #include "mojo/services/media/common/cpp/local_time.h" |
| 19 #include "mojo/services/media/common/interfaces/rate_control.mojom.h" | 19 #include "mojo/services/media/common/interfaces/timelines.mojom.h" |
| 20 | 20 |
| 21 namespace mojo { | 21 namespace mojo { |
| 22 namespace media { | 22 namespace media { |
| 23 namespace audio { | 23 namespace audio { |
| 24 namespace examples { | 24 namespace examples { |
| 25 | 25 |
| 26 static constexpr uint32_t SAMP_FREQ = 48000; | 26 static constexpr uint32_t SAMP_FREQ = 48000; |
| 27 static constexpr uint32_t CHUNK_USEC = 10000; | 27 static constexpr uint32_t CHUNK_USEC = 10000; |
| 28 static constexpr uint32_t BUF_LO_WATER_USEC = 500000; | 28 static constexpr uint32_t BUF_LO_WATER_USEC = 500000; |
| 29 static constexpr uint32_t BUF_HI_WATER_USEC = BUF_LO_WATER_USEC | 29 static constexpr uint32_t BUF_HI_WATER_USEC = BUF_LO_WATER_USEC |
| (...skipping 15 matching lines...) Expand all Loading... |
| 45 void Quit() override; | 45 void Quit() override; |
| 46 | 46 |
| 47 private: | 47 private: |
| 48 void GenerateToneCbk(MediaResult res); | 48 void GenerateToneCbk(MediaResult res); |
| 49 void PlayTone(double freq_hz, double amplitude, double duration_sec); | 49 void PlayTone(double freq_hz, double amplitude, double duration_sec); |
| 50 void PostShutdown(); | 50 void PostShutdown(); |
| 51 void Shutdown(); | 51 void Shutdown(); |
| 52 void OnConnectionError(const std::string& connection_name); | 52 void OnConnectionError(const std::string& connection_name); |
| 53 | 53 |
| 54 AudioServerPtr audio_server_; | 54 AudioServerPtr audio_server_; |
| 55 AudioTrackPtr audio_track_; | 55 AudioTrackPtr audio_track_; |
| 56 RateControlPtr rate_control_; | 56 TimelineConsumerPtr timeline_consumer_; |
| 57 std::unique_ptr<CircularBufferMediaPipeAdapter> audio_pipe_; | 57 std::unique_ptr<CircularBufferMediaPipeAdapter> audio_pipe_; |
| 58 | 58 |
| 59 bool clock_started_ = false; | 59 bool clock_started_ = false; |
| 60 uint64_t media_time_ = 0; | 60 uint64_t media_time_ = 0; |
| 61 double freq_hz_ = 440.0; | 61 double freq_hz_ = 440.0; |
| 62 double amplitude_ = 1.0; | 62 double amplitude_ = 1.0; |
| 63 bool shutting_down_ = false; | 63 bool shutting_down_ = false; |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 void PlayToneApp::Quit() { | 66 void PlayToneApp::Quit() { |
| 67 rate_control_.reset(); | 67 timeline_consumer_.reset(); |
| 68 audio_pipe_.reset(); | 68 audio_pipe_.reset(); |
| 69 audio_track_.reset(); | 69 audio_track_.reset(); |
| 70 audio_server_.reset(); | 70 audio_server_.reset(); |
| 71 } | 71 } |
| 72 | 72 |
| 73 void PlayToneApp::Initialize(ApplicationImpl* app) { | 73 void PlayToneApp::Initialize(ApplicationImpl* app) { |
| 74 mojo::ConnectToService(app->shell(), "mojo:audio_server", | 74 mojo::ConnectToService(app->shell(), "mojo:audio_server", |
| 75 GetProxy(&audio_server_)); | 75 GetProxy(&audio_server_)); |
| 76 audio_server_.set_connection_error_handler([this]() { | 76 audio_server_.set_connection_error_handler([this]() { |
| 77 OnConnectionError("audio_server"); | 77 OnConnectionError("audio_server"); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 108 if (!audio_track_.WaitForIncomingResponse()) { | 108 if (!audio_track_.WaitForIncomingResponse()) { |
| 109 MOJO_LOG(ERROR) | 109 MOJO_LOG(ERROR) |
| 110 << "Failed to fetch sync capabilities; no response received."; | 110 << "Failed to fetch sync capabilities; no response received."; |
| 111 Shutdown(); | 111 Shutdown(); |
| 112 return; | 112 return; |
| 113 } | 113 } |
| 114 | 114 |
| 115 // TODO(johngro): do something useful with our capabilities description. | 115 // TODO(johngro): do something useful with our capabilities description. |
| 116 sink_desc.reset(); | 116 sink_desc.reset(); |
| 117 | 117 |
| 118 // Grab the rate control interface for our audio renderer. | 118 // Grab the timeline consumer interface for our audio renderer. |
| 119 audio_track_->GetRateControl(GetProxy(&rate_control_)); | 119 MediaTimelineControlSitePtr timeline_control_site; |
| 120 rate_control_.set_connection_error_handler([this]() { | 120 audio_track_->GetTimelineControlSite(GetProxy(&timeline_control_site)); |
| 121 OnConnectionError("rate_control"); | 121 timeline_control_site->GetTimelineConsumer(GetProxy(&timeline_consumer_)); |
| 122 }); | 122 timeline_consumer_.set_connection_error_handler( |
| 123 [this]() { OnConnectionError("timeline_consumer"); }); |
| 123 | 124 |
| 124 // Configure our sink for 16-bit 48KHz mono. | 125 // Configure our sink for 16-bit 48KHz mono. |
| 125 AudioTrackConfigurationPtr cfg = AudioTrackConfiguration::New(); | 126 AudioTrackConfigurationPtr cfg = AudioTrackConfiguration::New(); |
| 126 | 127 |
| 127 AudioMediaTypeDetailsPtr pcm_cfg = AudioMediaTypeDetails::New(); | 128 AudioMediaTypeDetailsPtr pcm_cfg = AudioMediaTypeDetails::New(); |
| 128 pcm_cfg->sample_format = AudioSampleFormat::SIGNED_16; | 129 pcm_cfg->sample_format = AudioSampleFormat::SIGNED_16; |
| 129 pcm_cfg->channels = 1; | 130 pcm_cfg->channels = 1; |
| 130 pcm_cfg->frames_per_second = SAMP_FREQ; | 131 pcm_cfg->frames_per_second = SAMP_FREQ; |
| 131 | 132 |
| 132 cfg->media_type = MediaType::New(); | 133 cfg->media_type = MediaType::New(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 if (res != MediaResult::OK) { | 198 if (res != MediaResult::OK) { |
| 198 MOJO_LOG(ERROR) << "Unexpected error when sending media packet (" | 199 MOJO_LOG(ERROR) << "Unexpected error when sending media packet (" |
| 199 << res << ")."; | 200 << res << ")."; |
| 200 audio_pipe_->CancelMediaPacket(&mapped_pkt); | 201 audio_pipe_->CancelMediaPacket(&mapped_pkt); |
| 201 PostShutdown(); | 202 PostShutdown(); |
| 202 return; | 203 return; |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 | 206 |
| 206 if (!clock_started_) { | 207 if (!clock_started_) { |
| 207 // In theory, this could be done at compile time using std::ratio, but | 208 MOJO_LOG(INFO) << "Setting rate 1/1"; |
| 208 // std::ratio is prohibited. | |
| 209 LinearTransform::Ratio audio_rate(SAMP_FREQ, 1); | |
| 210 LinearTransform::Ratio local_time_rate(LocalDuration::period::num, | |
| 211 LocalDuration::period::den); | |
| 212 LinearTransform::Ratio rate; | |
| 213 bool success = LinearTransform::Ratio::Compose(local_time_rate, | |
| 214 audio_rate, | |
| 215 &rate); | |
| 216 MOJO_DCHECK(success); // assert that there was no loss of precision. | |
| 217 | 209 |
| 218 MOJO_LOG(INFO) << "Setting rate " << rate; | 210 timeline_consumer_->SetTimelineTransform( |
| 219 | 211 kUnspecifiedTime, 1, 1, kUnspecifiedTime, kUnspecifiedTime, |
| 220 rate_control_->SetRate(rate.numerator, rate.denominator); | 212 [](bool completed) {}); |
| 221 clock_started_ = true; | 213 clock_started_ = true; |
| 222 } | 214 } |
| 223 } | 215 } |
| 224 | 216 |
| 225 void PlayToneApp::OnConnectionError(const std::string& connection_name) { | 217 void PlayToneApp::OnConnectionError(const std::string& connection_name) { |
| 226 if (!shutting_down_) { | 218 if (!shutting_down_) { |
| 227 MOJO_LOG(ERROR) << connection_name << " connection closed unexpectedly!"; | 219 MOJO_LOG(ERROR) << connection_name << " connection closed unexpectedly!"; |
| 228 Shutdown(); | 220 Shutdown(); |
| 229 } | 221 } |
| 230 } | 222 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 249 } // namespace audio | 241 } // namespace audio |
| 250 } // namespace media | 242 } // namespace media |
| 251 } // namespace mojo | 243 } // namespace mojo |
| 252 | 244 |
| 253 MojoResult MojoMain(MojoHandle app_request) { | 245 MojoResult MojoMain(MojoHandle app_request) { |
| 254 mojo::ApplicationRunner runner( | 246 mojo::ApplicationRunner runner( |
| 255 std::unique_ptr<mojo::media::audio::examples::PlayToneApp>( | 247 std::unique_ptr<mojo::media::audio::examples::PlayToneApp>( |
| 256 new mojo::media::audio::examples::PlayToneApp())); | 248 new mojo::media::audio::examples::PlayToneApp())); |
| 257 return runner.Run(app_request); | 249 return runner.Run(app_request); |
| 258 } | 250 } |
| OLD | NEW |