blob: 70f4bd5eda4131054efa70b2f9182dbf03b05d64 [file] [log] [blame]
// Copyright 2021 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef STARBOARD_ANDROID_SHARED_AUDIO_TRACK_BRIDGE_H_
#define STARBOARD_ANDROID_SHARED_AUDIO_TRACK_BRIDGE_H_
#include <jni.h>
#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/common/optional.h"
#include "starboard/media.h"
#include "starboard/types.h"
namespace starboard {
namespace android {
namespace shared {
// The C++ encapsulation of the Java class AudioTrackBridge.
class AudioTrackBridge {
public:
// The maximum number of frames that can be written to android audio track per
// write request. It is used to pre-allocate |j_audio_data_|.
static constexpr int kMaxFramesPerRequest = 65536;
// The same as Android AudioTrack.ERROR_DEAD_OBJECT.
static constexpr int kAudioTrackErrorDeadObject = -6;
AudioTrackBridge(SbMediaAudioCodingType coding_type,
optional<SbMediaAudioSampleType> sample_type,
int channels,
int sampling_frequency_hz,
int preferred_buffer_size_in_bytes,
int tunnel_mode_audio_session_id,
bool is_web_audio);
~AudioTrackBridge();
static int GetMinBufferSizeInFrames(SbMediaAudioSampleType sample_type,
int channels,
int sampling_frequency_hz,
JniEnvExt* env = JniEnvExt::Get());
bool is_valid() const {
return j_audio_track_bridge_ != nullptr && j_audio_data_ != nullptr;
}
void Play(JniEnvExt* env = JniEnvExt::Get());
void Pause(JniEnvExt* env = JniEnvExt::Get());
void Stop(JniEnvExt* env = JniEnvExt::Get());
void PauseAndFlush(JniEnvExt* env = JniEnvExt::Get());
// Returns zero or the positive number of samples written, or a negative error
// code.
int WriteSample(const float* samples,
int num_of_samples,
JniEnvExt* env = JniEnvExt::Get());
int WriteSample(const uint16_t* samples,
int num_of_samples,
int64_t sync_time,
JniEnvExt* env = JniEnvExt::Get());
// This is used by passthrough, it treats samples as if they are in bytes.
// Returns zero or the positive number of samples written, or a negative error
// code.
int WriteSample(const uint8_t* buffer,
int num_of_samples,
int64_t sync_time,
JniEnvExt* env = JniEnvExt::Get());
void SetVolume(double volume, JniEnvExt* env = JniEnvExt::Get());
// |updated_at| contains the timestamp when the audio timstamp is updated on
// return. It can be nullptr.
int64_t GetAudioTimestamp(int64_t* updated_at,
JniEnvExt* env = JniEnvExt::Get());
bool GetAndResetHasAudioDeviceChanged(JniEnvExt* env = JniEnvExt::Get());
int GetUnderrunCount(JniEnvExt* env = JniEnvExt::Get());
int GetStartThresholdInFrames(JniEnvExt* env = JniEnvExt::Get());
private:
int max_samples_per_write_;
jobject j_audio_track_bridge_ = nullptr;
// The audio data has to be copied into a Java Array before writing into the
// audio track. Allocating a large array and saves as a member variable
// avoids an array being allocated repeatedly.
jobject j_audio_data_ = nullptr;
};
} // namespace shared
} // namespace android
} // namespace starboard
#endif // STARBOARD_ANDROID_SHARED_AUDIO_TRACK_BRIDGE_H_