Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: media/audio/alsa/alsa_output.cc

Issue 2101303004: Pass delay and timestamp to AudioSourceCallback::OnMoreData. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Changes based on comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 // THREAD SAFETY 5 // THREAD SAFETY
6 // 6 //
7 // AlsaPcmOutputStream object is *not* thread-safe and should only be used 7 // AlsaPcmOutputStream object is *not* thread-safe and should only be used
8 // from the audio thread. We DCHECK on this assumption whenever we can. 8 // from the audio thread. We DCHECK on this assumption whenever we can.
9 // 9 //
10 // SEMANTICS OF Close() 10 // SEMANTICS OF Close()
(...skipping 19 matching lines...) Expand all
30 // When |stop_stream_| is set, no more commands will be made against the 30 // When |stop_stream_| is set, no more commands will be made against the
31 // ALSA device, and playback will effectively stop. From the client's point of 31 // ALSA device, and playback will effectively stop. From the client's point of
32 // view, it will seem that the device has just clogged and stopped requesting 32 // view, it will seem that the device has just clogged and stopped requesting
33 // data. 33 // data.
34 34
35 #include "media/audio/alsa/alsa_output.h" 35 #include "media/audio/alsa/alsa_output.h"
36 36
37 #include <stddef.h> 37 #include <stddef.h>
38 38
39 #include <algorithm> 39 #include <algorithm>
40 #include <utility>
40 41
41 #include "base/bind.h" 42 #include "base/bind.h"
42 #include "base/logging.h" 43 #include "base/logging.h"
43 #include "base/memory/free_deleter.h" 44 #include "base/memory/free_deleter.h"
44 #include "base/stl_util.h" 45 #include "base/stl_util.h"
45 #include "base/threading/thread_task_runner_handle.h" 46 #include "base/threading/thread_task_runner_handle.h"
47 #include "base/time/default_tick_clock.h"
46 #include "base/trace_event/trace_event.h" 48 #include "base/trace_event/trace_event.h"
47 #include "media/audio/alsa/alsa_util.h" 49 #include "media/audio/alsa/alsa_util.h"
48 #include "media/audio/alsa/alsa_wrapper.h" 50 #include "media/audio/alsa/alsa_wrapper.h"
49 #include "media/audio/alsa/audio_manager_alsa.h" 51 #include "media/audio/alsa/audio_manager_alsa.h"
50 #include "media/base/channel_mixer.h" 52 #include "media/base/channel_mixer.h"
51 #include "media/base/data_buffer.h" 53 #include "media/base/data_buffer.h"
52 #include "media/base/seekable_buffer.h" 54 #include "media/base/seekable_buffer.h"
53 55
54 namespace media { 56 namespace media {
55 57
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 break; 120 break;
119 case AlsaPcmOutputStream::kIsPlaying: 121 case AlsaPcmOutputStream::kIsPlaying:
120 os << "kIsPlaying"; 122 os << "kIsPlaying";
121 break; 123 break;
122 case AlsaPcmOutputStream::kIsStopped: 124 case AlsaPcmOutputStream::kIsStopped:
123 os << "kIsStopped"; 125 os << "kIsStopped";
124 break; 126 break;
125 case AlsaPcmOutputStream::kIsClosed: 127 case AlsaPcmOutputStream::kIsClosed:
126 os << "kIsClosed"; 128 os << "kIsClosed";
127 break; 129 break;
128 }; 130 }
129 return os; 131 return os;
130 } 132 }
131 133
132 const char AlsaPcmOutputStream::kDefaultDevice[] = "default"; 134 const char AlsaPcmOutputStream::kDefaultDevice[] = "default";
133 const char AlsaPcmOutputStream::kAutoSelectDevice[] = ""; 135 const char AlsaPcmOutputStream::kAutoSelectDevice[] = "";
134 const char AlsaPcmOutputStream::kPlugPrefix[] = "plug:"; 136 const char AlsaPcmOutputStream::kPlugPrefix[] = "plug:";
135 137
136 // We use 40ms as our minimum required latency. If it is needed, we may be able 138 // We use 40ms as our minimum required latency. If it is needed, we may be able
137 // to get it down to 20ms. 139 // to get it down to 20ms.
138 const uint32_t AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000; 140 const uint32_t AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000;
(...skipping 18 matching lines...) Expand all
157 stop_stream_(false), 159 stop_stream_(false),
158 wrapper_(wrapper), 160 wrapper_(wrapper),
159 manager_(manager), 161 manager_(manager),
160 task_runner_(base::ThreadTaskRunnerHandle::Get()), 162 task_runner_(base::ThreadTaskRunnerHandle::Get()),
161 playback_handle_(NULL), 163 playback_handle_(NULL),
162 frames_per_packet_(packet_size_ / bytes_per_frame_), 164 frames_per_packet_(packet_size_ / bytes_per_frame_),
163 state_(kCreated), 165 state_(kCreated),
164 volume_(1.0f), 166 volume_(1.0f),
165 source_callback_(NULL), 167 source_callback_(NULL),
166 audio_bus_(AudioBus::Create(params)), 168 audio_bus_(AudioBus::Create(params)),
169 tick_clock_(new base::DefaultTickClock()),
167 weak_factory_(this) { 170 weak_factory_(this) {
168 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); 171 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
169 DCHECK_EQ(audio_bus_->frames() * bytes_per_frame_, packet_size_); 172 DCHECK_EQ(audio_bus_->frames() * bytes_per_frame_, packet_size_);
170 173
171 // Sanity check input values. 174 // Sanity check input values.
172 if (!params.IsValid()) { 175 if (!params.IsValid()) {
173 LOG(WARNING) << "Unsupported audio parameters."; 176 LOG(WARNING) << "Unsupported audio parameters.";
174 TransitionTo(kInError); 177 TransitionTo(kInError);
175 } 178 }
176 179
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 341
339 volume_ = static_cast<float>(volume); 342 volume_ = static_cast<float>(volume);
340 } 343 }
341 344
342 void AlsaPcmOutputStream::GetVolume(double* volume) { 345 void AlsaPcmOutputStream::GetVolume(double* volume) {
343 DCHECK(CalledOnValidThread()); 346 DCHECK(CalledOnValidThread());
344 347
345 *volume = volume_; 348 *volume = volume_;
346 } 349 }
347 350
351 void AlsaPcmOutputStream::SetTickClockForTesting(
352 std::unique_ptr<base::TickClock> tick_clock) {
353 DCHECK(tick_clock);
354 tick_clock_ = std::move(tick_clock);
355 }
356
348 void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) { 357 void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
349 DCHECK(CalledOnValidThread()); 358 DCHECK(CalledOnValidThread());
350 359
351 // If stopped, simulate a 0-length packet. 360 // If stopped, simulate a 0-length packet.
352 if (stop_stream_) { 361 if (stop_stream_) {
353 buffer_->Clear(); 362 buffer_->Clear();
354 *source_exhausted = true; 363 *source_exhausted = true;
355 return; 364 return;
356 } 365 }
357 366
358 *source_exhausted = false; 367 *source_exhausted = false;
359 368
360 // Request more data only when we run out of data in the buffer, because 369 // Request more data only when we run out of data in the buffer, because
361 // WritePacket() consumes only the current chunk of data. 370 // WritePacket() consumes only the current chunk of data.
362 if (!buffer_->forward_bytes()) { 371 if (!buffer_->forward_bytes()) {
363 // Before making a request to source for data we need to determine the 372 // Before making a request to source for data we need to determine the
364 // delay (in bytes) for the requested data to be played. 373 // time when the requested data will be played.
365 const uint32_t hardware_delay = GetCurrentDelay() * bytes_per_frame_; 374 const base::TimeTicks target_playout_time =
375 tick_clock_->NowTicks() +
376 FramesToTimeDelta(GetCurrentDelay(), sample_rate_);
366 377
367 scoped_refptr<media::DataBuffer> packet = 378 scoped_refptr<media::DataBuffer> packet =
368 new media::DataBuffer(packet_size_); 379 new media::DataBuffer(packet_size_);
369 int frames_filled = RunDataCallback( 380 int frames_filled = RunDataCallback(target_playout_time, audio_bus_.get());
370 audio_bus_.get(), hardware_delay);
371 381
372 size_t packet_size = frames_filled * bytes_per_frame_; 382 size_t packet_size = frames_filled * bytes_per_frame_;
373 DCHECK_LE(packet_size, packet_size_); 383 DCHECK_LE(packet_size, packet_size_);
374 384
375 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer; 385 // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer;
376 // volume adjust should use SSE optimized vector_fmul() prior to interleave. 386 // volume adjust should use SSE optimized vector_fmul() prior to interleave.
377 AudioBus* output_bus = audio_bus_.get(); 387 AudioBus* output_bus = audio_bus_.get();
378 ChannelLayout output_channel_layout = channel_layout_; 388 ChannelLayout output_channel_layout = channel_layout_;
379 if (channel_mixer_) { 389 if (channel_mixer_) {
380 output_bus = mixed_audio_bus_.get(); 390 output_bus = mixed_audio_bus_.get();
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 } else { 780 } else {
771 state_ = to; 781 state_ = to;
772 } 782 }
773 return state_; 783 return state_;
774 } 784 }
775 785
776 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() { 786 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() {
777 return state_; 787 return state_;
778 } 788 }
779 789
780 int AlsaPcmOutputStream::RunDataCallback(AudioBus* audio_bus, 790 int AlsaPcmOutputStream::RunDataCallback(base::TimeTicks target_playout_time,
781 uint32_t total_bytes_delay) { 791 AudioBus* audio_bus) {
782 TRACE_EVENT0("audio", "AlsaPcmOutputStream::RunDataCallback"); 792 TRACE_EVENT0("audio", "AlsaPcmOutputStream::RunDataCallback");
783 793
784 if (source_callback_) 794 if (source_callback_)
785 return source_callback_->OnMoreData(audio_bus, total_bytes_delay, 0); 795 return source_callback_->OnMoreData(target_playout_time, 0, audio_bus);
786 796
787 return 0; 797 return 0;
788 } 798 }
789 799
790 void AlsaPcmOutputStream::RunErrorCallback(int code) { 800 void AlsaPcmOutputStream::RunErrorCallback(int code) {
791 if (source_callback_) 801 if (source_callback_)
792 source_callback_->OnError(this); 802 source_callback_->OnError(this);
793 } 803 }
794 804
795 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to 805 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to
796 // release ownership of the currently registered callback. 806 // release ownership of the currently registered callback.
797 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) { 807 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
798 DCHECK(CalledOnValidThread()); 808 DCHECK(CalledOnValidThread());
799 source_callback_ = callback; 809 source_callback_ = callback;
800 } 810 }
801 811
802 } // namespace media 812 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698