AudioTrack: Add Tuner Configuration methods
Test: atest AudioTrackTest#testTunerConfiguration Bug: 133526565 Change-Id: I0cc8e9e8b780e1a87c38656c8dfc67dac03969d8
This commit is contained in:
@@ -24248,6 +24248,9 @@ package android.media {
|
||||
method public int write(@NonNull float[], int, int, int);
|
||||
method public int write(@NonNull java.nio.ByteBuffer, int, int);
|
||||
method public int write(@NonNull java.nio.ByteBuffer, int, int, long);
|
||||
field public static final int ENCAPSULATION_MODE_ELEMENTARY_STREAM = 1; // 0x1
|
||||
field public static final int ENCAPSULATION_MODE_HANDLE = 2; // 0x2
|
||||
field public static final int ENCAPSULATION_MODE_NONE = 0; // 0x0
|
||||
field public static final int ERROR = -1; // 0xffffffff
|
||||
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
|
||||
field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
|
||||
@@ -24274,10 +24277,12 @@ package android.media {
|
||||
method @NonNull public android.media.AudioTrack.Builder setAudioAttributes(@NonNull android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioTrack.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioTrack.Builder setBufferSizeInBytes(@IntRange(from=0) int) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioTrack.Builder setEncapsulationMode(int);
|
||||
method @NonNull public android.media.AudioTrack.Builder setOffloadedPlayback(boolean);
|
||||
method @NonNull public android.media.AudioTrack.Builder setPerformanceMode(int);
|
||||
method @NonNull public android.media.AudioTrack.Builder setSessionId(@IntRange(from=1) int) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
|
||||
method @NonNull public android.media.AudioTrack.Builder setTunerConfiguration(@NonNull android.media.AudioTrack.TunerConfiguration);
|
||||
}
|
||||
|
||||
public static final class AudioTrack.MetricsConstants {
|
||||
@@ -24305,6 +24310,18 @@ package android.media {
|
||||
method public void onTearDown(@NonNull android.media.AudioTrack);
|
||||
}
|
||||
|
||||
public static class AudioTrack.TunerConfiguration {
|
||||
method public int getContentId();
|
||||
method public int getSyncId();
|
||||
}
|
||||
|
||||
public static class AudioTrack.TunerConfiguration.Builder {
|
||||
ctor public AudioTrack.TunerConfiguration.Builder();
|
||||
method @NonNull public android.media.AudioTrack.TunerConfiguration build();
|
||||
method @NonNull public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
|
||||
method @NonNull public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
|
||||
}
|
||||
|
||||
public class CamcorderProfile {
|
||||
method public static android.media.CamcorderProfile get(int);
|
||||
method public static android.media.CamcorderProfile get(int, int);
|
||||
|
||||
@@ -102,6 +102,47 @@ class AudioTrackJniStorage {
|
||||
}
|
||||
};
|
||||
|
||||
class TunerConfigurationHelper {
|
||||
JNIEnv *const mEnv;
|
||||
jobject const mTunerConfiguration;
|
||||
|
||||
struct Ids {
|
||||
Ids(JNIEnv *env)
|
||||
: mClass(FindClassOrDie(env, "android/media/AudioTrack$TunerConfiguration")),
|
||||
mContentId(GetFieldIDOrDie(env, mClass, "mContentId", "I")),
|
||||
mSyncId(GetFieldIDOrDie(env, mClass, "mSyncId", "I")) {}
|
||||
const jclass mClass;
|
||||
const jfieldID mContentId;
|
||||
const jfieldID mSyncId;
|
||||
};
|
||||
|
||||
static const Ids &getIds(JNIEnv *env) {
|
||||
// Meyer's singleton, initializes first time control passes through
|
||||
// declaration in a block and is thread-safe per ISO/IEC 14882:2011 6.7.4.
|
||||
static Ids ids(env);
|
||||
return ids;
|
||||
}
|
||||
|
||||
public:
|
||||
TunerConfigurationHelper(JNIEnv *env, jobject tunerConfiguration)
|
||||
: mEnv(env), mTunerConfiguration(tunerConfiguration) {}
|
||||
|
||||
int32_t getContentId() const {
|
||||
if (mEnv == nullptr || mTunerConfiguration == nullptr) return 0;
|
||||
const Ids &ids = getIds(mEnv);
|
||||
return (int32_t)mEnv->GetIntField(mTunerConfiguration, ids.mContentId);
|
||||
}
|
||||
|
||||
int32_t getSyncId() const {
|
||||
if (mEnv == nullptr || mTunerConfiguration == nullptr) return 0;
|
||||
const Ids &ids = getIds(mEnv);
|
||||
return (int32_t)mEnv->GetIntField(mTunerConfiguration, ids.mSyncId);
|
||||
}
|
||||
|
||||
// optional check to confirm class and field ids can be found.
|
||||
static void initCheckOrDie(JNIEnv *env) { (void)getIds(env); }
|
||||
};
|
||||
|
||||
static Mutex sLock;
|
||||
static SortedVector <audiotrack_callback_cookie *> sAudioTrackCallBackCookies;
|
||||
|
||||
@@ -213,24 +254,36 @@ sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audio
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static jint
|
||||
android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa,
|
||||
jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask,
|
||||
jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
|
||||
jlong nativeAudioTrack, jboolean offload) {
|
||||
|
||||
static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
|
||||
jobject jaa, jintArray jSampleRate,
|
||||
jint channelPositionMask, jint channelIndexMask,
|
||||
jint audioFormat, jint buffSizeInBytes, jint memoryMode,
|
||||
jintArray jSession, jlong nativeAudioTrack,
|
||||
jboolean offload, jint encapsulationMode,
|
||||
jobject tunerConfiguration) {
|
||||
ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
|
||||
" nativeAudioTrack=0x%" PRIX64 ", offload=%d",
|
||||
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
|
||||
nativeAudioTrack, offload);
|
||||
|
||||
sp<AudioTrack> lpTrack = 0;
|
||||
" nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
|
||||
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
|
||||
nativeAudioTrack, offload, encapsulationMode, tunerConfiguration);
|
||||
|
||||
if (jSession == NULL) {
|
||||
ALOGE("Error creating AudioTrack: invalid session ID pointer");
|
||||
return (jint) AUDIO_JAVA_ERROR;
|
||||
}
|
||||
|
||||
// TODO: replace when we land matching AudioTrack::set() in frameworks/av in r or r-tv-dev.
|
||||
if (tunerConfiguration != nullptr) {
|
||||
const TunerConfigurationHelper tunerHelper(env, tunerConfiguration);
|
||||
ALOGE("Error creating AudioTrack: unsupported tuner contentId:%d syncId:%d",
|
||||
tunerHelper.getContentId(), tunerHelper.getSyncId());
|
||||
return (jint)AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
|
||||
}
|
||||
// TODO: replace when we land matching AudioTrack::set() in frameworks/av in r or r-tv-dev.
|
||||
if (encapsulationMode != 0 /* ENCAPSULATION_MODE_NONE */) {
|
||||
ALOGE("Error creating AudioTrack: unsupported encapsulationMode %d", encapsulationMode);
|
||||
return (jint)AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
|
||||
}
|
||||
|
||||
jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
|
||||
if (nSession == NULL) {
|
||||
ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
|
||||
@@ -249,6 +302,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
|
||||
}
|
||||
|
||||
// if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one.
|
||||
sp<AudioTrack> lpTrack;
|
||||
if (nativeAudioTrack == 0) {
|
||||
if (jaa == 0) {
|
||||
ALOGE("Error creating AudioTrack: invalid audio attributes");
|
||||
@@ -1304,82 +1358,75 @@ static void android_media_AudioTrack_set_delay_padding(JNIEnv *env, jobject thi
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
// name, signature, funcPtr
|
||||
{"native_is_direct_output_supported",
|
||||
"(IIIIIII)Z",
|
||||
(void *)android_media_AudioTrack_is_direct_output_supported},
|
||||
{"native_start", "()V", (void *)android_media_AudioTrack_start},
|
||||
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
|
||||
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
|
||||
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
|
||||
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZ)I",
|
||||
(void *)android_media_AudioTrack_setup},
|
||||
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
|
||||
{"native_release", "()V", (void *)android_media_AudioTrack_release},
|
||||
{"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>},
|
||||
{"native_write_native_bytes",
|
||||
"(Ljava/nio/ByteBuffer;IIIZ)I",
|
||||
(void *)android_media_AudioTrack_write_native_bytes},
|
||||
{"native_write_short", "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>},
|
||||
{"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>},
|
||||
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
|
||||
{"native_get_buffer_size_frames",
|
||||
"()I", (void *)android_media_AudioTrack_get_buffer_size_frames},
|
||||
{"native_set_buffer_size_frames",
|
||||
"(I)I", (void *)android_media_AudioTrack_set_buffer_size_frames},
|
||||
{"native_get_buffer_capacity_frames",
|
||||
"()I", (void *)android_media_AudioTrack_get_buffer_capacity_frames},
|
||||
{"native_set_playback_rate",
|
||||
"(I)I", (void *)android_media_AudioTrack_set_playback_rate},
|
||||
{"native_get_playback_rate",
|
||||
"()I", (void *)android_media_AudioTrack_get_playback_rate},
|
||||
{"native_set_playback_params",
|
||||
"(Landroid/media/PlaybackParams;)V",
|
||||
(void *)android_media_AudioTrack_set_playback_params},
|
||||
{"native_get_playback_params",
|
||||
"()Landroid/media/PlaybackParams;",
|
||||
(void *)android_media_AudioTrack_get_playback_params},
|
||||
{"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
|
||||
{"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos},
|
||||
{"native_set_pos_update_period",
|
||||
"(I)I", (void *)android_media_AudioTrack_set_pos_update_period},
|
||||
{"native_get_pos_update_period",
|
||||
"()I", (void *)android_media_AudioTrack_get_pos_update_period},
|
||||
{"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position},
|
||||
{"native_get_position", "()I", (void *)android_media_AudioTrack_get_position},
|
||||
{"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency},
|
||||
{"native_get_underrun_count", "()I", (void *)android_media_AudioTrack_get_underrun_count},
|
||||
{"native_get_flags", "()I", (void *)android_media_AudioTrack_get_flags},
|
||||
{"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp},
|
||||
{"native_getMetrics", "()Landroid/os/PersistableBundle;",
|
||||
(void *)android_media_AudioTrack_native_getMetrics},
|
||||
{"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop},
|
||||
{"native_reload_static", "()I", (void *)android_media_AudioTrack_reload},
|
||||
{"native_get_output_sample_rate",
|
||||
"(I)I", (void *)android_media_AudioTrack_get_output_sample_rate},
|
||||
{"native_get_min_buff_size",
|
||||
"(III)I", (void *)android_media_AudioTrack_get_min_buff_size},
|
||||
{"native_setAuxEffectSendLevel",
|
||||
"(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel},
|
||||
{"native_attachAuxEffect",
|
||||
"(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
|
||||
{"native_setOutputDevice", "(I)Z",
|
||||
(void *)android_media_AudioTrack_setOutputDevice},
|
||||
{"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
|
||||
{"native_enableDeviceCallback", "()V", (void *)android_media_AudioTrack_enableDeviceCallback},
|
||||
{"native_disableDeviceCallback", "()V", (void *)android_media_AudioTrack_disableDeviceCallback},
|
||||
{"native_applyVolumeShaper",
|
||||
"(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I",
|
||||
(void *)android_media_AudioTrack_apply_volume_shaper},
|
||||
{"native_getVolumeShaperState",
|
||||
"(I)Landroid/media/VolumeShaper$State;",
|
||||
(void *)android_media_AudioTrack_get_volume_shaper_state},
|
||||
{"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation},
|
||||
{"native_getPortId", "()I", (void *)android_media_AudioTrack_get_port_id},
|
||||
{"native_set_delay_padding", "(II)V", (void *)android_media_AudioTrack_set_delay_padding},
|
||||
// name, signature, funcPtr
|
||||
{"native_is_direct_output_supported", "(IIIIIII)Z",
|
||||
(void *)android_media_AudioTrack_is_direct_output_supported},
|
||||
{"native_start", "()V", (void *)android_media_AudioTrack_start},
|
||||
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
|
||||
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
|
||||
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
|
||||
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;)I",
|
||||
(void *)android_media_AudioTrack_setup},
|
||||
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
|
||||
{"native_release", "()V", (void *)android_media_AudioTrack_release},
|
||||
{"native_write_byte", "([BIIIZ)I", (void *)android_media_AudioTrack_writeArray<jbyteArray>},
|
||||
{"native_write_native_bytes", "(Ljava/nio/ByteBuffer;IIIZ)I",
|
||||
(void *)android_media_AudioTrack_write_native_bytes},
|
||||
{"native_write_short", "([SIIIZ)I",
|
||||
(void *)android_media_AudioTrack_writeArray<jshortArray>},
|
||||
{"native_write_float", "([FIIIZ)I",
|
||||
(void *)android_media_AudioTrack_writeArray<jfloatArray>},
|
||||
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
|
||||
{"native_get_buffer_size_frames", "()I",
|
||||
(void *)android_media_AudioTrack_get_buffer_size_frames},
|
||||
{"native_set_buffer_size_frames", "(I)I",
|
||||
(void *)android_media_AudioTrack_set_buffer_size_frames},
|
||||
{"native_get_buffer_capacity_frames", "()I",
|
||||
(void *)android_media_AudioTrack_get_buffer_capacity_frames},
|
||||
{"native_set_playback_rate", "(I)I", (void *)android_media_AudioTrack_set_playback_rate},
|
||||
{"native_get_playback_rate", "()I", (void *)android_media_AudioTrack_get_playback_rate},
|
||||
{"native_set_playback_params", "(Landroid/media/PlaybackParams;)V",
|
||||
(void *)android_media_AudioTrack_set_playback_params},
|
||||
{"native_get_playback_params", "()Landroid/media/PlaybackParams;",
|
||||
(void *)android_media_AudioTrack_get_playback_params},
|
||||
{"native_set_marker_pos", "(I)I", (void *)android_media_AudioTrack_set_marker_pos},
|
||||
{"native_get_marker_pos", "()I", (void *)android_media_AudioTrack_get_marker_pos},
|
||||
{"native_set_pos_update_period", "(I)I",
|
||||
(void *)android_media_AudioTrack_set_pos_update_period},
|
||||
{"native_get_pos_update_period", "()I",
|
||||
(void *)android_media_AudioTrack_get_pos_update_period},
|
||||
{"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position},
|
||||
{"native_get_position", "()I", (void *)android_media_AudioTrack_get_position},
|
||||
{"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency},
|
||||
{"native_get_underrun_count", "()I", (void *)android_media_AudioTrack_get_underrun_count},
|
||||
{"native_get_flags", "()I", (void *)android_media_AudioTrack_get_flags},
|
||||
{"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp},
|
||||
{"native_getMetrics", "()Landroid/os/PersistableBundle;",
|
||||
(void *)android_media_AudioTrack_native_getMetrics},
|
||||
{"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop},
|
||||
{"native_reload_static", "()I", (void *)android_media_AudioTrack_reload},
|
||||
{"native_get_output_sample_rate", "(I)I",
|
||||
(void *)android_media_AudioTrack_get_output_sample_rate},
|
||||
{"native_get_min_buff_size", "(III)I", (void *)android_media_AudioTrack_get_min_buff_size},
|
||||
{"native_setAuxEffectSendLevel", "(F)I",
|
||||
(void *)android_media_AudioTrack_setAuxEffectSendLevel},
|
||||
{"native_attachAuxEffect", "(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
|
||||
{"native_setOutputDevice", "(I)Z", (void *)android_media_AudioTrack_setOutputDevice},
|
||||
{"native_getRoutedDeviceId", "()I", (void *)android_media_AudioTrack_getRoutedDeviceId},
|
||||
{"native_enableDeviceCallback", "()V",
|
||||
(void *)android_media_AudioTrack_enableDeviceCallback},
|
||||
{"native_disableDeviceCallback", "()V",
|
||||
(void *)android_media_AudioTrack_disableDeviceCallback},
|
||||
{"native_applyVolumeShaper",
|
||||
"(Landroid/media/VolumeShaper$Configuration;Landroid/media/VolumeShaper$Operation;)I",
|
||||
(void *)android_media_AudioTrack_apply_volume_shaper},
|
||||
{"native_getVolumeShaperState", "(I)Landroid/media/VolumeShaper$State;",
|
||||
(void *)android_media_AudioTrack_get_volume_shaper_state},
|
||||
{"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation},
|
||||
{"native_getPortId", "()I", (void *)android_media_AudioTrack_get_port_id},
|
||||
{"native_set_delay_padding", "(II)V", (void *)android_media_AudioTrack_set_delay_padding},
|
||||
};
|
||||
|
||||
|
||||
// field names found in android/media/AudioTrack.java
|
||||
#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative"
|
||||
#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj"
|
||||
@@ -1436,6 +1483,10 @@ int register_android_media_AudioTrack(JNIEnv *env)
|
||||
gPlaybackParamsFields.init(env);
|
||||
|
||||
gVolumeShaperFields.init(env);
|
||||
|
||||
// optional check that the TunerConfiguration class and fields exist.
|
||||
TunerConfigurationHelper::initCheckOrDie(env);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,36 @@ public class AudioTrack extends PlayerBase
|
||||
|
||||
private final static String TAG = "android.media.AudioTrack";
|
||||
|
||||
/** @hide */
|
||||
@IntDef({
|
||||
ENCAPSULATION_MODE_NONE,
|
||||
ENCAPSULATION_MODE_ELEMENTARY_STREAM,
|
||||
ENCAPSULATION_MODE_HANDLE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface EncapsulationMode {}
|
||||
|
||||
// Important: The ENCAPSULATION_MODE values must be kept in sync with native header files.
|
||||
/**
|
||||
* This mode indicates no metadata encapsulation,
|
||||
* which is the default mode for sending audio data
|
||||
* through {@code AudioTrack}.
|
||||
*/
|
||||
public static final int ENCAPSULATION_MODE_NONE = 0;
|
||||
/**
|
||||
* This mode indicates metadata encapsulation with an elementary stream payload.
|
||||
* Both compressed and PCM format is allowed.
|
||||
*
|
||||
* TODO(b/147778408) Link: See the Android developers guide for more information.
|
||||
*/
|
||||
public static final int ENCAPSULATION_MODE_ELEMENTARY_STREAM = 1;
|
||||
/**
|
||||
* This mode indicates metadata encapsulation with a handle payload.
|
||||
* The handle is a 64 bit long, provided by the Tuner API.
|
||||
*
|
||||
* TODO(b/147778408) Link: Fill in Tuner API to obtain the handle.
|
||||
*/
|
||||
public static final int ENCAPSULATION_MODE_HANDLE = 2;
|
||||
|
||||
/** @hide */
|
||||
@IntDef({
|
||||
@@ -592,11 +622,13 @@ public class AudioTrack extends PlayerBase
|
||||
public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
|
||||
int mode, int sessionId)
|
||||
throws IllegalArgumentException {
|
||||
this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/);
|
||||
this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/,
|
||||
ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */);
|
||||
}
|
||||
|
||||
private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
|
||||
int mode, int sessionId, boolean offload)
|
||||
int mode, int sessionId, boolean offload, int encapsulationMode,
|
||||
@Nullable TunerConfiguration tunerConfiguration)
|
||||
throws IllegalArgumentException {
|
||||
super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK);
|
||||
// mState already == STATE_UNINITIALIZED
|
||||
@@ -663,7 +695,7 @@ public class AudioTrack extends PlayerBase
|
||||
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
|
||||
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
|
||||
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
|
||||
offload);
|
||||
offload, encapsulationMode, tunerConfiguration);
|
||||
if (initResult != SUCCESS) {
|
||||
loge("Error code "+initResult+" when initializing AudioTrack.");
|
||||
return; // with mState == STATE_UNINITIALIZED
|
||||
@@ -672,6 +704,8 @@ public class AudioTrack extends PlayerBase
|
||||
mSampleRate = sampleRate[0];
|
||||
mSessionId = session[0];
|
||||
|
||||
// TODO: consider caching encapsulationMode and tunerConfiguration in the Java object.
|
||||
|
||||
if ((mAttributes.getFlags() & AudioAttributes.FLAG_HW_AV_SYNC) != 0) {
|
||||
int frameSizeInBytes;
|
||||
if (AudioFormat.isEncodingLinearFrames(mAudioFormat)) {
|
||||
@@ -745,7 +779,9 @@ public class AudioTrack extends PlayerBase
|
||||
0 /*mDataLoadMode - NA*/,
|
||||
session,
|
||||
nativeTrackInJavaObj,
|
||||
false /*offload*/);
|
||||
false /*offload*/,
|
||||
ENCAPSULATION_MODE_NONE,
|
||||
null /* tunerConfiguration */);
|
||||
if (initResult != SUCCESS) {
|
||||
loge("Error code "+initResult+" when initializing AudioTrack.");
|
||||
return; // with mState == STATE_UNINITIALIZED
|
||||
@@ -757,6 +793,99 @@ public class AudioTrack extends PlayerBase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TunerConfiguration is used to convey tuner information
|
||||
* from the android.media.tv.Tuner API to AudioTrack construction.
|
||||
*
|
||||
* Use the Builder to construct the TunerConfiguration object,
|
||||
* which is then used by the {@link AudioTrack.Builder} to create an AudioTrack.
|
||||
*/
|
||||
public static class TunerConfiguration {
|
||||
private final int mContentId;
|
||||
private final int mSyncId;
|
||||
|
||||
private TunerConfiguration(int contentId, int syncId) {
|
||||
mContentId = contentId;
|
||||
mSyncId = syncId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contentId.
|
||||
*/
|
||||
public int getContentId() {
|
||||
return mContentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the syncId.
|
||||
*/
|
||||
public int getSyncId() {
|
||||
return mSyncId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link AudioTrack.TunerConfiguration} objects.
|
||||
*/
|
||||
public static class Builder {
|
||||
private int mContentId;
|
||||
private int mSyncId;
|
||||
|
||||
/**
|
||||
* Sets the contentId from the Tuner filter.
|
||||
*
|
||||
* @param contentId selects the audio stream to use.
|
||||
* See android.media.tv.tuner.filter.Filter#getId().
|
||||
* This is always a positive number.
|
||||
* TODO(b/147778408) Link to tuner filter doc when unhidden.
|
||||
* @return the same Builder instance.
|
||||
*/
|
||||
public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) {
|
||||
if (contentId < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"contentId " + contentId + " must be positive");
|
||||
}
|
||||
mContentId = contentId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the syncId from the Tuner filter.
|
||||
*
|
||||
* @param syncId selects the clock to use for synchronization
|
||||
* of audio with other streams such as video.
|
||||
* See android.media.tv.tuner.Tuner#getAvSyncHwId().
|
||||
* This is always a positive number.
|
||||
* TODO(b/147778408) Link to tuner filter doc when unhidden.
|
||||
* @return the same Builder instance.
|
||||
*/
|
||||
public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) {
|
||||
if (syncId < 1) {
|
||||
throw new IllegalArgumentException("syncId " + syncId + " must be positive");
|
||||
}
|
||||
mSyncId = syncId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link AudioTrack.TunerConfiguration} instance initialized with
|
||||
* the parameters set on this {@code Builder}.
|
||||
*
|
||||
* @return a new successfully initialized {@link AudioTrack.TunerConfiguration}.
|
||||
* @throws UnsupportedOperationException if the parameters set on the
|
||||
* {@code Builder} are incompatible.
|
||||
*/
|
||||
public @NonNull TunerConfiguration build() {
|
||||
if (mContentId < 1 || mSyncId < 1) {
|
||||
throw new UnsupportedOperationException(
|
||||
"contentId " + mContentId
|
||||
+ " syncId " + mSyncId
|
||||
+ " must be set");
|
||||
}
|
||||
return new TunerConfiguration(mContentId, mSyncId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link AudioTrack} objects.
|
||||
* Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio
|
||||
@@ -799,10 +928,12 @@ public class AudioTrack extends PlayerBase
|
||||
private AudioAttributes mAttributes;
|
||||
private AudioFormat mFormat;
|
||||
private int mBufferSizeInBytes;
|
||||
private int mEncapsulationMode = ENCAPSULATION_MODE_NONE;
|
||||
private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
|
||||
private int mMode = MODE_STREAM;
|
||||
private int mPerformanceMode = PERFORMANCE_MODE_NONE;
|
||||
private boolean mOffload = false;
|
||||
private TunerConfiguration mTunerConfiguration;
|
||||
|
||||
/**
|
||||
* Constructs a new Builder with the default values as described above.
|
||||
@@ -868,6 +999,34 @@ public class AudioTrack extends PlayerBase
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the encapsulation mode.
|
||||
*
|
||||
* Encapsulation mode allows metadata to be sent together with
|
||||
* the audio data payload in a {@code ByteBuffer}.
|
||||
* The data format is specified in the Android developers site.
|
||||
*
|
||||
* TODO(b/147778408) Link to doc page.
|
||||
*
|
||||
* @param encapsulationMode one of {@link AudioTrack#ENCAPSULATION_MODE_NONE},
|
||||
* {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM},
|
||||
* {@link AudioTrack#ENCAPSULATION_MODE_HANDLE}.
|
||||
* @return the same Builder instance.
|
||||
*/
|
||||
public @NonNull Builder setEncapsulationMode(@EncapsulationMode int encapsulationMode) {
|
||||
switch (encapsulationMode) {
|
||||
case ENCAPSULATION_MODE_NONE:
|
||||
case ENCAPSULATION_MODE_ELEMENTARY_STREAM:
|
||||
case ENCAPSULATION_MODE_HANDLE:
|
||||
mEncapsulationMode = encapsulationMode;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid encapsulation mode " + encapsulationMode);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mode under which buffers of audio data are transferred from the
|
||||
* {@link AudioTrack} to the framework.
|
||||
@@ -948,6 +1107,25 @@ public class AudioTrack extends PlayerBase
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tuner configuration for the {@code AudioTrack}.
|
||||
*
|
||||
* The {@link AudioTrack.TunerConfiguration} consists of parameters obtained from
|
||||
* the Android TV tuner API which indicate the audio content stream id and the
|
||||
* synchronization id for the {@code AudioTrack}.
|
||||
*
|
||||
* @param tunerConfiguration obtained by {@link AudioTrack.TunerConfiguration.Builder}.
|
||||
* @return the same Builder instance.
|
||||
*/
|
||||
public @NonNull Builder setTunerConfiguration(
|
||||
@NonNull TunerConfiguration tunerConfiguration) {
|
||||
if (tunerConfiguration == null) {
|
||||
throw new IllegalArgumentException("tunerConfiguration is null");
|
||||
}
|
||||
mTunerConfiguration = tunerConfiguration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link AudioTrack} instance initialized with all the parameters set
|
||||
* on this <code>Builder</code>.
|
||||
@@ -1003,6 +1181,8 @@ public class AudioTrack extends PlayerBase
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check mEncapsulationMode compatibility with MODE_STATIC, etc?
|
||||
|
||||
try {
|
||||
// If the buffer size is not specified in streaming mode,
|
||||
// use a single frame for the buffer size and let the
|
||||
@@ -1012,7 +1192,8 @@ public class AudioTrack extends PlayerBase
|
||||
* mFormat.getBytesPerSample(mFormat.getEncoding());
|
||||
}
|
||||
final AudioTrack track = new AudioTrack(
|
||||
mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload);
|
||||
mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload,
|
||||
mEncapsulationMode, mTunerConfiguration);
|
||||
if (track.getState() == STATE_UNINITIALIZED) {
|
||||
// release is not necessary
|
||||
throw new UnsupportedOperationException("Cannot create AudioTrack");
|
||||
@@ -3595,7 +3776,7 @@ public class AudioTrack extends PlayerBase
|
||||
Object /*AudioAttributes*/ attributes,
|
||||
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
||||
int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack,
|
||||
boolean offload);
|
||||
boolean offload, int encapsulationMode, Object tunerConfiguration);
|
||||
|
||||
private native final void native_finalize();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user