Merge "Allow sample rate UNSPECIFIED to mean a route-dependent value" into nyc-dev

This commit is contained in:
Glenn Kasten
2016-02-26 00:17:44 +00:00
committed by Android (Google) Code Review
10 changed files with 108 additions and 51 deletions

View File

@@ -19767,6 +19767,7 @@ package android.media {
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {

View File

@@ -21263,6 +21263,7 @@ package android.media {
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {

View File

@@ -19776,6 +19776,7 @@ package android.media {
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
field public static final int SAMPLE_RATE_UNSPECIFIED = 0; // 0x0
}
public static class AudioFormat.Builder {

View File

@@ -180,9 +180,13 @@ static sp<AudioRecord> setAudioRecord(JNIEnv* env, jobject thiz, const sp<AudioR
// ----------------------------------------------------------------------------
static jint
android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jobject jaa, jint sampleRateInHertz, jint channelMask, jint channelIndexMask,
jobject jaa, jintArray jSampleRate, jint channelMask, jint channelIndexMask,
jint audioFormat, jint buffSizeInBytes, jintArray jSession, jstring opPackageName)
{
jint elements[1];
env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
int sampleRateInHertz = elements[0];
//ALOGV(">> Entering android_media_AudioRecord_setup");
//ALOGV("sampleRate=%d, audioFormat=%d, channel mask=%x, buffSizeInBytes=%d",
// sampleRateInHertz, audioFormat, channelMask, buffSizeInBytes);
@@ -304,6 +308,11 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
{
const jint elements[1] = { (jint) lpRecorder->getSampleRate() };
env->SetIntArrayRegion(jSampleRate, 0, 1, elements);
}
{ // scope for the lock
Mutex::Autolock l(sLock);
sAudioRecordCallBackCookies.add(lpCallbackData);
@@ -717,7 +726,7 @@ static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[ILjava/lang/String;)I",
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIII[ILjava/lang/String;)I",
(void *)android_media_AudioRecord_setup},
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},

View File

@@ -215,9 +215,13 @@ static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks(
static jint
android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jobject jaa,
jint sampleRateInHertz, jint channelPositionMask, jint channelIndexMask,
jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask,
jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
jint elements[1];
env->GetIntArrayRegion(jSampleRate, 0, 1, elements);
int sampleRateInHertz = elements[0];
ALOGV("sampleRate=%d, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d",
sampleRateInHertz, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes);
@@ -370,6 +374,11 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
{
const jint elements[1] = { (jint) lpTrack->getSampleRate() };
env->SetIntArrayRegion(jSampleRate, 0, 1, elements);
}
{ // scope for the lock
Mutex::Autolock l(sLock);
sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData);
@@ -1114,7 +1123,7 @@ static const JNINativeMethod gMethods[] = {
{"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[I)I",
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[I)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},

View File

@@ -335,6 +335,24 @@ public class AudioFormat implements Parcelable {
CHANNEL_OUT_LOW_FREQUENCY);
// CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
/** Minimum value for sample rate,
* assuming AudioTrack and AudioRecord share the same limitations.
* @hide
*/
// never unhide
public static final int SAMPLE_RATE_HZ_MIN = 4000;
/** Maximum value for sample rate,
* assuming AudioTrack and AudioRecord share the same limitations.
* @hide
*/
// never unhide
public static final int SAMPLE_RATE_HZ_MAX = 192000;
/** Sample rate will be a route-dependent value.
* For AudioTrack, it is usually the sink sample rate,
* and for AudioRecord it is usually the source sample rate.
*/
public static final int SAMPLE_RATE_UNSPECIFIED = 0;
/**
* @hide
* Return the input channel mask corresponding to an output channel mask.
@@ -561,7 +579,7 @@ public class AudioFormat implements Parcelable {
}
/**
* Constructor used by the JNI
* Constructor used by the JNI. Parameters are not checked for validity.
*/
// Update sound trigger JNI in core/jni/android_hardware_SoundTrigger.cpp when modifying this
// constructor
@@ -610,12 +628,9 @@ public class AudioFormat implements Parcelable {
/**
* Return the sample rate.
* @return one of the values that can be set in {@link Builder#setSampleRate(int)} or
* 0 if not set.
* {@link #SAMPLE_RATE_UNSPECIFIED} if not set.
*/
public int getSampleRate() {
if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) == 0) {
return 0;
}
return mSampleRate;
}
@@ -687,7 +702,7 @@ public class AudioFormat implements Parcelable {
*/
public static class Builder {
private int mEncoding = ENCODING_INVALID;
private int mSampleRate = 0;
private int mSampleRate = SAMPLE_RATE_UNSPECIFIED;
private int mChannelMask = CHANNEL_INVALID;
private int mChannelIndexMask = 0;
private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
@@ -718,6 +733,8 @@ public class AudioFormat implements Parcelable {
public AudioFormat build() {
AudioFormat af = new AudioFormat(1980/*ignored*/);
af.mEncoding = mEncoding;
// not calling setSampleRate is equivalent to calling
// setSampleRate(SAMPLE_RATE_UNSPECIFIED)
af.mSampleRate = mSampleRate;
af.mChannelMask = mChannelMask;
af.mChannelIndexMask = mChannelIndexMask;
@@ -795,7 +812,7 @@ public class AudioFormat implements Parcelable {
* are specified but do not have the same channel count.
*/
public @NonNull Builder setChannelMask(int channelMask) {
if (channelMask == 0) {
if (channelMask == CHANNEL_INVALID) {
throw new IllegalArgumentException("Invalid zero channel mask");
} else if (/* channelMask != 0 && */ mChannelIndexMask != 0 &&
Integer.bitCount(channelMask) != Integer.bitCount(mChannelIndexMask)) {
@@ -867,7 +884,11 @@ public class AudioFormat implements Parcelable {
* @throws java.lang.IllegalArgumentException
*/
public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {
if ((sampleRate <= 0) || (sampleRate > 192000)) {
// TODO Consider whether to keep the MIN and MAX range checks here.
// It is not necessary and poses the problem of defining the limits independently from
// native implementation or platform capabilities.
if (((sampleRate < SAMPLE_RATE_HZ_MIN) || (sampleRate > SAMPLE_RATE_HZ_MAX)) &&
sampleRate != SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException("Invalid sample rate " + sampleRate);
}
mSampleRate = sampleRate;

View File

@@ -3321,6 +3321,7 @@ public class AudioManager {
* Used as a key for {@link #getProperty} to request the native or optimal output sample rate
* for this device's primary output stream, in decimal Hz.
*/
// FIXME Deprecate
public static final String PROPERTY_OUTPUT_SAMPLE_RATE =
"android.media.property.OUTPUT_SAMPLE_RATE";
@@ -3328,6 +3329,7 @@ public class AudioManager {
* Used as a key for {@link #getProperty} to request the native or optimal output buffer size
* for this device's primary output stream, in decimal PCM frames.
*/
// FIXME Deprecate
public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER =
"android.media.property.OUTPUT_FRAMES_PER_BUFFER";

View File

@@ -57,10 +57,6 @@ public class AudioRecord implements AudioRouting
// Constants
//--------------------
/** Minimum value for sample rate */
private static final int SAMPLE_RATE_HZ_MIN = 4000;
/** Maximum value for sample rate */
private static final int SAMPLE_RATE_HZ_MAX = 192000;
/**
* indicates AudioRecord state is not successfully initialized.
@@ -168,8 +164,9 @@ public class AudioRecord implements AudioRouting
//--------------------
/**
* The audio data sampling rate in Hz.
* Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
*/
private int mSampleRate;
private int mSampleRate; // initialized by all constructors via audioParamCheck()
/**
* The number of input audio channels (1 is mono, 2 is stereo)
*/
@@ -251,6 +248,9 @@ public class AudioRecord implements AudioRouting
* @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only
* rate that is guaranteed to work on all devices, but other rates such as 22050,
* 16000, and 11025 may work on some devices.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
* which is usually the sample rate of the source.
* {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_IN_MONO} and
* {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is guaranteed
@@ -337,16 +337,9 @@ public class AudioRecord implements AudioRouting
mAudioAttributes = attributes;
}
int rate = 0;
if ((format.getPropertySetMask()
& AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
{
rate = format.getSampleRate();
} else {
rate = AudioSystem.getPrimaryOutputSamplingRate();
if (rate <= 0) {
rate = 44100;
}
int rate = format.getSampleRate();
if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
rate = 0;
}
int encoding = AudioFormat.ENCODING_DEFAULT;
@@ -373,12 +366,13 @@ public class AudioRecord implements AudioRouting
audioBuffSizeCheck(bufferSizeInBytes);
int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
//TODO: update native initialization when information about hardware init failure
// due to capture device already open is available.
int initResult = native_setup( new WeakReference<AudioRecord>(this),
mAudioAttributes, mSampleRate, mChannelMask, mChannelIndexMask,
mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
mAudioFormat, mNativeBufferSizeInBytes,
session, ActivityThread.currentOpPackageName());
if (initResult != SUCCESS) {
@@ -386,6 +380,7 @@ public class AudioRecord implements AudioRouting
return; // with mState == STATE_UNINITIALIZED
}
mSampleRate = sampleRate[0];
mSessionId = session[0];
mState = STATE_INITIALIZED;
@@ -623,6 +618,7 @@ public class AudioRecord implements AudioRouting
return mask;
}
// postconditions:
// mRecordSource is valid
// mAudioFormat is valid
@@ -642,7 +638,9 @@ public class AudioRecord implements AudioRouting
//--------------
// sample rate
if ((sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX)) {
if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException(sampleRateInHz
+ "Hz is not a supported sample rate.");
}
@@ -714,7 +712,11 @@ public class AudioRecord implements AudioRouting
// Getters
//--------------------
/**
* Returns the configured audio data sample rate in Hz
* Returns the configured audio sink sample rate in Hz.
* The sink sample rate never changes after construction.
* If the constructor had a specific sample rate, then the sink sample rate is that value.
* If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
* then the sink sample rate is a route-dependent default value based on the source [sic].
*/
public int getSampleRate() {
return mSampleRate;
@@ -861,6 +863,7 @@ public class AudioRecord implements AudioRouting
* See {@link #AudioRecord(int, int, int, int, int)} for more information on valid
* configuration values.
* @param sampleRateInHz the sample rate expressed in Hertz.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_IN_MONO} and
* {@link AudioFormat#CHANNEL_IN_STEREO}
@@ -1708,7 +1711,7 @@ public class AudioRecord implements AudioRouting
private native final int native_setup(Object audiorecord_this,
Object /*AudioAttributes*/ attributes,
int sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int[] sessionId, String opPackageName);
// TODO remove: implementation calls directly into implementation of native_release()

View File

@@ -91,11 +91,6 @@ public class AudioTrack implements AudioRouting
*/
private static final float GAIN_MAX = 1.0f;
/** Minimum value for sample rate */
private static final int SAMPLE_RATE_HZ_MIN = 4000;
/** Maximum value for sample rate */
private static final int SAMPLE_RATE_HZ_MAX = 192000;
/** Maximum value for AudioTrack channel count
* @hide public for MediaCode only, do not un-hide or change to a numeric literal
*/
@@ -254,6 +249,7 @@ public class AudioTrack implements AudioRouting
private final Looper mInitializationLooper;
/**
* The audio data source sampling rate in Hz.
* Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
*/
private int mSampleRate; // initialized by all constructors via audioParamCheck()
/**
@@ -340,6 +336,9 @@ public class AudioTrack implements AudioRouting
* {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
* {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
* @param sampleRateInHz the initial source sample rate expressed in Hz.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
* which is usually the sample rate of the sink.
* {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -389,6 +388,8 @@ public class AudioTrack implements AudioRouting
* {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
* {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
* @param sampleRateInHz the initial source sample rate expressed in Hz.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
* which is usually the sample rate of the sink.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -461,16 +462,11 @@ public class AudioTrack implements AudioRouting
looper = Looper.getMainLooper();
}
int rate = 0;
if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
{
rate = format.getSampleRate();
} else {
rate = AudioSystem.getPrimaryOutputSamplingRate();
if (rate <= 0) {
rate = 44100;
}
int rate = format.getSampleRate();
if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
rate = 0;
}
int channelIndexMask = 0;
if ((format.getPropertySetMask()
& AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) {
@@ -503,17 +499,19 @@ public class AudioTrack implements AudioRouting
throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
}
int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
// native initialization
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
mSampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
}
mSampleRate = sampleRate[0];
mSessionId = session[0];
if (mDataLoadMode == MODE_STATIC) {
@@ -712,7 +710,7 @@ public class AudioTrack implements AudioRouting
if (mFormat == null) {
mFormat = new AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
.setSampleRate(AudioSystem.getPrimaryOutputSamplingRate())
//.setSampleRate(AudioFormat.SAMPLE_RATE_UNSPECIFIED)
.setEncoding(AudioFormat.ENCODING_DEFAULT)
.build();
}
@@ -762,7 +760,9 @@ public class AudioTrack implements AudioRouting
int audioFormat, int mode) {
//--------------
// sample rate, note these values are subject to change
if (sampleRateInHz < SAMPLE_RATE_HZ_MIN || sampleRateInHz > SAMPLE_RATE_HZ_MAX) {
if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
throw new IllegalArgumentException(sampleRateInHz
+ "Hz is not a supported sample rate.");
}
@@ -948,7 +948,13 @@ public class AudioTrack implements AudioRouting
}
/**
* Returns the configured audio data sample rate in Hz
* Returns the configured audio source sample rate in Hz.
* The initial source sample rate depends on the constructor parameters,
* but the source sample rate may change if {@link #setPlaybackRate(int)} is called.
* If the constructor had a specific sample rate, then the initial sink sample rate is that
* value.
* If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
* then the initial sink sample rate is a route-dependent default value based on the source [sic].
*/
public int getSampleRate() {
return mSampleRate;
@@ -1218,6 +1224,7 @@ public class AudioTrack implements AudioRouting
* to a higher value than the initial source sample rate, be sure to configure the buffer size
* based on the highest planned sample rate.
* @param sampleRateInHz the source sample rate expressed in Hz.
* {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
* @param channelConfig describes the configuration of the audio channels.
* See {@link AudioFormat#CHANNEL_OUT_MONO} and
* {@link AudioFormat#CHANNEL_OUT_STEREO}
@@ -1255,7 +1262,9 @@ public class AudioTrack implements AudioRouting
}
// sample rate, note these values are subject to change
if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {
// Note: AudioFormat.SAMPLE_RATE_UNSPECIFIED is not allowed
if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) ||
(sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) {
loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
return ERROR_BAD_VALUE;
}
@@ -2763,7 +2772,7 @@ public class AudioTrack implements AudioRouting
// AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC
private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
Object /*AudioAttributes*/ attributes,
int sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int mode, int[] sessionId);
private native final void native_finalize();

View File

@@ -277,6 +277,7 @@ public class AudioMix {
mRouteFlags = ROUTE_FLAG_RENDER;
}
if (mFormat == null) {
// FIXME Can we eliminate this? Will AudioMix work with an unspecified sample rate?
int rate = AudioSystem.getPrimaryOutputSamplingRate();
if (rate <= 0) {
rate = 44100;