OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 case AVAudioSessionRouteChangeReasonUnknown: | 575 case AVAudioSessionRouteChangeReasonUnknown: |
576 LOG(LS_INFO) << " ReasonUnknown"; | 576 LOG(LS_INFO) << " ReasonUnknown"; |
577 break; | 577 break; |
578 case AVAudioSessionRouteChangeReasonNewDeviceAvailable: | 578 case AVAudioSessionRouteChangeReasonNewDeviceAvailable: |
579 LOG(LS_INFO) << " NewDeviceAvailable"; | 579 LOG(LS_INFO) << " NewDeviceAvailable"; |
580 break; | 580 break; |
581 case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: | 581 case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: |
582 LOG(LS_INFO) << " OldDeviceUnavailable"; | 582 LOG(LS_INFO) << " OldDeviceUnavailable"; |
583 break; | 583 break; |
584 case AVAudioSessionRouteChangeReasonCategoryChange: | 584 case AVAudioSessionRouteChangeReasonCategoryChange: |
| 585 // It turns out that we see this notification (at least in iOS 9.2) |
| 586 // when making a switch from a BT device to e.g. Speaker using the |
| 587 // iOS Control Center and that we therefore must check if the sample |
| 588 // rate has changed. And if so is the case, restart the audio unit. |
585 LOG(LS_INFO) << " CategoryChange"; | 589 LOG(LS_INFO) << " CategoryChange"; |
586 LOG(LS_INFO) << " New category: " << ios::GetAudioSessionCategory(); | 590 LOG(LS_INFO) << " New category: " << ios::GetAudioSessionCategory(); |
587 // Don't see this as route change since it can be triggered in | |
588 // combination with session interruptions as well. | |
589 valid_route_change = false; | |
590 break; | 591 break; |
591 case AVAudioSessionRouteChangeReasonOverride: | 592 case AVAudioSessionRouteChangeReasonOverride: |
592 LOG(LS_INFO) << " Override"; | 593 LOG(LS_INFO) << " Override"; |
593 break; | 594 break; |
594 case AVAudioSessionRouteChangeReasonWakeFromSleep: | 595 case AVAudioSessionRouteChangeReasonWakeFromSleep: |
595 LOG(LS_INFO) << " WakeFromSleep"; | 596 LOG(LS_INFO) << " WakeFromSleep"; |
596 break; | 597 break; |
597 case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory: | 598 case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory: |
598 LOG(LS_INFO) << " NoSuitableRouteForCategory"; | 599 LOG(LS_INFO) << " NoSuitableRouteForCategory"; |
599 break; | 600 break; |
600 case AVAudioSessionRouteChangeReasonRouteConfigurationChange: | 601 case AVAudioSessionRouteChangeReasonRouteConfigurationChange: |
601 // Ignore this type of route change since we are focusing | 602 // The set of input and output ports has not changed, but their |
| 603 // configuration has, e.g., a port’s selected data source has |
| 604 // changed. Ignore this type of route change since we are focusing |
602 // on detecting headset changes. | 605 // on detecting headset changes. |
603 LOG(LS_INFO) << " RouteConfigurationChange"; | 606 LOG(LS_INFO) << " RouteConfigurationChange (ignored)"; |
604 valid_route_change = false; | 607 valid_route_change = false; |
605 break; | 608 break; |
606 } | 609 } |
607 | 610 |
608 if (valid_route_change) { | 611 if (valid_route_change) { |
609 // Log previous route configuration. | 612 // Log previous route configuration. |
610 AVAudioSessionRouteDescription* prev_route = | 613 AVAudioSessionRouteDescription* prev_route = |
611 notification.userInfo[AVAudioSessionRouteChangePreviousRouteKey]; | 614 notification.userInfo[AVAudioSessionRouteChangePreviousRouteKey]; |
612 LOG(LS_INFO) << "Previous route:"; | 615 LOG(LS_INFO) << "Previous route:"; |
613 LOG(LS_INFO) << ios::StdStringFromNSString( | 616 LOG(LS_INFO) << ios::StdStringFromNSString( |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 application_format_.mSampleRate = playout_parameters_.sample_rate(); | 930 application_format_.mSampleRate = playout_parameters_.sample_rate(); |
928 UInt32 size = sizeof(application_format_); | 931 UInt32 size = sizeof(application_format_); |
929 AudioUnitSetProperty(vpio_unit_, kAudioUnitProperty_StreamFormat, | 932 AudioUnitSetProperty(vpio_unit_, kAudioUnitProperty_StreamFormat, |
930 kAudioUnitScope_Output, 1, &application_format_, size); | 933 kAudioUnitScope_Output, 1, &application_format_, size); |
931 AudioUnitSetProperty(vpio_unit_, kAudioUnitProperty_StreamFormat, | 934 AudioUnitSetProperty(vpio_unit_, kAudioUnitProperty_StreamFormat, |
932 kAudioUnitScope_Input, 0, &application_format_, size); | 935 kAudioUnitScope_Input, 0, &application_format_, size); |
933 | 936 |
934 // Prepare the audio unit to render audio again. | 937 // Prepare the audio unit to render audio again. |
935 LOG_AND_RETURN_IF_ERROR(AudioUnitInitialize(vpio_unit_), | 938 LOG_AND_RETURN_IF_ERROR(AudioUnitInitialize(vpio_unit_), |
936 "Failed to initialize the Voice-Processing I/O unit"); | 939 "Failed to initialize the Voice-Processing I/O unit"); |
| 940 LOG(LS_INFO) << "Voice-Processing I/O unit is now reinitialized"; |
937 | 941 |
938 // Start rendering audio using the new format. | 942 // Start rendering audio using the new format. |
939 LOG_AND_RETURN_IF_ERROR(AudioOutputUnitStart(vpio_unit_), | 943 LOG_AND_RETURN_IF_ERROR(AudioOutputUnitStart(vpio_unit_), |
940 "Failed to start the Voice-Processing I/O unit"); | 944 "Failed to start the Voice-Processing I/O unit"); |
| 945 LOG(LS_INFO) << "Voice-Processing I/O unit is now restarted"; |
941 return true; | 946 return true; |
942 } | 947 } |
943 | 948 |
944 bool AudioDeviceIOS::InitPlayOrRecord() { | 949 bool AudioDeviceIOS::InitPlayOrRecord() { |
945 LOGI() << "InitPlayOrRecord"; | 950 LOGI() << "InitPlayOrRecord"; |
946 // Activate the audio session if not already activated. | 951 // Activate the audio session if not already activated. |
947 if (!ActivateAudioSession()) { | 952 if (!ActivateAudioSession()) { |
948 return false; | 953 return false; |
949 } | 954 } |
950 | 955 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 const AudioTimeStamp* in_time_stamp, | 1031 const AudioTimeStamp* in_time_stamp, |
1027 UInt32 in_bus_number, | 1032 UInt32 in_bus_number, |
1028 UInt32 in_number_frames) { | 1033 UInt32 in_number_frames) { |
1029 OSStatus result = noErr; | 1034 OSStatus result = noErr; |
1030 // Simply return if recording is not enabled. | 1035 // Simply return if recording is not enabled. |
1031 if (!rtc::AtomicOps::AcquireLoad(&recording_)) | 1036 if (!rtc::AtomicOps::AcquireLoad(&recording_)) |
1032 return result; | 1037 return result; |
1033 if (in_number_frames != record_parameters_.frames_per_buffer()) { | 1038 if (in_number_frames != record_parameters_.frames_per_buffer()) { |
1034 // We have seen short bursts (1-2 frames) where |in_number_frames| changes. | 1039 // We have seen short bursts (1-2 frames) where |in_number_frames| changes. |
1035 // Add a log to keep track of longer sequences if that should ever happen. | 1040 // Add a log to keep track of longer sequences if that should ever happen. |
| 1041 // Also return since calling AudioUnitRender in this state will only result |
| 1042 // in kAudio_ParamError (-50) anyhow. |
1036 LOG(LS_WARNING) << "in_number_frames (" << in_number_frames | 1043 LOG(LS_WARNING) << "in_number_frames (" << in_number_frames |
1037 << ") != " << record_parameters_.frames_per_buffer(); | 1044 << ") != " << record_parameters_.frames_per_buffer(); |
| 1045 return noErr; |
1038 } | 1046 } |
1039 // Obtain the recorded audio samples by initiating a rendering cycle. | 1047 // Obtain the recorded audio samples by initiating a rendering cycle. |
1040 // Since it happens on the input bus, the |io_data| parameter is a reference | 1048 // Since it happens on the input bus, the |io_data| parameter is a reference |
1041 // to the preallocated audio buffer list that the audio unit renders into. | 1049 // to the preallocated audio buffer list that the audio unit renders into. |
1042 // TODO(henrika): should error handling be improved? | 1050 // TODO(henrika): should error handling be improved? |
1043 AudioBufferList* io_data = &audio_record_buffer_list_; | 1051 AudioBufferList* io_data = &audio_record_buffer_list_; |
1044 result = AudioUnitRender(vpio_unit_, io_action_flags, in_time_stamp, | 1052 result = AudioUnitRender(vpio_unit_, io_action_flags, in_time_stamp, |
1045 in_bus_number, in_number_frames, io_data); | 1053 in_bus_number, in_number_frames, io_data); |
1046 if (result != noErr) { | 1054 if (result != noErr) { |
1047 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result; | 1055 LOG_F(LS_ERROR) << "AudioUnitRender failed: " << result; |
1048 return result; | 1056 return result; |
1049 } | 1057 } |
1050 // Get a pointer to the recorded audio and send it to the WebRTC ADB. | 1058 // Get a pointer to the recorded audio and send it to the WebRTC ADB. |
1051 // Use the FineAudioBuffer instance to convert between native buffer size | 1059 // Use the FineAudioBuffer instance to convert between native buffer size |
1052 // and the 10ms buffer size used by WebRTC. | 1060 // and the 10ms buffer size used by WebRTC. |
1053 const UInt32 data_size_in_bytes = io_data->mBuffers[0].mDataByteSize; | 1061 const UInt32 data_size_in_bytes = io_data->mBuffers[0].mDataByteSize; |
1054 RTC_CHECK_EQ(data_size_in_bytes / kBytesPerSample, in_number_frames); | 1062 RTC_CHECK_EQ(data_size_in_bytes / kBytesPerSample, in_number_frames); |
1055 SInt8* data = static_cast<SInt8*>(io_data->mBuffers[0].mData); | 1063 SInt8* data = static_cast<SInt8*>(io_data->mBuffers[0].mData); |
1056 fine_audio_buffer_->DeliverRecordedData(data, data_size_in_bytes, | 1064 fine_audio_buffer_->DeliverRecordedData(data, data_size_in_bytes, |
1057 kFixedPlayoutDelayEstimate, | 1065 kFixedPlayoutDelayEstimate, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches | 1103 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches |
1096 // the native I/O audio unit) to a preallocated intermediate buffer and | 1104 // the native I/O audio unit) to a preallocated intermediate buffer and |
1097 // copy the result to the audio buffer in the |io_data| destination. | 1105 // copy the result to the audio buffer in the |io_data| destination. |
1098 SInt8* source = playout_audio_buffer_.get(); | 1106 SInt8* source = playout_audio_buffer_.get(); |
1099 fine_audio_buffer_->GetPlayoutData(source); | 1107 fine_audio_buffer_->GetPlayoutData(source); |
1100 memcpy(destination, source, dataSizeInBytes); | 1108 memcpy(destination, source, dataSizeInBytes); |
1101 return noErr; | 1109 return noErr; |
1102 } | 1110 } |
1103 | 1111 |
1104 } // namespace webrtc | 1112 } // namespace webrtc |
OLD | NEW |