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

Side by Side Diff: media/audio/mac/audio_output_mac.cc

Issue 10583009: Revert 142862 - Change the way we are stopping audio stream on Mac once again. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/mac/audio_output_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/audio/mac/audio_output_mac.h" 5 #include "media/audio/mac/audio_output_mac.h"
6 6
7 #include <CoreServices/CoreServices.h> 7 #include <CoreServices/CoreServices.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 packet_size_(params.GetBytesPerBuffer()), 53 packet_size_(params.GetBytesPerBuffer()),
54 silence_bytes_(0), 54 silence_bytes_(0),
55 volume_(1), 55 volume_(1),
56 pending_bytes_(0), 56 pending_bytes_(0),
57 num_source_channels_(params.channels()), 57 num_source_channels_(params.channels()),
58 source_layout_(params.channel_layout()), 58 source_layout_(params.channel_layout()),
59 num_core_channels_(0), 59 num_core_channels_(0),
60 should_swizzle_(false), 60 should_swizzle_(false),
61 should_down_mix_(false), 61 should_down_mix_(false),
62 stopped_event_(true /* manual reset */, false /* initial state */), 62 stopped_event_(true /* manual reset */, false /* initial state */),
63 stop_requested_(false) { 63 num_buffers_left_(kNumBuffers) {
64 // We must have a manager. 64 // We must have a manager.
65 DCHECK(manager_); 65 DCHECK(manager_);
66 // A frame is one sample across all channels. In interleaved audio the per 66 // A frame is one sample across all channels. In interleaved audio the per
67 // frame fields identify the set of n |channels|. In uncompressed audio, a 67 // frame fields identify the set of n |channels|. In uncompressed audio, a
68 // packet is always one frame. 68 // packet is always one frame.
69 format_.mSampleRate = params.sample_rate(); 69 format_.mSampleRate = params.sample_rate();
70 format_.mFormatID = kAudioFormatLinearPCM; 70 format_.mFormatID = kAudioFormatLinearPCM;
71 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked; 71 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked;
72 format_.mBitsPerChannel = params.bits_per_sample(); 72 format_.mBitsPerChannel = params.bits_per_sample();
73 format_.mChannelsPerFrame = params.channels(); 73 format_.mChannelsPerFrame = params.channels();
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 core_channel_orderings_[input_channel] == kEmptyChannel && 372 core_channel_orderings_[input_channel] == kEmptyChannel &&
373 kChannelOrderings[source_layout_][input_channel] > kEmptyChannel && 373 kChannelOrderings[source_layout_][input_channel] > kEmptyChannel &&
374 kChannelOrderings[source_layout_][output_channel] == kEmptyChannel) { 374 kChannelOrderings[source_layout_][output_channel] == kEmptyChannel) {
375 channel_remap_[core_channel_orderings_[output_channel]] = 375 channel_remap_[core_channel_orderings_[output_channel]] =
376 kChannelOrderings[source_layout_][input_channel]; 376 kChannelOrderings[source_layout_][input_channel];
377 return true; 377 return true;
378 } 378 }
379 return false; 379 return false;
380 } 380 }
381 381
382 void PCMQueueOutAudioOutputStream::IsRunningCallback(
383 void* p_this,
384 AudioQueueRef queue,
385 AudioQueuePropertyID inID) {
386 PCMQueueOutAudioOutputStream* audio_stream =
387 static_cast<PCMQueueOutAudioOutputStream*>(p_this);
388 UInt32 running = 0;
389 UInt32 size = sizeof(running);
390 OSStatus err = AudioQueueGetProperty(queue,
391 kAudioQueueProperty_IsRunning,
392 &running,
393 &size);
394 if (err) {
395 audio_stream->HandleError(err);
396 return;
397 }
398 if (!running) {
399 // Remove property listener, we don't need it anymore.
400 OSStatus err = AudioQueueRemovePropertyListener(
401 queue,
402 kAudioQueueProperty_IsRunning,
403 PCMQueueOutAudioOutputStream::IsRunningCallback,
404 audio_stream);
405 if (err != noErr)
406 audio_stream->HandleError(err);
407
408 // Ok, finally signal that stream is not running.
409 audio_stream->stopped_event_.Signal();
410 }
411 }
412
413 // Note to future hackers of this function: Do not add locks to this function 382 // Note to future hackers of this function: Do not add locks to this function
414 // that are held through any calls made back into AudioQueue APIs, or other 383 // that are held through any calls made back into AudioQueue APIs, or other
415 // OS audio functions. This is because the OS dispatch may grab external 384 // OS audio functions. This is because the OS dispatch may grab external
416 // locks, or possibly re-enter this function which can lead to a deadlock. 385 // locks, or possibly re-enter this function which can lead to a deadlock.
417 void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this, 386 void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this,
418 AudioQueueRef queue, 387 AudioQueueRef queue,
419 AudioQueueBufferRef buffer) { 388 AudioQueueBufferRef buffer) {
420 TRACE_EVENT0("audio", "PCMQueueOutAudioOutputStream::RenderCallback"); 389 TRACE_EVENT0("audio", "PCMQueueOutAudioOutputStream::RenderCallback");
421 390
422 PCMQueueOutAudioOutputStream* audio_stream = 391 PCMQueueOutAudioOutputStream* audio_stream =
423 static_cast<PCMQueueOutAudioOutputStream*>(p_this); 392 static_cast<PCMQueueOutAudioOutputStream*>(p_this);
424 393
425 // Call the audio source to fill the free buffer with data. Not having a 394 // Call the audio source to fill the free buffer with data. Not having a
426 // source means that the queue has been stopped. 395 // source means that the queue has been stopped.
427 AudioSourceCallback* source = audio_stream->GetSource(); 396 AudioSourceCallback* source = audio_stream->GetSource();
428 if (!source) { 397 if (!source) {
429 // PCMQueueOutAudioOutputStream::Stop() is waiting for callback to 398 // PCMQueueOutAudioOutputStream::Stop() is waiting for callback to
430 // stop the stream and signal when all activity ceased (we probably 399 // stop the stream and signal when all callbacks are done.
431 // can stop the stream there, but it is better to have all the 400 // (we probably can stop the stream there, but it is better to have
432 // complex logic in one place; stopping latency is not very important 401 // all the complex logic in one place; stopping latency is not very
433 // if you reuse audio stream in the mixer and not close it immediately). 402 // important if you reuse audio stream in the mixer and not close it
434 if (!audio_stream->stop_requested_) { 403 // immediately).
435 audio_stream->stop_requested_ = true; 404 --audio_stream->num_buffers_left_;
436 // Before actually stopping the stream, register callback that 405 if (audio_stream->num_buffers_left_ == kNumBuffers - 1) {
437 // OS would call when status of "is running" property changes. 406 // First buffer after stop requested, stop the queue.
438 // This way we (hopefully) would know when stream is actually 407 OSStatus err = AudioQueueStop(audio_stream->audio_queue_, true);
439 // stopped and it is safe to dispose it.
440 OSStatus err = AudioQueueAddPropertyListener(
441 queue,
442 kAudioQueueProperty_IsRunning,
443 PCMQueueOutAudioOutputStream::IsRunningCallback,
444 audio_stream);
445 if (err != noErr) 408 if (err != noErr)
446 audio_stream->HandleError(err); 409 audio_stream->HandleError(err);
447 // Now stop the queue. 410 }
448 err = AudioQueueStop(queue, true); 411 if (audio_stream->num_buffers_left_ == 0) {
449 if (err != noErr) 412 // Now we finally saw all the buffers.
450 audio_stream->HandleError(err); 413 // Signal that stopping is complete.
414 // Should never touch audio_stream after signaling as it
415 // can be deleted at any moment.
416 audio_stream->stopped_event_.Signal();
451 } 417 }
452 return; 418 return;
453 } 419 }
454 420
455 // Adjust the number of pending bytes by subtracting the amount played. 421 // Adjust the number of pending bytes by subtracting the amount played.
456 if (!static_cast<AudioQueueUserData*>(buffer->mUserData)->empty_buffer) 422 if (!static_cast<AudioQueueUserData*>(buffer->mUserData)->empty_buffer)
457 audio_stream->pending_bytes_ -= buffer->mAudioDataByteSize; 423 audio_stream->pending_bytes_ -= buffer->mAudioDataByteSize;
458 uint32 capacity = buffer->mAudioDataBytesCapacity; 424 uint32 capacity = buffer->mAudioDataBytesCapacity;
459 // TODO(sergeyu): Specify correct hardware delay for AudioBuffersState. 425 // TODO(sergeyu): Specify correct hardware delay for AudioBuffersState.
460 uint32 filled = source->OnMoreData( 426 uint32 filled = source->OnMoreData(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) { 502 void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) {
537 DCHECK(callback); 503 DCHECK(callback);
538 DLOG_IF(ERROR, !audio_queue_) << "Open() has not been called successfully"; 504 DLOG_IF(ERROR, !audio_queue_) << "Open() has not been called successfully";
539 if (!audio_queue_) 505 if (!audio_queue_)
540 return; 506 return;
541 507
542 OSStatus err = noErr; 508 OSStatus err = noErr;
543 SetSource(callback); 509 SetSource(callback);
544 pending_bytes_ = 0; 510 pending_bytes_ = 0;
545 stopped_event_.Reset(); 511 stopped_event_.Reset();
546 stop_requested_ = false; 512 num_buffers_left_ = kNumBuffers;
547 // Ask the source to pre-fill all our buffers before playing. 513 // Ask the source to pre-fill all our buffers before playing.
548 for (uint32 ix = 0; ix != kNumBuffers; ++ix) { 514 for (uint32 ix = 0; ix != kNumBuffers; ++ix) {
549 buffer_[ix]->mAudioDataByteSize = 0; 515 buffer_[ix]->mAudioDataByteSize = 0;
550 // Caller waits for 1st packet to become available, but not for others, 516 // Caller waits for 1st packet to become available, but not for others,
551 // so we wait for them here. 517 // so we wait for them here.
552 if (ix != 0) { 518 if (ix != 0) {
553 AudioSourceCallback* source = GetSource(); 519 AudioSourceCallback* source = GetSource();
554 if (source) 520 if (source)
555 source->WaitTillDataReady(); 521 source->WaitTillDataReady();
556 } 522 }
(...skipping 20 matching lines...) Expand all
577 source_ = source; 543 source_ = source;
578 } 544 }
579 545
580 AudioOutputStream::AudioSourceCallback* 546 AudioOutputStream::AudioSourceCallback*
581 PCMQueueOutAudioOutputStream::GetSource() { 547 PCMQueueOutAudioOutputStream::GetSource() {
582 base::AutoLock lock(source_lock_); 548 base::AutoLock lock(source_lock_);
583 return source_; 549 return source_;
584 } 550 }
585 551
586 } // namespace media 552 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/mac/audio_output_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698