Merge "AudioFormat: Add ENCODING_PCM_32BIT ENCODING_PCM_24BIT_PACKED" am: e468f6c151 am: 32010fbba7

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1670486

Change-Id: I1b3354768d9ed8539459c48f5bb1a051cc9ebf24
This commit is contained in:
Andy Hung
2021-04-23 20:42:57 +00:00
committed by Automerger Merge Worker
6 changed files with 127 additions and 29 deletions

View File

@@ -23,6 +23,7 @@ import android.util.SparseIntArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Objects;
import java.util.TreeSet;
@@ -467,9 +468,32 @@ public final class AudioDeviceInfo {
* @see AudioFormat
*
* Note: an empty array indicates that the device supports arbitrary encodings.
* For forward compatibility, applications should ignore entries it does not recognize.
*/
public @NonNull int[] getEncodings() {
return AudioFormat.filterPublicFormats(mPort.formats());
final int[] encodings = AudioFormat.filterPublicFormats(mPort.formats());
boolean hasFloat = false;
boolean hasExtendedIntegerPrecision = false;
for (int encoding : encodings) {
if (AudioFormat.isEncodingLinearPcm(encoding)) {
if (encoding == AudioFormat.ENCODING_PCM_FLOAT) {
hasFloat = true;
} else if (AudioFormat.getBytesPerSample(encoding) > 2) {
hasExtendedIntegerPrecision = true;
}
}
}
if (hasExtendedIntegerPrecision && !hasFloat) {
// R and earlier compatibility - add ENCODING_PCM_FLOAT to the end
// (replacing the zero pad). This ensures pre-S apps that look
// for ENCODING_PCM_FLOAT continue to see that encoding if the device supports
// extended precision integers.
int[] encodingsPlusFloat = Arrays.copyOf(encodings, encodings.length + 1);
encodingsPlusFloat[encodings.length] = AudioFormat.ENCODING_PCM_FLOAT;
return encodingsPlusFloat;
}
return encodings;
}
/**

View File

@@ -110,6 +110,24 @@ import java.util.Objects;
* <code>AudioTrack</code> as of API {@link android.os.Build.VERSION_CODES#LOLLIPOP}
* support <code>ENCODING_PCM_FLOAT</code>.
* </li>
* <li> {@link #ENCODING_PCM_24BIT_PACKED}: Introduced in
* API {@link android.os.Build.VERSION_CODES#S},
* this encoding specifies the audio sample is an
* extended precision 24 bit signed integer
* stored as a 3 Java bytes in a {@code ByteBuffer} or byte array in native endian
* (see {@link java.nio.ByteOrder#nativeOrder()}).
* Each sample has full range from [-8388608, 8388607],
* and can be interpreted as fixed point Q.23 data.
* </li>
* <li> {@link #ENCODING_PCM_32BIT}: Introduced in
* API {@link android.os.Build.VERSION_CODES#S},
* this encoding specifies the audio sample is an
* extended precision 32 bit signed integer
* stored as a 4 Java bytes in a {@code ByteBuffer} or byte array in native endian
* (see {@link java.nio.ByteOrder#nativeOrder()}).
* Each sample has full range from [-2147483648, 2147483647],
* and can be interpreted as fixed point Q.31 data.
* </li>
* </ul>
* <p>For compressed audio, the encoding specifies the method of compression,
* for example {@link #ENCODING_AC3} and {@link #ENCODING_DTS}. The compressed
@@ -285,6 +303,19 @@ public final class AudioFormat implements Parcelable {
/** Audio data format: OPUS compressed. */
public static final int ENCODING_OPUS = 20;
/** @hide
* We do not permit legacy short array reads or writes for encodings
* introduced after this threshold.
*/
public static final int ENCODING_LEGACY_SHORT_ARRAY_THRESHOLD = ENCODING_OPUS;
/** Audio data format: PCM 24 bit per sample packed as 3 bytes.
* Not guaranteed to be supported by devices, may be emulated if not supported. */
public static final int ENCODING_PCM_24BIT_PACKED = 21;
/** Audio data format: PCM 32 bit per sample.
* Not guaranteed to be supported by devices, may be emulated if not supported. */
public static final int ENCODING_PCM_32BIT = 22;
/** @hide */
public static String toLogFriendlyEncoding(int enc) {
switch(enc) {
@@ -328,6 +359,10 @@ public final class AudioFormat implements Parcelable {
return "ENCODING_DOLBY_MAT";
case ENCODING_OPUS:
return "ENCODING_OPUS";
case ENCODING_PCM_24BIT_PACKED:
return "ENCODING_PCM_24BIT_PACKED";
case ENCODING_PCM_32BIT:
return "ENCODING_PCM_32BIT";
default :
return "invalid encoding " + enc;
}
@@ -561,17 +596,20 @@ public final class AudioFormat implements Parcelable {
public static int getBytesPerSample(int audioFormat)
{
switch (audioFormat) {
case ENCODING_PCM_8BIT:
return 1;
case ENCODING_PCM_16BIT:
case ENCODING_IEC61937:
case ENCODING_DEFAULT:
return 2;
case ENCODING_PCM_FLOAT:
return 4;
case ENCODING_INVALID:
default:
throw new IllegalArgumentException("Bad audio format " + audioFormat);
case ENCODING_PCM_8BIT:
return 1;
case ENCODING_PCM_16BIT:
case ENCODING_IEC61937:
case ENCODING_DEFAULT:
return 2;
case ENCODING_PCM_24BIT_PACKED:
return 3;
case ENCODING_PCM_FLOAT:
case ENCODING_PCM_32BIT:
return 4;
case ENCODING_INVALID:
default:
throw new IllegalArgumentException("Bad audio format " + audioFormat);
}
}
@@ -598,6 +636,8 @@ public final class AudioFormat implements Parcelable {
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
case ENCODING_PCM_24BIT_PACKED:
case ENCODING_PCM_32BIT:
return true;
default:
return false;
@@ -627,6 +667,8 @@ public final class AudioFormat implements Parcelable {
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
case ENCODING_PCM_24BIT_PACKED:
case ENCODING_PCM_32BIT:
return true;
default:
return false;
@@ -641,6 +683,8 @@ public final class AudioFormat implements Parcelable {
case ENCODING_PCM_16BIT:
case ENCODING_PCM_8BIT:
case ENCODING_PCM_FLOAT:
case ENCODING_PCM_24BIT_PACKED:
case ENCODING_PCM_32BIT:
case ENCODING_DEFAULT:
return true;
case ENCODING_AC3:
@@ -674,6 +718,8 @@ public final class AudioFormat implements Parcelable {
case ENCODING_PCM_8BIT:
case ENCODING_PCM_FLOAT:
case ENCODING_IEC61937: // same size as stereo PCM
case ENCODING_PCM_24BIT_PACKED:
case ENCODING_PCM_32BIT:
case ENCODING_DEFAULT:
return true;
case ENCODING_AC3:
@@ -971,6 +1017,8 @@ public final class AudioFormat implements Parcelable {
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
case ENCODING_PCM_24BIT_PACKED:
case ENCODING_PCM_32BIT:
mEncoding = encoding;
break;
case ENCODING_INVALID:
@@ -1191,7 +1239,9 @@ public final class AudioFormat implements Parcelable {
ENCODING_AC4,
ENCODING_E_AC3_JOC,
ENCODING_DOLBY_MAT,
ENCODING_OPUS }
ENCODING_OPUS,
ENCODING_PCM_24BIT_PACKED,
ENCODING_PCM_32BIT }
)
@Retention(RetentionPolicy.SOURCE)
public @interface Encoding {}

View File

@@ -845,17 +845,21 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
//--------------
// audio format
switch (audioFormat) {
case AudioFormat.ENCODING_DEFAULT:
mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
break;
case AudioFormat.ENCODING_PCM_FLOAT:
case AudioFormat.ENCODING_PCM_16BIT:
case AudioFormat.ENCODING_PCM_8BIT:
mAudioFormat = audioFormat;
break;
default:
throw new IllegalArgumentException("Unsupported sample encoding " + audioFormat
+ ". Should be ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, or ENCODING_PCM_FLOAT.");
case AudioFormat.ENCODING_DEFAULT:
mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
break;
case AudioFormat.ENCODING_PCM_24BIT_PACKED:
case AudioFormat.ENCODING_PCM_32BIT:
case AudioFormat.ENCODING_PCM_FLOAT:
case AudioFormat.ENCODING_PCM_16BIT:
case AudioFormat.ENCODING_PCM_8BIT:
mAudioFormat = audioFormat;
break;
default:
throw new IllegalArgumentException("Unsupported sample encoding " + audioFormat
+ ". Should be ENCODING_PCM_8BIT, ENCODING_PCM_16BIT,"
+ " ENCODING_PCM_24BIT_PACKED, ENCODING_PCM_32BIT,"
+ " or ENCODING_PCM_FLOAT.");
}
}
@@ -1262,6 +1266,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
*/
public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@ReadMode int readMode) {
// Note: we allow reads of extended integers into a byte array.
if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
@@ -1334,7 +1339,10 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
*/
public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@ReadMode int readMode) {
if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
if (mState != STATE_INITIALIZED
|| mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT
// use ByteBuffer instead for later encodings
|| mAudioFormat > AudioFormat.ENCODING_LEGACY_SHORT_ARRAY_THRESHOLD) {
return ERROR_INVALID_OPERATION;
}

View File

@@ -2992,7 +2992,7 @@ public class AudioTrack extends PlayerBase
*/
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
@WriteMode int writeMode) {
// Note: we allow writes of extended integers and compressed formats from a byte array.
if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
@@ -3106,7 +3106,10 @@ public class AudioTrack extends PlayerBase
public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
@WriteMode int writeMode) {
if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
if (mState == STATE_UNINITIALIZED
|| mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT
// use ByteBuffer or byte[] instead for later encodings
|| mAudioFormat > AudioFormat.ENCODING_LEGACY_SHORT_ARRAY_THRESHOLD) {
return ERROR_INVALID_OPERATION;
}