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

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

Issue 743943002: Fixes crash in media::AudioBlockFifo::Push for Apple Thundebolt Displays (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Improved comments Created 6 years, 1 month 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 | « no previous file | 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_low_latency_input_mac.h" 5 #include "media/audio/mac/audio_low_latency_input_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/logging.h" 10 #include "base/logging.h"
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 reinterpret_cast<AUAudioInputStream*>(user_data); 459 reinterpret_cast<AUAudioInputStream*>(user_data);
460 DCHECK(audio_input); 460 DCHECK(audio_input);
461 if (!audio_input) 461 if (!audio_input)
462 return kAudioUnitErr_InvalidElement; 462 return kAudioUnitErr_InvalidElement;
463 463
464 // Update the |mDataByteSize| value in the audio_buffer_list() since 464 // Update the |mDataByteSize| value in the audio_buffer_list() since
465 // |number_of_frames| can be changed on the fly. 465 // |number_of_frames| can be changed on the fly.
466 // |mDataByteSize| needs to be exactly mapping to |number_of_frames|, 466 // |mDataByteSize| needs to be exactly mapping to |number_of_frames|,
467 // otherwise it will put CoreAudio into bad state and results in 467 // otherwise it will put CoreAudio into bad state and results in
468 // AudioUnitRender() returning -50 for the new created stream. 468 // AudioUnitRender() returning -50 for the new created stream.
469 // We have also seen kAudioUnitErr_TooManyFramesToProcess (-10874) and
470 // kAudioUnitErr_CannotDoInCurrentContext (-10863) as error codes.
469 // See crbug/428706 for details. 471 // See crbug/428706 for details.
470 UInt32 new_size = number_of_frames * audio_input->format_.mBytesPerFrame; 472 UInt32 new_size = number_of_frames * audio_input->format_.mBytesPerFrame;
471 AudioBuffer* audio_buffer = audio_input->audio_buffer_list()->mBuffers; 473 AudioBuffer* audio_buffer = audio_input->audio_buffer_list()->mBuffers;
472 if (new_size != audio_buffer->mDataByteSize) { 474 if (new_size != audio_buffer->mDataByteSize) {
473 if (new_size > audio_buffer->mDataByteSize) { 475 if (new_size > audio_buffer->mDataByteSize) {
474 // This can happen iff the device is unpluged during recording. In such 476 // This can happen if the device is unpluged during recording. We
475 // case the buffer will not be used anymore since |audio_unit_| becomes 477 // allocate enough memory here to avoid depending on how CoreAudio
476 // invalid. We allocate enough memory here to avoid depending on 478 // handles it.
477 // how CoreAudio handles it. 479 // See See http://www.crbug.com/434681 for one example when we can enter
480 // this scope.
478 audio_input->audio_data_buffer_.reset(new uint8[new_size]); 481 audio_input->audio_data_buffer_.reset(new uint8[new_size]);
479 audio_buffer->mData = audio_input->audio_data_buffer_.get(); 482 audio_buffer->mData = audio_input->audio_data_buffer_.get();
480 } 483 }
481 484
482 // Update the |mDataByteSize| to match |number_of_frames|. 485 // Update the |mDataByteSize| to match |number_of_frames|.
483 audio_buffer->mDataByteSize = new_size; 486 audio_buffer->mDataByteSize = new_size;
484 } 487 }
485 488
486 // Receive audio from the AUHAL from the output scope of the Audio Unit. 489 // Receive audio from the AUHAL from the output scope of the Audio Unit.
487 OSStatus result = AudioUnitRender(audio_input->audio_unit(), 490 OSStatus result = AudioUnitRender(audio_input->audio_unit(),
488 flags, 491 flags,
489 time_stamp, 492 time_stamp,
490 bus_number, 493 bus_number,
491 number_of_frames, 494 number_of_frames,
492 audio_input->audio_buffer_list()); 495 audio_input->audio_buffer_list());
493 if (result) { 496 if (result) {
494 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.AudioInputCbErrorMac", result); 497 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.AudioInputCbErrorMac", result);
495 OSSTATUS_DLOG(ERROR, result) << "AudioUnitRender() failed."; 498 OSSTATUS_DLOG(ERROR, result) << "AudioUnitRender() failed ";
496 return result; 499 return result;
497 } 500 }
498 501
499 // Deliver recorded data to the consumer as a callback. 502 // Deliver recorded data to the consumer as a callback.
500 return audio_input->Provide(number_of_frames, 503 return audio_input->Provide(number_of_frames,
501 audio_input->audio_buffer_list(), 504 audio_input->audio_buffer_list(),
502 time_stamp); 505 time_stamp);
503 } 506 }
504 507
505 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, 508 OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames,
506 AudioBufferList* io_data, 509 AudioBufferList* io_data,
507 const AudioTimeStamp* time_stamp) { 510 const AudioTimeStamp* time_stamp) {
508 // Update the capture latency. 511 // Update the capture latency.
509 double capture_latency_frames = GetCaptureLatency(time_stamp); 512 double capture_latency_frames = GetCaptureLatency(time_stamp);
510 513
511 // The AGC volume level is updated once every second on a separate thread. 514 // The AGC volume level is updated once every second on a separate thread.
512 // Note that, |volume| is also updated each time SetVolume() is called 515 // Note that, |volume| is also updated each time SetVolume() is called
513 // through IPC by the render-side AGC. 516 // through IPC by the render-side AGC.
514 double normalized_volume = 0.0; 517 double normalized_volume = 0.0;
515 GetAgcVolume(&normalized_volume); 518 GetAgcVolume(&normalized_volume);
516 519
517 AudioBuffer& buffer = io_data->mBuffers[0]; 520 AudioBuffer& buffer = io_data->mBuffers[0];
518 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); 521 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData);
519 uint32 capture_delay_bytes = static_cast<uint32> 522 uint32 capture_delay_bytes = static_cast<uint32>
520 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); 523 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame);
521 DCHECK(audio_data); 524 DCHECK(audio_data);
522 if (!audio_data) 525 if (!audio_data)
523 return kAudioUnitErr_InvalidElement; 526 return kAudioUnitErr_InvalidElement;
524 527
528 // Dynamically increase capacity of the FIFO to handle larger buffers from
529 // CoreAudio. This can happen in combination with Apple Thunderbolt Displays
530 // when the Display Audio is used as capture source and the cable is first
531 // remove and then inserted again.
532 // See http://www.crbug.com/434681 for details.
533 if (static_cast<int>(number_of_frames) > fifo_.GetUnfilledFrames()) {
534 // Derive required increase in number of FIFO blocks. The increase is
535 // typically one block.
536 const int blocks =
537 static_cast<int>((number_of_frames - fifo_.GetUnfilledFrames()) /
538 number_of_frames_) + 1;
539 DLOG(WARNING) << "Increasing FIFO capacity by " << blocks << " blocks";
540 fifo_.IncreaseCapacity(blocks);
541 }
542
525 // Copy captured (and interleaved) data into FIFO. 543 // Copy captured (and interleaved) data into FIFO.
526 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); 544 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8);
527 545
528 // Consume and deliver the data when the FIFO has a block of available data. 546 // Consume and deliver the data when the FIFO has a block of available data.
529 while (fifo_.available_blocks()) { 547 while (fifo_.available_blocks()) {
530 const AudioBus* audio_bus = fifo_.Consume(); 548 const AudioBus* audio_bus = fifo_.Consume();
531 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); 549 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_));
532 550
533 // Compensate the audio delay caused by the FIFO. 551 // Compensate the audio delay caused by the FIFO.
534 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; 552 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 kAudioDevicePropertyScopeInput, 685 kAudioDevicePropertyScopeInput,
668 static_cast<UInt32>(channel) 686 static_cast<UInt32>(channel)
669 }; 687 };
670 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, 688 OSStatus result = AudioObjectIsPropertySettable(input_device_id_,
671 &property_address, 689 &property_address,
672 &is_settable); 690 &is_settable);
673 return (result == noErr) ? is_settable : false; 691 return (result == noErr) ? is_settable : false;
674 } 692 }
675 693
676 } // namespace media 694 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698