Index: media/audio/android/audio_track_output_stream.cc |
diff --git a/media/audio/android/audio_track_output_stream.cc b/media/audio/android/audio_track_output_stream.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d7567ce3e48f92aa351bd823a4f5f3840812a51b |
--- /dev/null |
+++ b/media/audio/android/audio_track_output_stream.cc |
@@ -0,0 +1,107 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/audio/android/audio_track_output_stream.h" |
+ |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
+#include "base/logging.h" |
+#include "base/single_thread_task_runner.h" |
+#include "jni/AudioTrackOutputStream_jni.h" |
+#include "media/audio/audio_manager_base.h" |
+ |
+using base::android::AttachCurrentThread; |
+ |
+namespace media { |
+ |
+AudioTrackOutputStream::AudioTrackOutputStream(AudioManagerBase* manager, |
+ const AudioParameters& params) |
+ : params_(params), |
+ audio_manager_(manager), |
+ callback_(nullptr), |
+ audio_bus_(AudioBus::Create(params_)), |
+ volume_(1.0) { |
+ audio_bus_->Zero(); |
+} |
+ |
+AudioTrackOutputStream::~AudioTrackOutputStream() { |
+ DCHECK(!callback_); |
+} |
+ |
+bool AudioTrackOutputStream::Open() { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ JNIEnv* env = AttachCurrentThread(); |
+ j_audio_output_stream_.Reset(Java_AudioTrackOutputStream_create(env)); |
+ return Java_AudioTrackOutputStream_open( |
+ env, j_audio_output_stream_.obj(), params_.channels(), |
+ params_.sample_rate(), 4, params_.frames_per_buffer()); |
+} |
+ |
+void AudioTrackOutputStream::Start(AudioSourceCallback* callback) { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ callback_ = callback; |
+ Java_AudioTrackOutputStream_start(AttachCurrentThread(), |
+ j_audio_output_stream_.obj(), |
+ reinterpret_cast<intptr_t>(this)); |
+} |
+ |
+void AudioTrackOutputStream::Stop() { |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ Java_AudioTrackOutputStream_stop(AttachCurrentThread(), |
+ j_audio_output_stream_.obj()); |
+ callback_ = nullptr; |
+} |
+ |
+void AudioTrackOutputStream::Close() { |
+ DCHECK(!callback_); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
+ Java_AudioTrackOutputStream_close(AttachCurrentThread(), |
+ j_audio_output_stream_.obj()); |
+ audio_manager_->ReleaseOutputStream(this); |
+} |
+ |
+void AudioTrackOutputStream::SetVolume(double volume) { |
+ // Track |volume_| since AudioTrack uses a scaled value. |
+ volume_ = volume; |
+ Java_AudioTrackOutputStream_setVolume(AttachCurrentThread(), |
+ j_audio_output_stream_.obj(), volume); |
+}; |
+ |
+void AudioTrackOutputStream::GetVolume(double* volume) { |
+ *volume = volume_; |
+}; |
+ |
+// AudioOutputStream::SourceCallback implementation methods called from Java. |
+void AudioTrackOutputStream::OnMoreData(JNIEnv* env, |
+ jobject obj, |
+ jobject audio_data, |
+ int delay_in_frames) { |
+ if (!callback_) |
+ return; |
+ |
+ callback_->OnMoreData(audio_bus_.get(), |
+ delay_in_frames * params_.GetBytesPerFrame()); |
+ float* native_bus = |
+ reinterpret_cast<float*>(env->GetDirectBufferAddress(audio_data)); |
+ |
+ for (int ch = 0; ch < audio_bus_->channels(); ++ch) { |
+ const float* source_data = audio_bus_->channel(ch); |
+ for (int i = 0, offset = ch; i < audio_bus_->frames(); |
+ ++i, offset += audio_bus_->channels()) { |
+ native_bus[offset] = source_data[i]; |
+ } |
+ } |
+} |
+ |
+void AudioTrackOutputStream::OnError(JNIEnv* env, jobject obj) { |
+ DCHECK(callback_); |
+ callback_->OnError(this); |
+} |
+ |
+// static |
+bool AudioTrackOutputStream::RegisterAudioTrackOutputStream(JNIEnv* env) { |
+ return RegisterNativesImpl(env); |
+} |
+ |
+} // namespace media |