audio_manager_android.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 3// found in the LICENSE file. 4 5#include "media/audio/android/audio_manager_android.h" 6 7#include "base/logging.h" 8#include "jni/AudioManagerAndroid_jni.h" 9#include "media/audio/android/opensles_input.h" 10#include "media/audio/android/opensles_output.h" 11#include "media/audio/audio_manager.h" 12#include "media/audio/audio_parameters.h" 13#include "media/audio/audio_util.h" 14#include "media/audio/fake_audio_input_stream.h" 15#include "media/base/channel_layout.h" 16 17namespace media { 18 19// Maximum number of output streams that can be open simultaneously. 20static const int kMaxOutputStreams = 10; 21 22static const int kAudioModeNormal = 0x00000000; 23static const int kAudioModeInCommunication = 0x00000003; 24 25static const int kDefaultInputBufferSize = 1024; 26static const int kDefaultOutputBufferSize = 2048; 27 28AudioManager* CreateAudioManager() { 29 return new AudioManagerAndroid(); 30} 31 32AudioManagerAndroid::AudioManagerAndroid() { 33 SetMaxOutputStreamsAllowed(kMaxOutputStreams); 34 35 j_audio_manager_.Reset( 36 Java_AudioManagerAndroid_createAudioManagerAndroid( 37 base::android::AttachCurrentThread(), 38 base::android::GetApplicationContext())); 39} 40 41AudioManagerAndroid::~AudioManagerAndroid() { 42 Shutdown(); 43} 44 45bool AudioManagerAndroid::HasAudioOutputDevices() { 46 return true; 47} 48 49bool AudioManagerAndroid::HasAudioInputDevices() { 50 return true; 51} 52 53void AudioManagerAndroid::GetAudioInputDeviceNames( 54 media::AudioDeviceNames* device_names) { 55 DCHECK(device_names->empty()); 56 device_names->push_front( 57 media::AudioDeviceName(kDefaultDeviceName, kDefaultDeviceId)); 58} 59 60AudioParameters AudioManagerAndroid::GetInputStreamParameters( 61 const std::string& device_id) { 62 int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize( 63 base::android::AttachCurrentThread(), GetNativeOutputSampleRate(), 2); 64 65 return AudioParameters( 66 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 67 GetNativeOutputSampleRate(), 16, 68 buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size); 69} 70 71AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream( 72 const AudioParameters& params) { 73 AudioOutputStream* stream = 74 AudioManagerBase::MakeAudioOutputStream(params); 75 if (stream && output_stream_count() == 1) 76 RegisterHeadsetReceiver(); 77 return stream; 78} 79 80AudioInputStream* AudioManagerAndroid::MakeAudioInputStream( 81 const AudioParameters& params, const std::string& device_id) { 82 AudioInputStream* stream = 83 AudioManagerBase::MakeAudioInputStream(params, device_id); 84 if (stream && input_stream_count() == 1) 85 SetAudioMode(kAudioModeInCommunication); 86 return stream; 87} 88 89void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) { 90 AudioManagerBase::ReleaseOutputStream(stream); 91 if (!output_stream_count()) 92 UnregisterHeadsetReceiver(); 93} 94 95void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) { 96 AudioManagerBase::ReleaseInputStream(stream); 97 if (!input_stream_count()) 98 SetAudioMode(kAudioModeNormal); 99} 100 101AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream( 102 const AudioParameters& params) { 103 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 104 return new OpenSLESOutputStream(this, params); 105} 106 107AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream( 108 const AudioParameters& params) { 109 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 110 return new OpenSLESOutputStream(this, params); 111} 112 113AudioInputStream* AudioManagerAndroid::MakeLinearInputStream( 114 const AudioParameters& params, const std::string& device_id) { 115 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); 116 return new OpenSLESInputStream(this, params); 117} 118 119AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream( 120 const AudioParameters& params, const std::string& device_id) { 121 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); 122 return new OpenSLESInputStream(this, params); 123} 124 125int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, 126 int channels) { 127 if (IsAudioLowLatencySupported()) { 128 int frame_size = GetAudioLowLatencyOutputFrameSize(); 129 // Return the optimal size as a multiple of the low latency frame 130 // size that is close to the target frame size. 131 return ((kDefaultOutputBufferSize + frame_size / 2) / frame_size) * 132 frame_size; 133 } else { 134 return std::max(kDefaultOutputBufferSize, 135 Java_AudioManagerAndroid_getMinOutputFrameSize( 136 base::android::AttachCurrentThread(), 137 sample_rate, channels)); 138 } 139} 140 141AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters( 142 const AudioParameters& input_params) { 143 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; 144 int sample_rate = GetNativeOutputSampleRate(); 145 int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2); 146 int bits_per_sample = 16; 147 int input_channels = 0; 148 if (input_params.IsValid()) { 149 // Use the client's input parameters if they are valid. 150 sample_rate = input_params.sample_rate(); 151 bits_per_sample = input_params.bits_per_sample(); 152 channel_layout = input_params.channel_layout(); 153 input_channels = input_params.input_channels(); 154 buffer_size = GetOptimalOutputFrameSize(sample_rate, channel_layout); 155 } 156 157 int user_buffer_size = GetUserBufferSize(); 158 if (user_buffer_size) 159 buffer_size = user_buffer_size; 160 161 return AudioParameters( 162 AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels, 163 sample_rate, bits_per_sample, buffer_size); 164} 165 166// static 167bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) { 168 return RegisterNativesImpl(env); 169} 170 171void AudioManagerAndroid::SetAudioMode(int mode) { 172 Java_AudioManagerAndroid_setMode( 173 base::android::AttachCurrentThread(), 174 j_audio_manager_.obj(), mode); 175} 176 177void AudioManagerAndroid::RegisterHeadsetReceiver() { 178 Java_AudioManagerAndroid_registerHeadsetReceiver( 179 base::android::AttachCurrentThread(), 180 j_audio_manager_.obj()); 181} 182 183void AudioManagerAndroid::UnregisterHeadsetReceiver() { 184 Java_AudioManagerAndroid_unregisterHeadsetReceiver( 185 base::android::AttachCurrentThread(), 186 j_audio_manager_.obj()); 187} 188 189int AudioManagerAndroid::GetNativeOutputSampleRate() { 190 return Java_AudioManagerAndroid_getNativeOutputSampleRate( 191 base::android::AttachCurrentThread(), 192 j_audio_manager_.obj()); 193} 194 195bool AudioManagerAndroid::IsAudioLowLatencySupported() { 196 return Java_AudioManagerAndroid_isAudioLowLatencySupported( 197 base::android::AttachCurrentThread(), 198 j_audio_manager_.obj()); 199} 200 201int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() { 202 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize( 203 base::android::AttachCurrentThread(), 204 j_audio_manager_.obj()); 205} 206 207} // namespace media 208