Merge pull request #2323 from DolbyLaboratories:dlb/ac4-profile/dev

PiperOrigin-RevId: 750171380
This commit is contained in:
Copybara-Service 2025-04-22 06:43:36 -07:00
commit 661effcddd
53 changed files with 170 additions and 4 deletions

View File

@ -62,6 +62,8 @@ public final class CodecSpecificDataUtil {
private static final String CODEC_ID_AV01 = "av01";
// MP4A AAC.
private static final String CODEC_ID_MP4A = "mp4a";
// AC-4
private static final String CODEC_ID_AC4 = "ac-4";
private static final Pattern PROFILE_PATTERN = Pattern.compile("^\\D?(\\d+)$");
@ -350,6 +352,8 @@ public final class CodecSpecificDataUtil {
return getAv1ProfileAndLevel(format.codecs, parts, format.colorInfo);
case CODEC_ID_MP4A:
return getAacCodecProfileAndLevel(format.codecs, parts);
case CODEC_ID_AC4:
return getAc4CodecProfileAndLevel(format.codecs, parts);
default:
return null;
}
@ -763,6 +767,41 @@ public final class CodecSpecificDataUtil {
return null;
}
@Nullable
private static Pair<Integer, Integer> getAc4CodecProfileAndLevel(String codec, String[] parts) {
if (parts.length != 4) {
Log.w(TAG, "Ignoring malformed AC-4 codec string: " + codec);
return null;
}
int bitstreamVersionInteger;
int presentationVersionInteger;
int levelInteger;
try {
bitstreamVersionInteger = Integer.parseInt(parts[1]);
presentationVersionInteger = Integer.parseInt(parts[2]);
levelInteger = Integer.parseInt(parts[3]);
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed AC-4 codec string: " + codec);
return null;
}
int profile =
ac4BitstreamAndPresentationVersionsToProfileConst(
bitstreamVersionInteger, presentationVersionInteger);
if (profile == -1) {
Log.w(
TAG,
"Unknown AC-4 profile: " + bitstreamVersionInteger + "." + presentationVersionInteger);
return null;
}
int level = ac4LevelNumberToConst(levelInteger);
if (level == -1) {
Log.w(TAG, "Unknown AC-4 level: " + levelInteger);
return null;
}
return new Pair<>(profile, level);
}
private static int avcProfileNumberToConst(int profileNumber) {
switch (profileNumber) {
case 66:
@ -1094,5 +1133,51 @@ public final class CodecSpecificDataUtil {
}
}
private static int ac4BitstreamAndPresentationVersionsToProfileConst(
int bitstreamVersionInteger, int presentationVersionInteger) {
int ac4Profile = -1;
switch (bitstreamVersionInteger) {
case 0:
if (presentationVersionInteger == 0) {
ac4Profile = MediaCodecInfo.CodecProfileLevel.AC4Profile00;
}
break;
case 1:
if (presentationVersionInteger == 0) {
ac4Profile = MediaCodecInfo.CodecProfileLevel.AC4Profile10;
} else if (presentationVersionInteger == 1) {
ac4Profile = MediaCodecInfo.CodecProfileLevel.AC4Profile11;
}
break;
case 2:
if (presentationVersionInteger == 1) {
ac4Profile = MediaCodecInfo.CodecProfileLevel.AC4Profile21;
} else if (presentationVersionInteger == 2) {
ac4Profile = MediaCodecInfo.CodecProfileLevel.AC4Profile22;
}
break;
default:
break;
}
return ac4Profile;
}
private static int ac4LevelNumberToConst(int levelNumber) {
switch (levelNumber) {
case 0:
return MediaCodecInfo.CodecProfileLevel.AC4Level0;
case 1:
return MediaCodecInfo.CodecProfileLevel.AC4Level1;
case 2:
return MediaCodecInfo.CodecProfileLevel.AC4Level2;
case 3:
return MediaCodecInfo.CodecProfileLevel.AC4Level3;
case 4:
return MediaCodecInfo.CodecProfileLevel.AC4Level4;
default:
return -1;
}
}
private CodecSpecificDataUtil() {}
}

View File

@ -33,6 +33,7 @@ import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Pair;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
@ -44,6 +45,7 @@ import androidx.media3.common.MimeTypes;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.util.CodecSpecificDataUtil;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.MediaFormatUtil;
import androidx.media3.common.util.UnstableApi;
@ -1020,11 +1022,18 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
mediaFormat.setFloat(MediaFormat.KEY_OPERATING_RATE, codecOperatingRate);
}
}
if (SDK_INT <= 28 && MimeTypes.AUDIO_AC4.equals(format.sampleMimeType)) {
if (MimeTypes.AUDIO_AC4.equals(format.sampleMimeType)) {
Pair<Integer, Integer> profileLevel = CodecSpecificDataUtil.getCodecProfileAndLevel(format);
if (profileLevel != null) {
MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_PROFILE, profileLevel.first);
MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_LEVEL, profileLevel.second);
}
if (SDK_INT <= 28) {
// On some older builds, the AC-4 decoder expects to receive samples formatted as raw frames
// not sync frames. Set a format key to override this.
mediaFormat.setInteger("ac4-is-sync", 1);
}
}
if (SDK_INT >= 24
&& audioSink.getFormatSupport(
Util.getPcmFormat(C.ENCODING_PCM_FLOAT, format.channelCount, format.sampleRate))

View File

@ -28,6 +28,7 @@ import androidx.media3.common.ParserException;
import androidx.media3.common.util.ParsableBitArray;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@ -240,6 +241,7 @@ public final class Ac4Util {
presentationConfig = dataBitArray.readBits(5); // presentation_config
isSingleSubstreamGroup = (presentationConfig == 0x1f);
}
ac4Presentation.version = presentationVersion;
boolean addEmdfSubstreams;
if (!(isSingleSubstream || isSingleSubstreamGroup) && presentationConfig == 6) {
@ -437,6 +439,9 @@ public final class Ac4Util {
"Can't determine channel count of presentation.");
}
String codecString =
createCodecsString(bitstreamVersion, ac4Presentation.version, ac4Presentation.level);
return new Format.Builder()
.setId(trackId)
.setSampleMimeType(MimeTypes.AUDIO_AC4)
@ -444,6 +449,7 @@ public final class Ac4Util {
.setSampleRate(sampleRate)
.setDrmInitData(drmInitData)
.setLanguage(language)
.setCodecs(codecString)
.build();
}
@ -631,6 +637,20 @@ public final class Ac4Util {
}
}
/**
* Create codec string based on bitstream version, presentation version and presentation level
*
* @param bitstreamVersion The bitstream version.
* @param presentationVersion The presentation version.
* @param mdcompat The mdcompat, i.e. presentation level.
* @return An AC-4 codec string built using the provided parameters.
*/
private static String createCodecsString(
int bitstreamVersion, int presentationVersion, int mdcompat) {
return Util.formatInvariant(
"ac-4.%02d.%02d.%02d", bitstreamVersion, presentationVersion, mdcompat);
}
/**
* Returns AC-4 format information given {@code data} containing a syncframe. The reading position
* of {@code data} will be modified.
@ -767,6 +787,7 @@ public final class Ac4Util {
public int numOfUmxObjects;
public boolean hasBackChannels;
public int topChannelPairs;
public int version;
public int level;
private Ac4Presentation() {
@ -775,6 +796,7 @@ public final class Ac4Util {
numOfUmxObjects = -1;
hasBackChannels = true;
topChannelPairs = 2;
version = 1;
level = 0;
}
}

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
maxInputSize = 622
channelCount = 2
sampleRate = 48000

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -15,6 +15,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
maxInputSize = 8158
channelCount = 21
sampleRate = 48000

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.01.04
channelCount = 21
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und

View File

@ -14,6 +14,7 @@ track 0:
id = 1
containerMimeType = audio/mp4
sampleMimeType = audio/ac4
codecs = ac-4.02.02.00
channelCount = 2
sampleRate = 48000
language = und