diff options
| -rw-r--r-- | api/current.txt | 3 | ||||
| -rw-r--r-- | core/jni/android_media_AudioFormat.h | 22 | ||||
| -rw-r--r-- | core/jni/android_media_AudioTrack.cpp | 27 | ||||
| -rw-r--r-- | media/java/android/media/AudioFormat.java | 53 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 4 | ||||
| -rw-r--r-- | media/java/android/media/AudioTrack.java | 44 |
6 files changed, 106 insertions, 47 deletions
diff --git a/api/current.txt b/api/current.txt index f6ccc67..65589d4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13739,7 +13739,9 @@ package android.media { field public static final int CHANNEL_OUT_QUAD = 204; // 0xcc field public static final int CHANNEL_OUT_STEREO = 12; // 0xc field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c + field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_E_AC3 = 6; // 0x6 field public static final int ENCODING_INVALID = 0; // 0x0 field public static final int ENCODING_PCM_16BIT = 2; // 0x2 field public static final int ENCODING_PCM_8BIT = 3; // 0x3 @@ -13813,6 +13815,7 @@ package android.media { field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0 field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1 field public static final int ERROR = -1; // 0xffffffff + field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE"; field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"; field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE"; diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index a2b1ed9..807dd32 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -20,11 +20,15 @@ #include <system/audio.h> // keep these values in sync with AudioFormat.java -#define ENCODING_PCM_16BIT 2 -#define ENCODING_PCM_8BIT 3 -#define ENCODING_PCM_FLOAT 4 -#define ENCODING_INVALID 0 -#define ENCODING_DEFAULT 1 +#define ENCODING_PCM_16BIT 2 +#define ENCODING_PCM_8BIT 3 +#define ENCODING_PCM_FLOAT 4 +#define ENCODING_AC3 5 +#define ENCODING_E_AC3 6 +#define ENCODING_INVALID 0 +#define ENCODING_DEFAULT 1 + + #define CHANNEL_INVALID 0 #define CHANNEL_OUT_DEFAULT 1 @@ -38,6 +42,10 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_PCM_8_BIT; case ENCODING_PCM_FLOAT: return AUDIO_FORMAT_PCM_FLOAT; + case ENCODING_AC3: + return AUDIO_FORMAT_AC3; + case ENCODING_E_AC3: + return AUDIO_FORMAT_E_AC3; case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; default: @@ -54,6 +62,10 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_PCM_8BIT; case AUDIO_FORMAT_PCM_FLOAT: return ENCODING_PCM_FLOAT; + case AUDIO_FORMAT_AC3: + return ENCODING_AC3; + case AUDIO_FORMAT_E_AC3: + return ENCODING_E_AC3; case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; default: diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index e548e91..264a9ae 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -220,8 +220,13 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, } // compute the frame count - const size_t bytesPerSample = audio_bytes_per_sample(format); - size_t frameCount = buffSizeInBytes / (channelCount * bytesPerSample); + size_t frameCount; + if (audio_is_linear_pcm(format)) { + const size_t bytesPerSample = audio_bytes_per_sample(format); + frameCount = buffSizeInBytes / (channelCount * bytesPerSample); + } else { + frameCount = buffSizeInBytes; + } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { @@ -266,7 +271,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, format,// word length, PCM nativeChannelMask, frameCount, - AUDIO_OUTPUT_FLAG_NONE, + audio_is_linear_pcm(format) ? AUDIO_OUTPUT_FLAG_NONE : AUDIO_OUTPUT_FLAG_DIRECT, audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 0,// shared mem @@ -478,14 +483,6 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* da switch (format) { default: - // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT, - // AUDIO_FORMAT_PCM_8_BIT, and AUDIO_FORMAT_PCM_FLOAT, - // due to the limited set of values for audioFormat. - // The next section of the switch will probably work for more formats, but it has only - // been tested for AUDIO_FORMAT_PCM_16_BIT and AUDIO_FORMAT_PCM_FLOAT, - // so that's why the "default" case fails. - break; - case AUDIO_FORMAT_PCM_FLOAT: case AUDIO_FORMAT_PCM_16_BIT: { // writing to shared memory, check for capacity @@ -904,8 +901,12 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi return -1; } const audio_format_t format = audioFormatToNative(audioFormat); - const size_t bytesPerSample = audio_bytes_per_sample(format); - return frameCount * channelCount * bytesPerSample; + if (audio_is_linear_pcm(format)) { + const size_t bytesPerSample = audio_bytes_per_sample(format); + return frameCount * channelCount * bytesPerSample; + } else { + return frameCount; + } } // ---------------------------------------------------------------------------- diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index e05aef0..bd2be1b 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -25,10 +25,10 @@ import java.lang.annotation.RetentionPolicy; * The AudioFormat class is used to access a number of audio format and * channel configuration constants. They are for instance used * in {@link AudioTrack} and {@link AudioRecord}. - * + * */ public class AudioFormat { - + //--------------------------------------------------------- // Constants //-------------------- @@ -44,6 +44,10 @@ public class AudioFormat { public static final int ENCODING_PCM_8BIT = 3; /** Audio data format: single-precision floating-point per sample */ public static final int ENCODING_PCM_FLOAT = 4; + /** Audio data format: AC-3 compressed */ + public static final int ENCODING_AC3 = 5; + /** Audio data format: E-AC-3 compressed */ + public static final int ENCODING_E_AC3 = 6; /** Invalid audio channel configuration */ /** @deprecated use CHANNEL_INVALID instead */ @@ -152,11 +156,44 @@ public class AudioFormat { switch (audioFormat) { case ENCODING_PCM_8BIT: return 1; + case ENCODING_PCM_16BIT: + case ENCODING_DEFAULT: + return 2; case ENCODING_PCM_FLOAT: return 4; + case ENCODING_INVALID: + default: + throw new IllegalArgumentException("Bad audio format " + audioFormat); + } + } + + /** @hide */ + public static boolean isValidEncoding(int audioFormat) + { + switch (audioFormat) { + case ENCODING_PCM_8BIT: case ENCODING_PCM_16BIT: + case ENCODING_PCM_FLOAT: + case ENCODING_AC3: + case ENCODING_E_AC3: + return true; + default: + return false; + } + } + + /** @hide */ + public static boolean isEncodingLinearPcm(int audioFormat) + { + switch (audioFormat) { + case ENCODING_PCM_8BIT: + case ENCODING_PCM_16BIT: + case ENCODING_PCM_FLOAT: case ENCODING_DEFAULT: - return 2; + return true; + case ENCODING_AC3: + case ENCODING_E_AC3: + return false; case ENCODING_INVALID: default: throw new IllegalArgumentException("Bad audio format " + audioFormat); @@ -236,7 +273,9 @@ public class AudioFormat { * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT}, * {@link AudioFormat#ENCODING_PCM_8BIT}, * {@link AudioFormat#ENCODING_PCM_16BIT}, - * {@link AudioFormat#ENCODING_PCM_FLOAT}. + * {@link AudioFormat#ENCODING_PCM_FLOAT}, + * {@link AudioFormat#ENCODING_AC3}, + * {@link AudioFormat#ENCODING_E_AC3}. * @return the same Builder instance. * @throws java.lang.IllegalArgumentException */ @@ -248,6 +287,8 @@ public class AudioFormat { case ENCODING_PCM_8BIT: case ENCODING_PCM_16BIT: case ENCODING_PCM_FLOAT: + case ENCODING_AC3: + case ENCODING_E_AC3: mEncoding = encoding; break; case ENCODING_INVALID: @@ -311,7 +352,9 @@ public class AudioFormat { ENCODING_DEFAULT, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, - ENCODING_PCM_FLOAT + ENCODING_PCM_FLOAT, + ENCODING_AC3, + ENCODING_E_AC3 }) @Retention(RetentionPolicy.SOURCE) public @interface Encoding {} diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 3238498..cf6d35e 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2974,7 +2974,9 @@ public class AudioManager { /** @hide */ public static final int ERROR_NO_INIT = AudioSystem.NO_INIT; - /** @hide + /** + * An error code indicating that the object reporting it is no longer valid and needs to + * be recreated. */ public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index cfd9c3b..3a72833 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -457,25 +457,19 @@ public class AudioTrack //-------------- // audio format - switch (audioFormat) { - case AudioFormat.ENCODING_DEFAULT: - mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; - break; - case AudioFormat.ENCODING_PCM_16BIT: - case AudioFormat.ENCODING_PCM_8BIT: - case AudioFormat.ENCODING_PCM_FLOAT: - mAudioFormat = audioFormat; - break; - default: - throw new IllegalArgumentException("Unsupported sample encoding." - + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT" - + " or ENCODING_PCM_FLOAT" - + "."); + if (audioFormat == AudioFormat.ENCODING_DEFAULT) { + audioFormat = AudioFormat.ENCODING_PCM_16BIT; + } + + if (!AudioFormat.isValidEncoding(audioFormat)) { + throw new IllegalArgumentException("Unsupported audio encoding."); } + mAudioFormat = audioFormat; //-------------- // audio load mode - if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) { + if (((mode != MODE_STREAM) && (mode != MODE_STATIC)) || + ((mode != MODE_STREAM) && !AudioFormat.isEncodingLinearPcm(mAudioFormat))) { throw new IllegalArgumentException("Invalid mode."); } mDataLoadMode = mode; @@ -522,8 +516,13 @@ public class AudioTrack private void audioBuffSizeCheck(int audioBufferSize) { // NB: this section is only valid with PCM data. // To update when supporting compressed formats - int frameSizeInBytes = mChannelCount - * (AudioFormat.getBytesPerSample(mAudioFormat)); + int frameSizeInBytes; + if (AudioFormat.isEncodingLinearPcm(mAudioFormat)) { + frameSizeInBytes = mChannelCount + * (AudioFormat.getBytesPerSample(mAudioFormat)); + } else { + frameSizeInBytes = 1; + } if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { throw new IllegalArgumentException("Invalid audio buffer size."); } @@ -757,9 +756,7 @@ public class AudioTrack } } - if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT) - && (audioFormat != AudioFormat.ENCODING_PCM_8BIT) - && (audioFormat != AudioFormat.ENCODING_PCM_FLOAT)) { + if (!AudioFormat.isValidEncoding(audioFormat)) { loge("getMinBufferSize(): Invalid audio format."); return ERROR_BAD_VALUE; } @@ -1164,7 +1161,9 @@ public class AudioTrack * @param sizeInBytes the number of bytes to read in audioData after the offset. * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if - * the parameters don't resolve to valid data and indexes. + * the parameters don't resolve to valid data and indexes, or + * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and + * needs to be recreated. */ public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) { @@ -1213,7 +1212,7 @@ public class AudioTrack public int write(short[] audioData, int offsetInShorts, int sizeInShorts) { - if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { + if (mState == STATE_UNINITIALIZED || mAudioFormat != AudioFormat.ENCODING_PCM_16BIT) { return ERROR_INVALID_OPERATION; } @@ -1473,7 +1472,6 @@ public class AudioTrack void onPeriodicNotification(AudioTrack track); } - //--------------------------------------------------------- // Inner classes //-------------------- |
