| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2  *  Copyright (c) 2013 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 69 AudioTrackJni::AudioTrackJni(AudioManager* audio_manager) | 69 AudioTrackJni::AudioTrackJni(AudioManager* audio_manager) | 
| 70     : j_environment_(JVM::GetInstance()->environment()), | 70     : j_environment_(JVM::GetInstance()->environment()), | 
| 71       audio_parameters_(audio_manager->GetPlayoutAudioParameters()), | 71       audio_parameters_(audio_manager->GetPlayoutAudioParameters()), | 
| 72       direct_buffer_address_(nullptr), | 72       direct_buffer_address_(nullptr), | 
| 73       direct_buffer_capacity_in_bytes_(0), | 73       direct_buffer_capacity_in_bytes_(0), | 
| 74       frames_per_buffer_(0), | 74       frames_per_buffer_(0), | 
| 75       initialized_(false), | 75       initialized_(false), | 
| 76       playing_(false), | 76       playing_(false), | 
| 77       audio_device_buffer_(nullptr) { | 77       audio_device_buffer_(nullptr) { | 
| 78   ALOGD("ctor%s", GetThreadInfo().c_str()); | 78   ALOGD("ctor%s", GetThreadInfo().c_str()); | 
| 79   DCHECK(audio_parameters_.is_valid()); | 79   RTC_DCHECK(audio_parameters_.is_valid()); | 
| 80   CHECK(j_environment_); | 80   RTC_CHECK(j_environment_); | 
| 81   JNINativeMethod native_methods[] = { | 81   JNINativeMethod native_methods[] = { | 
| 82       {"nativeCacheDirectBufferAddress", "(Ljava/nio/ByteBuffer;J)V", | 82       {"nativeCacheDirectBufferAddress", "(Ljava/nio/ByteBuffer;J)V", | 
| 83       reinterpret_cast<void*>( | 83       reinterpret_cast<void*>( | 
| 84           &webrtc::AudioTrackJni::CacheDirectBufferAddress)}, | 84           &webrtc::AudioTrackJni::CacheDirectBufferAddress)}, | 
| 85       {"nativeGetPlayoutData", "(IJ)V", | 85       {"nativeGetPlayoutData", "(IJ)V", | 
| 86       reinterpret_cast<void*>(&webrtc::AudioTrackJni::GetPlayoutData)}}; | 86       reinterpret_cast<void*>(&webrtc::AudioTrackJni::GetPlayoutData)}}; | 
| 87   j_native_registration_ = j_environment_->RegisterNatives( | 87   j_native_registration_ = j_environment_->RegisterNatives( | 
| 88       "org/webrtc/voiceengine/WebRtcAudioTrack", | 88       "org/webrtc/voiceengine/WebRtcAudioTrack", | 
| 89       native_methods, arraysize(native_methods)); | 89       native_methods, arraysize(native_methods)); | 
| 90   j_audio_track_.reset(new JavaAudioTrack( | 90   j_audio_track_.reset(new JavaAudioTrack( | 
| 91       j_native_registration_.get(), | 91       j_native_registration_.get(), | 
| 92       j_native_registration_->NewObject( | 92       j_native_registration_->NewObject( | 
| 93           "<init>", "(Landroid/content/Context;J)V", | 93           "<init>", "(Landroid/content/Context;J)V", | 
| 94           JVM::GetInstance()->context(), PointerTojlong(this)))); | 94           JVM::GetInstance()->context(), PointerTojlong(this)))); | 
| 95   // Detach from this thread since we want to use the checker to verify calls | 95   // Detach from this thread since we want to use the checker to verify calls | 
| 96   // from the Java based audio thread. | 96   // from the Java based audio thread. | 
| 97   thread_checker_java_.DetachFromThread(); | 97   thread_checker_java_.DetachFromThread(); | 
| 98 } | 98 } | 
| 99 | 99 | 
| 100 AudioTrackJni::~AudioTrackJni() { | 100 AudioTrackJni::~AudioTrackJni() { | 
| 101   ALOGD("~dtor%s", GetThreadInfo().c_str()); | 101   ALOGD("~dtor%s", GetThreadInfo().c_str()); | 
| 102   DCHECK(thread_checker_.CalledOnValidThread()); | 102   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 103   Terminate(); | 103   Terminate(); | 
| 104 } | 104 } | 
| 105 | 105 | 
| 106 int32_t AudioTrackJni::Init() { | 106 int32_t AudioTrackJni::Init() { | 
| 107   ALOGD("Init%s", GetThreadInfo().c_str()); | 107   ALOGD("Init%s", GetThreadInfo().c_str()); | 
| 108   DCHECK(thread_checker_.CalledOnValidThread()); | 108   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 109   return 0; | 109   return 0; | 
| 110 } | 110 } | 
| 111 | 111 | 
| 112 int32_t AudioTrackJni::Terminate() { | 112 int32_t AudioTrackJni::Terminate() { | 
| 113   ALOGD("Terminate%s", GetThreadInfo().c_str()); | 113   ALOGD("Terminate%s", GetThreadInfo().c_str()); | 
| 114   DCHECK(thread_checker_.CalledOnValidThread()); | 114   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 115   StopPlayout(); | 115   StopPlayout(); | 
| 116   return 0; | 116   return 0; | 
| 117 } | 117 } | 
| 118 | 118 | 
| 119 int32_t AudioTrackJni::InitPlayout() { | 119 int32_t AudioTrackJni::InitPlayout() { | 
| 120   ALOGD("InitPlayout%s", GetThreadInfo().c_str()); | 120   ALOGD("InitPlayout%s", GetThreadInfo().c_str()); | 
| 121   DCHECK(thread_checker_.CalledOnValidThread()); | 121   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 122   DCHECK(!initialized_); | 122   RTC_DCHECK(!initialized_); | 
| 123   DCHECK(!playing_); | 123   RTC_DCHECK(!playing_); | 
| 124   j_audio_track_->InitPlayout( | 124   j_audio_track_->InitPlayout( | 
| 125       audio_parameters_.sample_rate(), audio_parameters_.channels()); | 125       audio_parameters_.sample_rate(), audio_parameters_.channels()); | 
| 126   initialized_ = true; | 126   initialized_ = true; | 
| 127   return 0; | 127   return 0; | 
| 128 } | 128 } | 
| 129 | 129 | 
| 130 int32_t AudioTrackJni::StartPlayout() { | 130 int32_t AudioTrackJni::StartPlayout() { | 
| 131   ALOGD("StartPlayout%s", GetThreadInfo().c_str()); | 131   ALOGD("StartPlayout%s", GetThreadInfo().c_str()); | 
| 132   DCHECK(thread_checker_.CalledOnValidThread()); | 132   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 133   DCHECK(initialized_); | 133   RTC_DCHECK(initialized_); | 
| 134   DCHECK(!playing_); | 134   RTC_DCHECK(!playing_); | 
| 135   if (!j_audio_track_->StartPlayout()) { | 135   if (!j_audio_track_->StartPlayout()) { | 
| 136     ALOGE("StartPlayout failed!"); | 136     ALOGE("StartPlayout failed!"); | 
| 137     return -1; | 137     return -1; | 
| 138   } | 138   } | 
| 139   playing_ = true; | 139   playing_ = true; | 
| 140   return 0; | 140   return 0; | 
| 141 } | 141 } | 
| 142 | 142 | 
| 143 int32_t AudioTrackJni::StopPlayout() { | 143 int32_t AudioTrackJni::StopPlayout() { | 
| 144   ALOGD("StopPlayout%s", GetThreadInfo().c_str()); | 144   ALOGD("StopPlayout%s", GetThreadInfo().c_str()); | 
| 145   DCHECK(thread_checker_.CalledOnValidThread()); | 145   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 146   if (!initialized_ || !playing_) { | 146   if (!initialized_ || !playing_) { | 
| 147     return 0; | 147     return 0; | 
| 148   } | 148   } | 
| 149   if (!j_audio_track_->StopPlayout()) { | 149   if (!j_audio_track_->StopPlayout()) { | 
| 150     ALOGE("StopPlayout failed!"); | 150     ALOGE("StopPlayout failed!"); | 
| 151     return -1; | 151     return -1; | 
| 152   } | 152   } | 
| 153   // If we don't detach here, we will hit a DCHECK in OnDataIsRecorded() next | 153   // If we don't detach here, we will hit a RTC_DCHECK in OnDataIsRecorded() | 
| 154   // time StartRecording() is called since it will create a new Java thread. | 154   // next time StartRecording() is called since it will create a new Java | 
|  | 155   // thread. | 
| 155   thread_checker_java_.DetachFromThread(); | 156   thread_checker_java_.DetachFromThread(); | 
| 156   initialized_ = false; | 157   initialized_ = false; | 
| 157   playing_ = false; | 158   playing_ = false; | 
| 158   return 0; | 159   return 0; | 
| 159 } | 160 } | 
| 160 | 161 | 
| 161 int AudioTrackJni::SpeakerVolumeIsAvailable(bool& available) { | 162 int AudioTrackJni::SpeakerVolumeIsAvailable(bool& available) { | 
| 162   available = true; | 163   available = true; | 
| 163   return 0; | 164   return 0; | 
| 164 } | 165 } | 
| 165 | 166 | 
| 166 int AudioTrackJni::SetSpeakerVolume(uint32_t volume) { | 167 int AudioTrackJni::SetSpeakerVolume(uint32_t volume) { | 
| 167   ALOGD("SetSpeakerVolume(%d)%s", volume, GetThreadInfo().c_str()); | 168   ALOGD("SetSpeakerVolume(%d)%s", volume, GetThreadInfo().c_str()); | 
| 168   DCHECK(thread_checker_.CalledOnValidThread()); | 169   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 169   return j_audio_track_->SetStreamVolume(volume) ? 0 : -1; | 170   return j_audio_track_->SetStreamVolume(volume) ? 0 : -1; | 
| 170 } | 171 } | 
| 171 | 172 | 
| 172 int AudioTrackJni::MaxSpeakerVolume(uint32_t& max_volume) const { | 173 int AudioTrackJni::MaxSpeakerVolume(uint32_t& max_volume) const { | 
| 173   ALOGD("MaxSpeakerVolume%s", GetThreadInfo().c_str()); | 174   ALOGD("MaxSpeakerVolume%s", GetThreadInfo().c_str()); | 
| 174   DCHECK(thread_checker_.CalledOnValidThread()); | 175   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 175   max_volume = j_audio_track_->GetStreamMaxVolume(); | 176   max_volume = j_audio_track_->GetStreamMaxVolume(); | 
| 176   return 0; | 177   return 0; | 
| 177 } | 178 } | 
| 178 | 179 | 
| 179 int AudioTrackJni::MinSpeakerVolume(uint32_t& min_volume) const { | 180 int AudioTrackJni::MinSpeakerVolume(uint32_t& min_volume) const { | 
| 180   ALOGD("MaxSpeakerVolume%s", GetThreadInfo().c_str()); | 181   ALOGD("MaxSpeakerVolume%s", GetThreadInfo().c_str()); | 
| 181   DCHECK(thread_checker_.CalledOnValidThread()); | 182   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 182   min_volume = 0; | 183   min_volume = 0; | 
| 183   return 0; | 184   return 0; | 
| 184 } | 185 } | 
| 185 | 186 | 
| 186 int AudioTrackJni::SpeakerVolume(uint32_t& volume) const { | 187 int AudioTrackJni::SpeakerVolume(uint32_t& volume) const { | 
| 187   ALOGD("SpeakerVolume%s", GetThreadInfo().c_str()); | 188   ALOGD("SpeakerVolume%s", GetThreadInfo().c_str()); | 
| 188   DCHECK(thread_checker_.CalledOnValidThread()); | 189   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 189   volume = j_audio_track_->GetStreamVolume(); | 190   volume = j_audio_track_->GetStreamVolume(); | 
| 190   return 0; | 191   return 0; | 
| 191 } | 192 } | 
| 192 | 193 | 
| 193 // TODO(henrika): possibly add stereo support. | 194 // TODO(henrika): possibly add stereo support. | 
| 194 void AudioTrackJni::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) { | 195 void AudioTrackJni::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) { | 
| 195   ALOGD("AttachAudioBuffer%s", GetThreadInfo().c_str()); | 196   ALOGD("AttachAudioBuffer%s", GetThreadInfo().c_str()); | 
| 196   DCHECK(thread_checker_.CalledOnValidThread()); | 197   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 197   audio_device_buffer_ = audioBuffer; | 198   audio_device_buffer_ = audioBuffer; | 
| 198   const int sample_rate_hz = audio_parameters_.sample_rate(); | 199   const int sample_rate_hz = audio_parameters_.sample_rate(); | 
| 199   ALOGD("SetPlayoutSampleRate(%d)", sample_rate_hz); | 200   ALOGD("SetPlayoutSampleRate(%d)", sample_rate_hz); | 
| 200   audio_device_buffer_->SetPlayoutSampleRate(sample_rate_hz); | 201   audio_device_buffer_->SetPlayoutSampleRate(sample_rate_hz); | 
| 201   const int channels = audio_parameters_.channels(); | 202   const int channels = audio_parameters_.channels(); | 
| 202   ALOGD("SetPlayoutChannels(%d)", channels); | 203   ALOGD("SetPlayoutChannels(%d)", channels); | 
| 203   audio_device_buffer_->SetPlayoutChannels(channels); | 204   audio_device_buffer_->SetPlayoutChannels(channels); | 
| 204 } | 205 } | 
| 205 | 206 | 
| 206 void JNICALL AudioTrackJni::CacheDirectBufferAddress( | 207 void JNICALL AudioTrackJni::CacheDirectBufferAddress( | 
| 207     JNIEnv* env, jobject obj, jobject byte_buffer, jlong nativeAudioTrack) { | 208     JNIEnv* env, jobject obj, jobject byte_buffer, jlong nativeAudioTrack) { | 
| 208   webrtc::AudioTrackJni* this_object = | 209   webrtc::AudioTrackJni* this_object = | 
| 209       reinterpret_cast<webrtc::AudioTrackJni*> (nativeAudioTrack); | 210       reinterpret_cast<webrtc::AudioTrackJni*> (nativeAudioTrack); | 
| 210   this_object->OnCacheDirectBufferAddress(env, byte_buffer); | 211   this_object->OnCacheDirectBufferAddress(env, byte_buffer); | 
| 211 } | 212 } | 
| 212 | 213 | 
| 213 void AudioTrackJni::OnCacheDirectBufferAddress( | 214 void AudioTrackJni::OnCacheDirectBufferAddress( | 
| 214     JNIEnv* env, jobject byte_buffer) { | 215     JNIEnv* env, jobject byte_buffer) { | 
| 215   ALOGD("OnCacheDirectBufferAddress"); | 216   ALOGD("OnCacheDirectBufferAddress"); | 
| 216   DCHECK(thread_checker_.CalledOnValidThread()); | 217   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 217   direct_buffer_address_ = | 218   direct_buffer_address_ = | 
| 218       env->GetDirectBufferAddress(byte_buffer); | 219       env->GetDirectBufferAddress(byte_buffer); | 
| 219   jlong capacity = env->GetDirectBufferCapacity(byte_buffer); | 220   jlong capacity = env->GetDirectBufferCapacity(byte_buffer); | 
| 220   ALOGD("direct buffer capacity: %lld", capacity); | 221   ALOGD("direct buffer capacity: %lld", capacity); | 
| 221   direct_buffer_capacity_in_bytes_ = static_cast<size_t>(capacity); | 222   direct_buffer_capacity_in_bytes_ = static_cast<size_t>(capacity); | 
| 222   frames_per_buffer_ = direct_buffer_capacity_in_bytes_ / kBytesPerFrame; | 223   frames_per_buffer_ = direct_buffer_capacity_in_bytes_ / kBytesPerFrame; | 
| 223   ALOGD("frames_per_buffer: %" PRIuS, frames_per_buffer_); | 224   ALOGD("frames_per_buffer: %" PRIuS, frames_per_buffer_); | 
| 224 } | 225 } | 
| 225 | 226 | 
| 226 void JNICALL AudioTrackJni::GetPlayoutData( | 227 void JNICALL AudioTrackJni::GetPlayoutData( | 
| 227   JNIEnv* env, jobject obj, jint length, jlong nativeAudioTrack) { | 228   JNIEnv* env, jobject obj, jint length, jlong nativeAudioTrack) { | 
| 228   webrtc::AudioTrackJni* this_object = | 229   webrtc::AudioTrackJni* this_object = | 
| 229       reinterpret_cast<webrtc::AudioTrackJni*> (nativeAudioTrack); | 230       reinterpret_cast<webrtc::AudioTrackJni*> (nativeAudioTrack); | 
| 230   this_object->OnGetPlayoutData(static_cast<size_t>(length)); | 231   this_object->OnGetPlayoutData(static_cast<size_t>(length)); | 
| 231 } | 232 } | 
| 232 | 233 | 
| 233 // This method is called on a high-priority thread from Java. The name of | 234 // This method is called on a high-priority thread from Java. The name of | 
| 234 // the thread is 'AudioRecordTrack'. | 235 // the thread is 'AudioRecordTrack'. | 
| 235 void AudioTrackJni::OnGetPlayoutData(size_t length) { | 236 void AudioTrackJni::OnGetPlayoutData(size_t length) { | 
| 236   DCHECK(thread_checker_java_.CalledOnValidThread()); | 237   RTC_DCHECK(thread_checker_java_.CalledOnValidThread()); | 
| 237   DCHECK_EQ(frames_per_buffer_, length / kBytesPerFrame); | 238   RTC_DCHECK_EQ(frames_per_buffer_, length / kBytesPerFrame); | 
| 238   if (!audio_device_buffer_) { | 239   if (!audio_device_buffer_) { | 
| 239     ALOGE("AttachAudioBuffer has not been called!"); | 240     ALOGE("AttachAudioBuffer has not been called!"); | 
| 240     return; | 241     return; | 
| 241   } | 242   } | 
| 242   // Pull decoded data (in 16-bit PCM format) from jitter buffer. | 243   // Pull decoded data (in 16-bit PCM format) from jitter buffer. | 
| 243   int samples = audio_device_buffer_->RequestPlayoutData(frames_per_buffer_); | 244   int samples = audio_device_buffer_->RequestPlayoutData(frames_per_buffer_); | 
| 244   if (samples <= 0) { | 245   if (samples <= 0) { | 
| 245     ALOGE("AudioDeviceBuffer::RequestPlayoutData failed!"); | 246     ALOGE("AudioDeviceBuffer::RequestPlayoutData failed!"); | 
| 246     return; | 247     return; | 
| 247   } | 248   } | 
| 248   DCHECK_EQ(static_cast<size_t>(samples), frames_per_buffer_); | 249   RTC_DCHECK_EQ(static_cast<size_t>(samples), frames_per_buffer_); | 
| 249   // Copy decoded data into common byte buffer to ensure that it can be | 250   // Copy decoded data into common byte buffer to ensure that it can be | 
| 250   // written to the Java based audio track. | 251   // written to the Java based audio track. | 
| 251   samples = audio_device_buffer_->GetPlayoutData(direct_buffer_address_); | 252   samples = audio_device_buffer_->GetPlayoutData(direct_buffer_address_); | 
| 252   DCHECK_EQ(length, kBytesPerFrame * samples); | 253   RTC_DCHECK_EQ(length, kBytesPerFrame * samples); | 
| 253 } | 254 } | 
| 254 | 255 | 
| 255 }  // namespace webrtc | 256 }  // namespace webrtc | 
| OLD | NEW | 
|---|