1// Copyright 2013 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_record_input.h"
6
7#include "base/logging.h"
8#include "jni/AudioRecordInput_jni.h"
9#include "media/audio/android/audio_manager_android.h"
10#include "media/base/audio_bus.h"
11
12namespace media {
13
14AudioRecordInputStream::AudioRecordInputStream(
15    AudioManagerAndroid* audio_manager,
16    const AudioParameters& params)
17    : audio_manager_(audio_manager),
18      callback_(NULL),
19      direct_buffer_address_(NULL),
20      audio_bus_(media::AudioBus::Create(params)),
21      bytes_per_sample_(params.bits_per_sample() / 8) {
22  DVLOG(2) << __PRETTY_FUNCTION__;
23  DCHECK(params.IsValid());
24  j_audio_record_.Reset(
25      Java_AudioRecordInput_createAudioRecordInput(
26          base::android::AttachCurrentThread(),
27          reinterpret_cast<intptr_t>(this),
28          params.sample_rate(),
29          params.channels(),
30          params.bits_per_sample(),
31          params.GetBytesPerBuffer(),
32          params.effects() & AudioParameters::ECHO_CANCELLER));
33}
34
35AudioRecordInputStream::~AudioRecordInputStream() {
36  DVLOG(2) << __PRETTY_FUNCTION__;
37  DCHECK(thread_checker_.CalledOnValidThread());
38}
39
40void AudioRecordInputStream::CacheDirectBufferAddress(JNIEnv* env, jobject obj,
41                                                      jobject byte_buffer) {
42  DCHECK(thread_checker_.CalledOnValidThread());
43  direct_buffer_address_ = static_cast<uint8*>(
44      env->GetDirectBufferAddress(byte_buffer));
45}
46
47// static
48bool AudioRecordInputStream::RegisterAudioRecordInput(JNIEnv* env) {
49  return RegisterNativesImpl(env);
50}
51
52void AudioRecordInputStream::OnData(JNIEnv* env, jobject obj, jint size,
53                                    jint hardware_delay_bytes) {
54  DCHECK(direct_buffer_address_);
55  DCHECK_EQ(size,
56            audio_bus_->frames() * audio_bus_->channels() * bytes_per_sample_);
57  // Passing zero as the volume parameter indicates there is no access to a
58  // hardware volume slider.
59  audio_bus_->FromInterleaved(
60      direct_buffer_address_, audio_bus_->frames(), bytes_per_sample_);
61  callback_->OnData(this, audio_bus_.get(), hardware_delay_bytes, 0.0);
62}
63
64bool AudioRecordInputStream::Open() {
65  DVLOG(2) << __PRETTY_FUNCTION__;
66  DCHECK(thread_checker_.CalledOnValidThread());
67  return Java_AudioRecordInput_open(
68      base::android::AttachCurrentThread(), j_audio_record_.obj());
69}
70
71void AudioRecordInputStream::Start(AudioInputCallback* callback) {
72  DVLOG(2) << __PRETTY_FUNCTION__;
73  DCHECK(thread_checker_.CalledOnValidThread());
74  DCHECK(callback);
75
76  if (callback_) {
77    // Start() was already called.
78    DCHECK_EQ(callback_, callback);
79    return;
80  }
81  // The Java thread has not yet started, so we are free to set |callback_|.
82  callback_ = callback;
83
84  Java_AudioRecordInput_start(
85      base::android::AttachCurrentThread(), j_audio_record_.obj());
86}
87
88void AudioRecordInputStream::Stop() {
89  DVLOG(2) << __PRETTY_FUNCTION__;
90  DCHECK(thread_checker_.CalledOnValidThread());
91  if (!callback_) {
92    // Start() was never called, or Stop() was already called.
93    return;
94  }
95
96  Java_AudioRecordInput_stop(
97      base::android::AttachCurrentThread(), j_audio_record_.obj());
98
99  // The Java thread must have been stopped at this point, so we are free to
100  // clear |callback_|.
101  callback_ = NULL;
102}
103
104void AudioRecordInputStream::Close() {
105  DVLOG(2) << __PRETTY_FUNCTION__;
106  DCHECK(thread_checker_.CalledOnValidThread());
107  Stop();
108  DCHECK(!callback_);
109  Java_AudioRecordInput_close(
110      base::android::AttachCurrentThread(), j_audio_record_.obj());
111  audio_manager_->ReleaseInputStream(this);
112}
113
114double AudioRecordInputStream::GetMaxVolume() {
115  NOTIMPLEMENTED();
116  return 0.0;
117}
118
119void AudioRecordInputStream::SetVolume(double volume) {
120  NOTIMPLEMENTED();
121}
122
123double AudioRecordInputStream::GetVolume() {
124  NOTIMPLEMENTED();
125  return 0.0;
126}
127
128void AudioRecordInputStream::SetAutomaticGainControl(bool enabled) {
129  NOTIMPLEMENTED();
130}
131
132bool AudioRecordInputStream::GetAutomaticGainControl() {
133  NOTIMPLEMENTED();
134  return false;
135}
136
137bool AudioRecordInputStream::IsMuted() {
138  NOTIMPLEMENTED();
139  return false;
140}
141
142}  // namespace media
143