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

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

Issue 2914593002: Replace deprecated base::NonThreadSafe in media/audio in favor of SequenceChecker. (Closed)
Patch Set: Created 3 years, 6 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
« no previous file with comments | « media/audio/alsa/alsa_output.h ('k') | media/audio/sounds/audio_stream_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 TransitionTo(kInError); 179 TransitionTo(kInError);
180 } 180 }
181 181
182 if (pcm_format_ == SND_PCM_FORMAT_UNKNOWN) { 182 if (pcm_format_ == SND_PCM_FORMAT_UNKNOWN) {
183 LOG(WARNING) << "Unsupported bits per sample: " << params.bits_per_sample(); 183 LOG(WARNING) << "Unsupported bits per sample: " << params.bits_per_sample();
184 TransitionTo(kInError); 184 TransitionTo(kInError);
185 } 185 }
186 } 186 }
187 187
188 AlsaPcmOutputStream::~AlsaPcmOutputStream() { 188 AlsaPcmOutputStream::~AlsaPcmOutputStream() {
189 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
189 InternalState current_state = state(); 190 InternalState current_state = state();
190 DCHECK(current_state == kCreated || 191 DCHECK(current_state == kCreated ||
191 current_state == kIsClosed || 192 current_state == kIsClosed ||
192 current_state == kInError); 193 current_state == kInError);
193 DCHECK(!playback_handle_); 194 DCHECK(!playback_handle_);
194 } 195 }
195 196
196 bool AlsaPcmOutputStream::Open() { 197 bool AlsaPcmOutputStream::Open() {
197 DCHECK(CalledOnValidThread()); 198 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
198 199
199 if (state() == kInError) 200 if (state() == kInError)
200 return false; 201 return false;
201 202
202 if (!CanTransitionTo(kIsOpened)) { 203 if (!CanTransitionTo(kIsOpened)) {
203 NOTREACHED() << "Invalid state: " << state(); 204 NOTREACHED() << "Invalid state: " << state();
204 return false; 205 return false;
205 } 206 }
206 207
207 // We do not need to check if the transition was successful because 208 // We do not need to check if the transition was successful because
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 // Buffer size is at least twice of packet size. 246 // Buffer size is at least twice of packet size.
246 alsa_buffer_frames_ = frames_per_packet_ * 2; 247 alsa_buffer_frames_ = frames_per_packet_ * 2;
247 } else { 248 } else {
248 alsa_buffer_frames_ = buffer_size; 249 alsa_buffer_frames_ = buffer_size;
249 } 250 }
250 251
251 return true; 252 return true;
252 } 253 }
253 254
254 void AlsaPcmOutputStream::Close() { 255 void AlsaPcmOutputStream::Close() {
255 DCHECK(CalledOnValidThread()); 256 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
256 257
257 if (state() != kIsClosed) 258 if (state() != kIsClosed)
258 TransitionTo(kIsClosed); 259 TransitionTo(kIsClosed);
259 260
260 // Shutdown the audio device. 261 // Shutdown the audio device.
261 if (playback_handle_) { 262 if (playback_handle_) {
262 if (alsa_util::CloseDevice(wrapper_, playback_handle_) < 0) { 263 if (alsa_util::CloseDevice(wrapper_, playback_handle_) < 0) {
263 LOG(WARNING) << "Unable to close audio device. Leaking handle."; 264 LOG(WARNING) << "Unable to close audio device. Leaking handle.";
264 } 265 }
265 playback_handle_ = NULL; 266 playback_handle_ = NULL;
266 267
267 // Release the buffer. 268 // Release the buffer.
268 buffer_.reset(); 269 buffer_.reset();
269 270
270 // Signal anything that might already be scheduled to stop. 271 // Signal anything that might already be scheduled to stop.
271 stop_stream_ = true; // Not necessary in production, but unit tests 272 stop_stream_ = true; // Not necessary in production, but unit tests
272 // uses the flag to verify that stream was closed. 273 // uses the flag to verify that stream was closed.
273 } 274 }
274 275
275 weak_factory_.InvalidateWeakPtrs(); 276 weak_factory_.InvalidateWeakPtrs();
276 277
277 // Signal to the manager that we're closed and can be removed. 278 // Signal to the manager that we're closed and can be removed.
278 // Should be last call in the method as it deletes "this". 279 // Should be last call in the method as it deletes "this".
279 manager_->ReleaseOutputStream(this); 280 manager_->ReleaseOutputStream(this);
280 } 281 }
281 282
282 void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) { 283 void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) {
283 DCHECK(CalledOnValidThread()); 284 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
284 285
285 CHECK(callback); 286 CHECK(callback);
286 287
287 if (stop_stream_) 288 if (stop_stream_)
288 return; 289 return;
289 290
290 // Only post the task if we can enter the playing state. 291 // Only post the task if we can enter the playing state.
291 if (TransitionTo(kIsPlaying) != kIsPlaying) 292 if (TransitionTo(kIsPlaying) != kIsPlaying)
292 return; 293 return;
293 294
(...skipping 28 matching lines...) Expand all
322 memset(silent_packet->writable_data(), 0, silent_packet->data_size()); 323 memset(silent_packet->writable_data(), 0, silent_packet->data_size());
323 buffer_->Append(silent_packet); 324 buffer_->Append(silent_packet);
324 WritePacket(); 325 WritePacket();
325 326
326 // Start the callback chain. 327 // Start the callback chain.
327 set_source_callback(callback); 328 set_source_callback(callback);
328 WriteTask(); 329 WriteTask();
329 } 330 }
330 331
331 void AlsaPcmOutputStream::Stop() { 332 void AlsaPcmOutputStream::Stop() {
332 DCHECK(CalledOnValidThread()); 333 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
333 334
334 // Reset the callback, so that it is not called anymore. 335 // Reset the callback, so that it is not called anymore.
335 set_source_callback(NULL); 336 set_source_callback(NULL);
336 weak_factory_.InvalidateWeakPtrs(); 337 weak_factory_.InvalidateWeakPtrs();
337 338
338 TransitionTo(kIsStopped); 339 TransitionTo(kIsStopped);
339 } 340 }
340 341
341 void AlsaPcmOutputStream::SetVolume(double volume) { 342 void AlsaPcmOutputStream::SetVolume(double volume) {
342 DCHECK(CalledOnValidThread()); 343 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
343 344
344 volume_ = static_cast<float>(volume); 345 volume_ = static_cast<float>(volume);
345 } 346 }
346 347
347 void AlsaPcmOutputStream::GetVolume(double* volume) { 348 void AlsaPcmOutputStream::GetVolume(double* volume) {
348 DCHECK(CalledOnValidThread()); 349 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
349 350
350 *volume = volume_; 351 *volume = volume_;
351 } 352 }
352 353
353 void AlsaPcmOutputStream::SetTickClockForTesting( 354 void AlsaPcmOutputStream::SetTickClockForTesting(
354 std::unique_ptr<base::TickClock> tick_clock) { 355 std::unique_ptr<base::TickClock> tick_clock) {
355 DCHECK(tick_clock); 356 DCHECK(tick_clock);
356 tick_clock_ = std::move(tick_clock); 357 tick_clock_ = std::move(tick_clock);
357 } 358 }
358 359
359 void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) { 360 void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
360 DCHECK(CalledOnValidThread()); 361 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
361 362
362 // If stopped, simulate a 0-length packet. 363 // If stopped, simulate a 0-length packet.
363 if (stop_stream_) { 364 if (stop_stream_) {
364 buffer_->Clear(); 365 buffer_->Clear();
365 *source_exhausted = true; 366 *source_exhausted = true;
366 return; 367 return;
367 } 368 }
368 369
369 *source_exhausted = false; 370 *source_exhausted = false;
370 371
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 packet->set_data_size(packet_size); 425 packet->set_data_size(packet_size);
425 // Add the packet to the buffer. 426 // Add the packet to the buffer.
426 buffer_->Append(packet); 427 buffer_->Append(packet);
427 } else { 428 } else {
428 *source_exhausted = true; 429 *source_exhausted = true;
429 } 430 }
430 } 431 }
431 } 432 }
432 433
433 void AlsaPcmOutputStream::WritePacket() { 434 void AlsaPcmOutputStream::WritePacket() {
434 DCHECK(CalledOnValidThread()); 435 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
435 436
436 // If the device is in error, just eat the bytes. 437 // If the device is in error, just eat the bytes.
437 if (stop_stream_) { 438 if (stop_stream_) {
438 buffer_->Clear(); 439 buffer_->Clear();
439 return; 440 return;
440 } 441 }
441 442
442 if (state() != kIsPlaying) 443 if (state() != kIsPlaying)
443 return; 444 return;
444 445
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // This ensures that shorter sounds will still play. 484 // This ensures that shorter sounds will still play.
484 if (playback_handle_ && 485 if (playback_handle_ &&
485 (wrapper_->PcmState(playback_handle_) == SND_PCM_STATE_PREPARED) && 486 (wrapper_->PcmState(playback_handle_) == SND_PCM_STATE_PREPARED) &&
486 GetCurrentDelay() > 0) { 487 GetCurrentDelay() > 0) {
487 wrapper_->PcmStart(playback_handle_); 488 wrapper_->PcmStart(playback_handle_);
488 } 489 }
489 } 490 }
490 } 491 }
491 492
492 void AlsaPcmOutputStream::WriteTask() { 493 void AlsaPcmOutputStream::WriteTask() {
493 DCHECK(CalledOnValidThread()); 494 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
494 495
495 if (stop_stream_) 496 if (stop_stream_)
496 return; 497 return;
497 498
498 if (state() == kIsStopped) 499 if (state() == kIsStopped)
499 return; 500 return;
500 501
501 bool source_exhausted; 502 bool source_exhausted;
502 BufferPacket(&source_exhausted); 503 BufferPacket(&source_exhausted);
503 WritePacket(); 504 WritePacket();
504 505
505 ScheduleNextWrite(source_exhausted); 506 ScheduleNextWrite(source_exhausted);
506 } 507 }
507 508
508 void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) { 509 void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) {
509 DCHECK(CalledOnValidThread()); 510 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
510 511
511 if (stop_stream_ || state() != kIsPlaying) 512 if (stop_stream_ || state() != kIsPlaying)
512 return; 513 return;
513 514
514 const uint32_t kTargetFramesAvailable = alsa_buffer_frames_ / 2; 515 const uint32_t kTargetFramesAvailable = alsa_buffer_frames_ / 2;
515 uint32_t available_frames = GetAvailableFrames(); 516 uint32_t available_frames = GetAvailableFrames();
516 517
517 base::TimeDelta next_fill_time; 518 base::TimeDelta next_fill_time;
518 if (buffer_->forward_bytes() && available_frames) { 519 if (buffer_->forward_bytes() && available_frames) {
519 // If we've got data available and ALSA has room, deliver it immediately. 520 // If we've got data available and ALSA has room, deliver it immediately.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 } 627 }
627 628
628 if (delay < 0) { 629 if (delay < 0) {
629 delay = 0; 630 delay = 0;
630 } 631 }
631 632
632 return delay; 633 return delay;
633 } 634 }
634 635
635 snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() { 636 snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() {
636 DCHECK(CalledOnValidThread()); 637 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
637 638
638 if (stop_stream_) 639 if (stop_stream_)
639 return 0; 640 return 0;
640 641
641 // Find the number of frames queued in the sound device. 642 // Find the number of frames queued in the sound device.
642 snd_pcm_sframes_t available_frames = 643 snd_pcm_sframes_t available_frames =
643 wrapper_->PcmAvailUpdate(playback_handle_); 644 wrapper_->PcmAvailUpdate(playback_handle_);
644 if (available_frames < 0) { 645 if (available_frames < 0) {
645 available_frames = wrapper_->PcmRecover(playback_handle_, 646 available_frames = wrapper_->PcmRecover(playback_handle_,
646 available_frames, 647 available_frames,
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 return to == kIsClosed || to == kInError; 760 return to == kIsClosed || to == kInError;
760 761
761 case kIsClosed: 762 case kIsClosed:
762 default: 763 default:
763 return false; 764 return false;
764 } 765 }
765 } 766 }
766 767
767 AlsaPcmOutputStream::InternalState 768 AlsaPcmOutputStream::InternalState
768 AlsaPcmOutputStream::TransitionTo(InternalState to) { 769 AlsaPcmOutputStream::TransitionTo(InternalState to) {
769 DCHECK(CalledOnValidThread()); 770 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
770 771
771 if (!CanTransitionTo(to)) { 772 if (!CanTransitionTo(to)) {
772 NOTREACHED() << "Cannot transition from: " << state_ << " to: " << to; 773 NOTREACHED() << "Cannot transition from: " << state_ << " to: " << to;
773 state_ = kInError; 774 state_ = kInError;
774 } else { 775 } else {
775 state_ = to; 776 state_ = to;
776 } 777 }
777 return state_; 778 return state_;
778 } 779 }
779 780
(...skipping 13 matching lines...) Expand all
793 } 794 }
794 795
795 void AlsaPcmOutputStream::RunErrorCallback(int code) { 796 void AlsaPcmOutputStream::RunErrorCallback(int code) {
796 if (source_callback_) 797 if (source_callback_)
797 source_callback_->OnError(); 798 source_callback_->OnError();
798 } 799 }
799 800
800 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to 801 // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to
801 // release ownership of the currently registered callback. 802 // release ownership of the currently registered callback.
802 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) { 803 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
803 DCHECK(CalledOnValidThread()); 804 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
804 source_callback_ = callback; 805 source_callback_ = callback;
805 } 806 }
806 807
807 } // namespace media 808 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/alsa/alsa_output.h ('k') | media/audio/sounds/audio_stream_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698