| /* | 
 |  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #ifndef MODULES_AUDIO_DEVICE_ANDROID_AUDIO_TRACK_JNI_H_ | 
 | #define MODULES_AUDIO_DEVICE_ANDROID_AUDIO_TRACK_JNI_H_ | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include <jni.h> | 
 |  | 
 | #include "modules/audio_device/android/audio_common.h" | 
 | #include "modules/audio_device/android/audio_manager.h" | 
 | #include "modules/audio_device/audio_device_generic.h" | 
 | #include "modules/audio_device/include/audio_device_defines.h" | 
 | #include "modules/utility/include/helpers_android.h" | 
 | #include "modules/utility/include/jvm_android.h" | 
 | #include "rtc_base/thread_checker.h" | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | // Implements 16-bit mono PCM audio output support for Android using the Java | 
 | // AudioTrack interface. Most of the work is done by its Java counterpart in | 
 | // WebRtcAudioTrack.java. This class is created and lives on a thread in | 
 | // C++-land, but decoded audio buffers are requested on a high-priority | 
 | // thread managed by the Java class. | 
 | // | 
 | // An instance must be created and destroyed on one and the same thread. | 
 | // All public methods must also be called on the same thread. A thread checker | 
 | // will RTC_DCHECK if any method is called on an invalid thread. | 
 | // | 
 | // This class uses AttachCurrentThreadIfNeeded to attach to a Java VM if needed | 
 | // and detach when the object goes out of scope. Additional thread checking | 
 | // guarantees that no other (possibly non attached) thread is used. | 
 | class AudioTrackJni { | 
 |  public: | 
 |   // Wraps the Java specific parts of the AudioTrackJni into one helper class. | 
 |   class JavaAudioTrack { | 
 |    public: | 
 |     JavaAudioTrack(NativeRegistration* native_registration, | 
 |                    std::unique_ptr<GlobalRef> audio_track); | 
 |     ~JavaAudioTrack(); | 
 |  | 
 |     bool InitPlayout(int sample_rate, int channels); | 
 |     bool StartPlayout(); | 
 |     bool StopPlayout(); | 
 |     bool SetStreamVolume(int volume); | 
 |     int GetStreamMaxVolume(); | 
 |     int GetStreamVolume(); | 
 |  | 
 |    private: | 
 |     std::unique_ptr<GlobalRef> audio_track_; | 
 |     jmethodID init_playout_; | 
 |     jmethodID start_playout_; | 
 |     jmethodID stop_playout_; | 
 |     jmethodID set_stream_volume_; | 
 |     jmethodID get_stream_max_volume_; | 
 |     jmethodID get_stream_volume_; | 
 |   }; | 
 |  | 
 |   explicit AudioTrackJni(AudioManager* audio_manager); | 
 |   ~AudioTrackJni(); | 
 |  | 
 |   int32_t Init(); | 
 |   int32_t Terminate(); | 
 |  | 
 |   int32_t InitPlayout(); | 
 |   bool PlayoutIsInitialized() const { return initialized_; } | 
 |  | 
 |   int32_t StartPlayout(); | 
 |   int32_t StopPlayout(); | 
 |   bool Playing() const { return playing_; } | 
 |  | 
 |   int SpeakerVolumeIsAvailable(bool& available); | 
 |   int SetSpeakerVolume(uint32_t volume); | 
 |   int SpeakerVolume(uint32_t& volume) const; | 
 |   int MaxSpeakerVolume(uint32_t& max_volume) const; | 
 |   int MinSpeakerVolume(uint32_t& min_volume) const; | 
 |  | 
 |   void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer); | 
 |  | 
 |  private: | 
 |   // Called from Java side so we can cache the address of the Java-manged | 
 |   // |byte_buffer| in |direct_buffer_address_|. The size of the buffer | 
 |   // is also stored in |direct_buffer_capacity_in_bytes_|. | 
 |   // Called on the same thread as the creating thread. | 
 |   static void JNICALL CacheDirectBufferAddress( | 
 |     JNIEnv* env, jobject obj, jobject byte_buffer, jlong nativeAudioTrack); | 
 |   void OnCacheDirectBufferAddress(JNIEnv* env, jobject byte_buffer); | 
 |  | 
 |   // Called periodically by the Java based WebRtcAudioTrack object when | 
 |   // playout has started. Each call indicates that |length| new bytes should | 
 |   // be written to the memory area |direct_buffer_address_| for playout. | 
 |   // This method is called on a high-priority thread from Java. The name of | 
 |   // the thread is 'AudioTrackThread'. | 
 |   static void JNICALL GetPlayoutData( | 
 |     JNIEnv* env, jobject obj, jint length, jlong nativeAudioTrack); | 
 |   void OnGetPlayoutData(size_t length); | 
 |  | 
 |   // Stores thread ID in constructor. | 
 |   rtc::ThreadChecker thread_checker_; | 
 |  | 
 |   // Stores thread ID in first call to OnGetPlayoutData() from high-priority | 
 |   // thread in Java. Detached during construction of this object. | 
 |   rtc::ThreadChecker thread_checker_java_; | 
 |  | 
 |   // Calls AttachCurrentThread() if this thread is not attached at construction. | 
 |   // Also ensures that DetachCurrentThread() is called at destruction. | 
 |   AttachCurrentThreadIfNeeded attach_thread_if_needed_; | 
 |  | 
 |   // Wraps the JNI interface pointer and methods associated with it. | 
 |   std::unique_ptr<JNIEnvironment> j_environment_; | 
 |  | 
 |   // Contains factory method for creating the Java object. | 
 |   std::unique_ptr<NativeRegistration> j_native_registration_; | 
 |  | 
 |   // Wraps the Java specific parts of the AudioTrackJni class. | 
 |   std::unique_ptr<AudioTrackJni::JavaAudioTrack> j_audio_track_; | 
 |  | 
 |   // Contains audio parameters provided to this class at construction by the | 
 |   // AudioManager. | 
 |   const AudioParameters audio_parameters_; | 
 |  | 
 |   // Cached copy of address to direct audio buffer owned by |j_audio_track_|. | 
 |   void* direct_buffer_address_; | 
 |  | 
 |   // Number of bytes in the direct audio buffer owned by |j_audio_track_|. | 
 |   size_t direct_buffer_capacity_in_bytes_; | 
 |  | 
 |   // Number of audio frames per audio buffer. Each audio frame corresponds to | 
 |   // one sample of PCM mono data at 16 bits per sample. Hence, each audio | 
 |   // frame contains 2 bytes (given that the Java layer only supports mono). | 
 |   // Example: 480 for 48000 Hz or 441 for 44100 Hz. | 
 |   size_t frames_per_buffer_; | 
 |  | 
 |   bool initialized_; | 
 |  | 
 |   bool playing_; | 
 |  | 
 |   // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the | 
 |   // AudioDeviceModuleImpl class and called by AudioDeviceModule::Create(). | 
 |   // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance | 
 |   // and therefore outlives this object. | 
 |   AudioDeviceBuffer* audio_device_buffer_; | 
 | }; | 
 |  | 
 | }  // namespace webrtc | 
 |  | 
 | #endif  // MODULES_AUDIO_DEVICE_ANDROID_AUDIO_TRACK_JNI_H_ |