Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* MP3: Ignore Xing data length if it's longer than the known stream length
([#3117](https://github.com/androidx/media/issues/3117)).
* Ignore `av1C` data with unsupported version.
* MP4: Add support for big-endian floating point PCM in `fpcm` boxes.
* Inspector:
* Audio:
* Update `MediaCodecAudioRenderer` to extract the spatial channelMask from
Expand All @@ -72,6 +73,7 @@
* Set correct `AudioProcessor.StreamMetadata.positionOffsetUs` to allow
time-based audio processing
([#418](https://github.com/androidx/media/issues/418)).
* Add support for big endian 32-bit and 64-bit floating point PCM.
* Video:
* Add support for skipping frames that are late during join rather than
dropping in DecoderVideoRenderer.
Expand Down
26 changes: 20 additions & 6 deletions libraries/common/src/main/java/androidx/media3/common/C.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,12 @@ private C() {}
* {@link #ENCODING_INVALID}, {@link #ENCODING_PCM_8BIT}, {@link #ENCODING_PCM_16BIT}, {@link
* #ENCODING_PCM_16BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_24BIT}, {@link
* #ENCODING_PCM_24BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_32BIT}, {@link
* #ENCODING_PCM_32BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_FLOAT}, {@link #ENCODING_PCM_DOUBLE},
* {@link #ENCODING_MP3}, {@link #ENCODING_AC3}, {@link #ENCODING_E_AC3}, {@link
* #ENCODING_E_AC3_JOC}, {@link #ENCODING_AC4}, {@link #ENCODING_DTS}, {@link #ENCODING_DTS_HD},
* {@link #ENCODING_DOLBY_TRUEHD}, {@link #ENCODING_OPUS} or {@link #ENCODING_DSD}.
* #ENCODING_PCM_32BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_FLOAT}, {@link
* #ENCODING_PCM_FLOAT_BIG_ENDIAN}, {@link #ENCODING_PCM_DOUBLE}, {@link
* #ENCODING_PCM_DOUBLE_BIG_ENDIAN}, {@link #ENCODING_MP3}, {@link #ENCODING_AC3}, {@link
* #ENCODING_E_AC3}, {@link #ENCODING_E_AC3_JOC}, {@link #ENCODING_AC4}, {@link #ENCODING_DTS},
* {@link #ENCODING_DTS_HD}, {@link #ENCODING_DOLBY_TRUEHD}, {@link #ENCODING_OPUS} or {@link
* #ENCODING_DSD}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
Expand All @@ -200,7 +202,9 @@ private C() {}
ENCODING_PCM_32BIT,
ENCODING_PCM_32BIT_BIG_ENDIAN,
ENCODING_PCM_FLOAT,
ENCODING_PCM_FLOAT_BIG_ENDIAN,
ENCODING_PCM_DOUBLE,
ENCODING_PCM_DOUBLE_BIG_ENDIAN,
ENCODING_MP3,
ENCODING_AAC_LC,
ENCODING_AAC_HE_V1,
Expand All @@ -226,7 +230,9 @@ private C() {}
* {@link #ENCODING_INVALID}, {@link #ENCODING_PCM_8BIT}, {@link #ENCODING_PCM_16BIT}, {@link
* #ENCODING_PCM_16BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_24BIT}, {@link
* #ENCODING_PCM_24BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_32BIT}, {@link
* #ENCODING_PCM_32BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_FLOAT}, {@link #ENCODING_PCM_DOUBLE}.
* #ENCODING_PCM_32BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_FLOAT}, {@link
* #ENCODING_PCM_FLOAT_BIG_ENDIAN}, {@link #ENCODING_PCM_DOUBLE}, {@link
* #ENCODING_PCM_DOUBLE_BIG_ENDIAN}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
Expand All @@ -242,7 +248,9 @@ private C() {}
ENCODING_PCM_32BIT,
ENCODING_PCM_32BIT_BIG_ENDIAN,
ENCODING_PCM_FLOAT,
ENCODING_PCM_DOUBLE
ENCODING_PCM_FLOAT_BIG_ENDIAN,
ENCODING_PCM_DOUBLE,
ENCODING_PCM_DOUBLE_BIG_ENDIAN
})
public @interface PcmEncoding {}

Expand Down Expand Up @@ -273,9 +281,15 @@ private C() {}
/** See {@link AudioFormat#ENCODING_PCM_FLOAT}. */
public static final int ENCODING_PCM_FLOAT = AudioFormat.ENCODING_PCM_FLOAT;

/** Like {@link #ENCODING_PCM_FLOAT} but with the bytes in big endian order. */
@UnstableApi public static final int ENCODING_PCM_FLOAT_BIG_ENDIAN = 0x71000000;

/** PCM encoding with double-precision floating point samples. */
@UnstableApi public static final int ENCODING_PCM_DOUBLE = 0x70000000;

/** Like {@link #ENCODING_PCM_DOUBLE} but with the bytes in big endian order. */
@UnstableApi public static final int ENCODING_PCM_DOUBLE_BIG_ENDIAN = 0x72000000;

/** See {@link AudioFormat#ENCODING_MP3}. */
public static final int ENCODING_MP3 = AudioFormat.ENCODING_MP3;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
* <li>{@link C#ENCODING_PCM_32BIT}
* <li>{@link C#ENCODING_PCM_32BIT_BIG_ENDIAN}
* <li>{@link C#ENCODING_PCM_FLOAT}
* <li>{@link C#ENCODING_PCM_FLOAT_BIG_ENDIAN}
* <li>{@link C#ENCODING_PCM_DOUBLE}
* <li>{@link C#ENCODING_PCM_DOUBLE_BIG_ENDIAN}
* </ul>
*/
@UnstableApi
Expand Down Expand Up @@ -74,9 +76,11 @@ public void queueInput(ByteBuffer inputBuffer) {
case C.ENCODING_PCM_32BIT:
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
resampledSize = size / 2;
break;
case C.ENCODING_PCM_DOUBLE:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
resampledSize = size / 4;
break;
case C.ENCODING_PCM_16BIT:
Expand Down Expand Up @@ -144,6 +148,22 @@ public void queueInput(ByteBuffer inputBuffer) {
buffer.put((byte) ((shortValue >> 8) & 0xFF));
}
break;
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
// 32 bit floating point -> 16 bit resampling. Floating point values are in the range
// [-1.0, 1.0], so need to be scaled by Short.MAX_VALUE.
for (int i = position; i < limit; i += 4) {
// Clamp to avoid integer overflow if the floating point values exceed their nominal range
// [Internal ref: b/161204847].
float floatValue =
Util.constrainValue(
Float.intBitsToFloat(Integer.reverseBytes(inputBuffer.getInt(i))),
/* min= */ -1,
/* max= */ 1);
short shortValue = (short) (floatValue * Short.MAX_VALUE);
buffer.put((byte) (shortValue & 0xFF));
buffer.put((byte) ((shortValue >> 8) & 0xFF));
}
break;
case C.ENCODING_PCM_DOUBLE:
// 64 bit floating point -> 16 bit resampling. Floating point values are in the range
// [-1.0, 1.0], so need to be scaled by Short.MAX_VALUE.
Expand All @@ -157,6 +177,22 @@ public void queueInput(ByteBuffer inputBuffer) {
buffer.put((byte) ((shortValue >> 8) & 0xFF));
}
break;
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
// 64 bit floating point -> 16 bit resampling. Floating point values are in the range
// [-1.0, 1.0], so need to be scaled by Short.MAX_VALUE.
for (int i = position; i < limit; i += 8) {
// Clamp to avoid integer overflow if the floating point values exceed their nominal range
// [Internal ref: b/161204847].
double doubleValue =
Util.constrainValue(
Double.longBitsToDouble(Long.reverseBytes(inputBuffer.getLong(i))),
/* min= */ -1,
/* max= */ 1);
short shortValue = (short) (doubleValue * Short.MAX_VALUE);
buffer.put((byte) (shortValue & 0xFF));
buffer.put((byte) ((shortValue >> 8) & 0xFF));
}
break;
case C.ENCODING_PCM_16BIT:
case C.ENCODING_INVALID:
case Format.NO_VALUE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ private static void maybeSetPcmEncoding(
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
case C.ENCODING_PCM_24BIT_BIG_ENDIAN:
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
case C.ENCODING_PCM_DOUBLE:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
default:
// No matching value. Do nothing.
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2448,11 +2448,28 @@ public static Format getPcmFormat(AudioProcessor.AudioFormat audioFormat) {
*/
@UnstableApi
public static @C.PcmEncoding int getFloatPcmEncoding(int bitDepth) {
return getFloatPcmEncoding(bitDepth, LITTLE_ENDIAN);
}

/**
* Converts a sample bit depth and byte order to a corresponding float PCM encoding constant.
*
* @param bitDepth The bit depth. Supported values are 32 and 64.
* @param byteOrder The byte order.
* @return The corresponding float PCM encoding. If the bit depth is unsupported then {@link
* C#ENCODING_INVALID} is returned.
*/
@UnstableApi
public static @C.PcmEncoding int getFloatPcmEncoding(int bitDepth, ByteOrder byteOrder) {
switch (bitDepth) {
case 32:
return C.ENCODING_PCM_FLOAT;
return byteOrder.equals(LITTLE_ENDIAN)
? C.ENCODING_PCM_FLOAT
: C.ENCODING_PCM_FLOAT_BIG_ENDIAN;
case 64:
return C.ENCODING_PCM_DOUBLE;
return byteOrder.equals(LITTLE_ENDIAN)
? C.ENCODING_PCM_DOUBLE
: C.ENCODING_PCM_DOUBLE_BIG_ENDIAN;
default:
return C.ENCODING_INVALID;
}
Expand All @@ -2474,7 +2491,9 @@ public static boolean isEncodingLinearPcm(@C.Encoding int encoding) {
|| encoding == C.ENCODING_PCM_32BIT
|| encoding == C.ENCODING_PCM_32BIT_BIG_ENDIAN
|| encoding == C.ENCODING_PCM_FLOAT
|| encoding == C.ENCODING_PCM_DOUBLE;
|| encoding == C.ENCODING_PCM_FLOAT_BIG_ENDIAN
|| encoding == C.ENCODING_PCM_DOUBLE
|| encoding == C.ENCODING_PCM_DOUBLE_BIG_ENDIAN;
}

/**
Expand All @@ -2490,7 +2509,9 @@ public static boolean isEncodingHighResolutionPcm(@C.PcmEncoding int encoding) {
|| encoding == C.ENCODING_PCM_32BIT
|| encoding == C.ENCODING_PCM_32BIT_BIG_ENDIAN
|| encoding == C.ENCODING_PCM_FLOAT
|| encoding == C.ENCODING_PCM_DOUBLE;
|| encoding == C.ENCODING_PCM_FLOAT_BIG_ENDIAN
|| encoding == C.ENCODING_PCM_DOUBLE
|| encoding == C.ENCODING_PCM_DOUBLE_BIG_ENDIAN;
}

/**
Expand Down Expand Up @@ -2689,8 +2710,10 @@ public static int getByteDepth(@C.PcmEncoding int pcmEncoding) {
case C.ENCODING_PCM_32BIT:
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
return 4;
case C.ENCODING_PCM_DOUBLE:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
return 8;
case C.ENCODING_INVALID:
case Format.NO_VALUE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ public static int getTypeForPcmEncoding(@C.PcmEncoding int pcmEncoding) {
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_DOUBLE:
return TYPE_FLOAT;
// TYPE_PCM is little endian so big endian formats don't match.
// TYPE_PCM/TYPE_FLOAT are little endian so big endian formats don't match.
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
case C.ENCODING_PCM_24BIT_BIG_ENDIAN:
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
case C.ENCODING_INVALID:
case Format.NO_VALUE:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,26 @@ private static ByteBuffer getTestSamplesForEncoding(int pcmEncoding) {
});
case C.ENCODING_PCM_FLOAT:
return createByteBuffer(new float[] {-1.0f, -0.5f, 0.0f, 0.5f, 1.0f});
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
return createByteBuffer(
new int[] {
Integer.reverseBytes(Float.floatToIntBits(-1.0f)),
Integer.reverseBytes(Float.floatToIntBits(-0.5f)),
Integer.reverseBytes(Float.floatToIntBits(0.0f)),
Integer.reverseBytes(Float.floatToIntBits(0.5f)),
Integer.reverseBytes(Float.floatToIntBits(1.0f))
});
case C.ENCODING_PCM_DOUBLE:
return createByteBuffer(new double[] {-1.0, -0.5, 0.0, 0.5, 1.0});
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
return createByteBuffer(
new long[] {
Long.reverseBytes(Double.doubleToLongBits(-1.0f)),
Long.reverseBytes(Double.doubleToLongBits(-0.5f)),
Long.reverseBytes(Double.doubleToLongBits(0.0f)),
Long.reverseBytes(Double.doubleToLongBits(0.5f)),
Long.reverseBytes(Double.doubleToLongBits(1.0f))
});
default:
throw new IllegalArgumentException();
}
Expand All @@ -158,7 +176,10 @@ private static float getToleranceForEncoding(int pcmEncoding) {
if (pcmEncoding == C.ENCODING_PCM_8BIT) {
return 256;
}
if (pcmEncoding == C.ENCODING_PCM_FLOAT || pcmEncoding == C.ENCODING_PCM_DOUBLE) {
if (pcmEncoding == C.ENCODING_PCM_FLOAT
|| pcmEncoding == C.ENCODING_PCM_DOUBLE
|| pcmEncoding == C.ENCODING_PCM_FLOAT_BIG_ENDIAN
|| pcmEncoding == C.ENCODING_PCM_DOUBLE_BIG_ENDIAN) {
return 1;
}
return 0;
Expand All @@ -175,7 +196,9 @@ protected ImmutableList<?> provideValues(Context context) {
value(C.ENCODING_PCM_32BIT).withName("ENCODING_PCM_32BIT"),
value(C.ENCODING_PCM_32BIT_BIG_ENDIAN).withName("ENCODING_PCM_32BIT_BIG_ENDIAN"),
value(C.ENCODING_PCM_FLOAT).withName("ENCODING_PCM_FLOAT"),
value(C.ENCODING_PCM_DOUBLE).withName("ENCODING_PCM_DOUBLE"));
value(C.ENCODING_PCM_FLOAT_BIG_ENDIAN).withName("ENCODING_PCM_FLOAT_BIG_ENDIAN"),
value(C.ENCODING_PCM_DOUBLE).withName("ENCODING_PCM_DOUBLE"),
value(C.ENCODING_PCM_DOUBLE_BIG_ENDIAN).withName("ENCODING_PCM_DOUBLE_BIG_ENDIAN"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ public void queueInput(ByteBuffer inputBuffer) {
buffer.putInt(inputBuffer.getInt(inputIndex));
break;
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
buffer.putFloat(inputBuffer.getFloat(inputIndex));
break;
case C.ENCODING_PCM_DOUBLE:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
buffer.putDouble(inputBuffer.getDouble(inputIndex));
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,9 @@ private FormatConfig getFormatConfig(Format format, int preferredBufferSize) {
case C.ENCODING_PCM_32BIT_BIG_ENDIAN:
case C.ENCODING_PCM_8BIT:
case C.ENCODING_PCM_FLOAT:
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
case C.ENCODING_PCM_DOUBLE:
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
case C.ENCODING_AAC_ER_BSAC:
case C.ENCODING_DSD:
case C.ENCODING_INVALID:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,35 @@ public static int readAs32BitIntPcm(ByteBuffer buffer, @C.Encoding int pcmEncodi
} else {
return (int) (floatValue * Integer.MAX_VALUE);
}
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
float floatBeValue =
Util.constrainValue(
Float.intBitsToFloat(Integer.reverseBytes(buffer.getInt())),
/* min= */ -1f,
/* max= */ 1f);
if (floatBeValue < 0) {
return (int) (-floatBeValue * Integer.MIN_VALUE);
} else {
return (int) (floatBeValue * Integer.MAX_VALUE);
}
case C.ENCODING_PCM_DOUBLE:
double doubleValue = Util.constrainValue(buffer.getDouble(), /* min= */ -1f, /* max= */ 1f);
if (doubleValue < 0) {
return (int) (-doubleValue * Integer.MIN_VALUE);
} else {
return (int) (doubleValue * Integer.MAX_VALUE);
}
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
double doubleBeValue =
Util.constrainValue(
Double.longBitsToDouble(Long.reverseBytes(buffer.getLong())),
/* min= */ -1f,
/* max= */ 1f);
if (doubleBeValue < 0) {
return (int) (-doubleBeValue * Integer.MIN_VALUE);
} else {
return (int) (doubleBeValue * Integer.MAX_VALUE);
}
default:
throw new IllegalStateException();
}
Expand Down Expand Up @@ -163,13 +185,31 @@ public static void write32BitIntPcm(
buffer.putFloat((float) pcm32bit / Integer.MAX_VALUE);
}
return;
case C.ENCODING_PCM_FLOAT_BIG_ENDIAN:
float floatValue;
if (pcm32bit < 0) {
floatValue = -((float) pcm32bit) / Integer.MIN_VALUE;
} else {
floatValue = (float) pcm32bit / Integer.MAX_VALUE;
}
buffer.putInt(Integer.reverseBytes(Float.floatToIntBits(floatValue)));
return;
case C.ENCODING_PCM_DOUBLE:
if (pcm32bit < 0) {
buffer.putDouble(-((double) pcm32bit) / Integer.MIN_VALUE);
} else {
buffer.putDouble((double) pcm32bit / Integer.MAX_VALUE);
}
return;
case C.ENCODING_PCM_DOUBLE_BIG_ENDIAN:
double doubleValue;
if (pcm32bit < 0) {
doubleValue = -((double) pcm32bit) / Integer.MIN_VALUE;
} else {
doubleValue = (double) pcm32bit / Integer.MAX_VALUE;
}
buffer.putLong(Long.reverseBytes(Double.doubleToLongBits(doubleValue)));
return;
default:
throw new IllegalStateException();
}
Expand Down
Loading