Skip to content

Commit

Permalink
Add configuration to support OPUS offload
Browse files Browse the repository at this point in the history
To support OPUS offload, we need to provide a few configuration values
that are currently not set due to the lack of devices supporting
OPUS offload.

PiperOrigin-RevId: 491613716
  • Loading branch information
tonihei authored and rohitjoins committed Nov 29, 2022
1 parent 532e0ff commit 4cf877b
Show file tree
Hide file tree
Showing 7 changed files with 646 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ private C() {}
* #ENCODING_PCM_16BIT_BIG_ENDIAN}, {@link #ENCODING_PCM_24BIT}, {@link #ENCODING_PCM_32BIT},
* {@link #ENCODING_PCM_FLOAT}, {@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} or {@link #ENCODING_DOLBY_TRUEHD}.
* {@link #ENCODING_DTS_HD}, {@link #ENCODING_DOLBY_TRUEHD} or {@link #ENCODING_OPUS}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
Expand All @@ -221,7 +221,8 @@ private C() {}
ENCODING_AC4,
ENCODING_DTS,
ENCODING_DTS_HD,
ENCODING_DOLBY_TRUEHD
ENCODING_DOLBY_TRUEHD,
ENCODING_OPUS,
})
public @interface Encoding {}

Expand Down Expand Up @@ -321,6 +322,10 @@ private C() {}
* @see AudioFormat#ENCODING_DOLBY_TRUEHD
*/
public static final int ENCODING_DOLBY_TRUEHD = AudioFormat.ENCODING_DOLBY_TRUEHD;
/**
* @see AudioFormat#ENCODING_OPUS
*/
public static final int ENCODING_OPUS = AudioFormat.ENCODING_OPUS;

/** Represents the behavior affecting whether spatialization will be used. */
@Documented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ public static String getMimeTypeFromMp4ObjectType(int objectType) {
return C.ENCODING_DTS_HD;
case MimeTypes.AUDIO_TRUEHD:
return C.ENCODING_DOLBY_TRUEHD;
case MimeTypes.AUDIO_OPUS:
return C.ENCODING_OPUS;
default:
return C.ENCODING_INVALID;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,8 @@ private static int getFramesPerEncodedSample(@C.Encoding int encoding, ByteBuffe
? 0
: (Ac3Util.parseTrueHdSyncframeAudioSampleCount(buffer, syncframeOffset)
* Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT);
case C.ENCODING_OPUS:
return OpusUtil.parsePacketAudioSampleCount(buffer);
case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
case C.ENCODING_PCM_24BIT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ protected static int getMaximumEncodedRateBytesPerSecond(@C.Encoding int encodin
return DtsUtil.DTS_HD_MAX_RATE_BYTES_PER_SECOND;
case C.ENCODING_DOLBY_TRUEHD:
return Ac3Util.TRUEHD_MAX_RATE_BYTES_PER_SECOND;
case C.ENCODING_OPUS:
return OpusUtil.MAX_BYTES_PER_SECOND;
case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
case C.ENCODING_PCM_24BIT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class OpusUtil {
/** Opus streams are always 48000 Hz. */
public static final int SAMPLE_RATE = 48_000;

/** Maximum achievable Opus bitrate. */
public static final int MAX_BYTES_PER_SECOND = 510 * 1000 / 8; // See RFC 6716. Section 2.1.1

private static final int DEFAULT_SEEK_PRE_ROLL_SAMPLES = 3840;
private static final int FULL_CODEC_INITIALIZATION_DATA_BUFFER_COUNT = 3;

Expand Down Expand Up @@ -61,6 +64,62 @@ public static List<byte[]> buildInitializationData(byte[] header) {
return initializationData;
}

/**
* Returns the number of audio samples in the given audio packet.
*
* <p>The buffer's position is not modified.
*
* @param buffer The audio packet.
* @return Returns the number of audio samples in the packet.
*/
public static int parsePacketAudioSampleCount(ByteBuffer buffer) {
long packetDurationUs =
getPacketDurationUs(buffer.get(0), buffer.limit() > 1 ? buffer.get(1) : 0);
return (int) (packetDurationUs * SAMPLE_RATE / C.MICROS_PER_SECOND);
}

/**
* Returns the duration of the given audio packet.
*
* @param buffer The audio packet.
* @return Returns the duration of the given audio packet, in microseconds.
*/
public static long getPacketDurationUs(byte[] buffer) {
return getPacketDurationUs(buffer[0], buffer.length > 1 ? buffer[1] : 0);
}

private static long getPacketDurationUs(byte packetByte0, byte packetByte1) {
// See RFC6716, Sections 3.1 and 3.2.
int toc = packetByte0 & 0xFF;
int frames;
switch (toc & 0x3) {
case 0:
frames = 1;
break;
case 1:
case 2:
frames = 2;
break;
default:
frames = packetByte1 & 0x3F;
break;
}

int config = toc >> 3;
int length = config & 0x3;
int frameDurationUs;
if (config >= 16) {
frameDurationUs = 2500 << length;
} else if (config >= 12) {
frameDurationUs = 10000 << (length & 0x1);
} else if (length == 3) {
frameDurationUs = 60000;
} else {
frameDurationUs = 10000 << length;
}
return (long) frames * frameDurationUs;
}

private static int getPreSkipSamples(byte[] header) {
return ((header[11] & 0xFF) << 8) | (header[10] & 0xFF);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected void reset(boolean headerData) {

@Override
protected long preparePayload(ParsableByteArray packet) {
return convertTimeToGranule(getPacketDurationUs(packet.getData()));
return convertTimeToGranule(OpusUtil.getPacketDurationUs(packet.getData()));
}

@Override
Expand Down Expand Up @@ -121,42 +121,6 @@ protected boolean readHeaders(ParsableByteArray packet, long position, SetupData
}
}

/**
* Returns the duration of the given audio packet.
*
* @param packet Contains audio data.
* @return Returns the duration of the given audio packet.
*/
private long getPacketDurationUs(byte[] packet) {
int toc = packet[0] & 0xFF;
int frames;
switch (toc & 0x3) {
case 0:
frames = 1;
break;
case 1:
case 2:
frames = 2;
break;
default:
frames = packet[1] & 0x3F;
break;
}

int config = toc >> 3;
int length = config & 0x3;
if (config >= 16) {
length = 2500 << length;
} else if (config >= 12) {
length = 10000 << (length & 0x1);
} else if (length == 3) {
length = 60000;
} else {
length = 10000 << length;
}
return (long) frames * length;
}

/**
* Returns true if the given {@link ParsableByteArray} starts with {@code expectedPrefix}. Does
* not change the {@link ParsableByteArray#getPosition() position} of {@code packet}.
Expand Down
Loading

0 comments on commit 4cf877b

Please sign in to comment.