diff options
author | 2024-12-18 23:14:41 -0800 | |
---|---|---|
committer | 2024-12-18 23:14:41 -0800 | |
commit | be726fb4c593f9efc3d4bba88ddbc28e5910df5f (patch) | |
tree | 485e2ae433113444f16d29eec09ca17870ac7b3e | |
parent | 7d6bf5dcef36508c6d0ebb3ab9188769f0d6e39f (diff) |
Revert "Java and JNI support for native AudioCapabilities."
Revert submission 3093180
Reason for revert: <Droidmonitor created revert due to b/385023849.Will be verified through ABTD for standard investigation.>
Reverted changes: /q/submissionid:3093180
Change-Id: Id2b767724f67aef3443b1abc50d542737cfbfb5d
-rw-r--r-- | media/java/android/media/MediaCodecInfo.java | 898 | ||||
-rw-r--r-- | media/jni/Android.bp | 2 | ||||
-rw-r--r-- | media/jni/android_media_CodecCapabilities.cpp | 117 | ||||
-rw-r--r-- | media/jni/android_media_MediaPlayer.cpp | 6 |
4 files changed, 364 insertions, 659 deletions
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index dbcba57520e6..782db358bf9f 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1104,11 +1104,10 @@ public final class MediaCodecInfo { // does not contain features and bitrate specific keys, keep only keys relevant for // a level check. Map<String, Object> levelCriticalFormatMap = new HashMap<>(map); - final Set<String> criticalKeys = isVideo() - ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS - : isAudio() - ? AudioCapabilities.AudioCapsLegacyImpl.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS - : null; + final Set<String> criticalKeys = + isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS : + isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS : + null; // critical keys will always contain KEY_MIME, but should also contain others to be // meaningful @@ -1411,597 +1410,434 @@ public final class MediaCodecInfo { */ public static final class AudioCapabilities { private static final String TAG = "AudioCapabilities"; + private CodecCapabilities mParent; + private Range<Integer> mBitrateRange; - /* package private */ interface AudioCapsIntf { - public Range<Integer> getBitrateRange(); - - public int[] getSupportedSampleRates(); - - public Range<Integer>[] getSupportedSampleRateRanges(); - - public int getMaxInputChannelCount(); - - public int getMinInputChannelCount(); - - public Range<Integer>[] getInputChannelCountRanges(); - - public boolean isSampleRateSupported(int sampleRate); + private int[] mSampleRates; + private Range<Integer>[] mSampleRateRanges; + private Range<Integer>[] mInputChannelRanges; - public void getDefaultFormat(MediaFormat format); + private static final int MAX_INPUT_CHANNEL_COUNT = 30; - public boolean supportsFormat(MediaFormat format); + /** + * Returns the range of supported bitrates in bits/second. + */ + public Range<Integer> getBitrateRange() { + return mBitrateRange; } - /* package private */ static final class AudioCapsLegacyImpl implements AudioCapsIntf { - private CodecCapabilities mParent; - private Range<Integer> mBitrateRange; - - private int[] mSampleRates; - private Range<Integer>[] mSampleRateRanges; - private Range<Integer>[] mInputChannelRanges; - - private static final int MAX_INPUT_CHANNEL_COUNT = 30; - - public Range<Integer> getBitrateRange() { - return mBitrateRange; - } - - public int[] getSupportedSampleRates() { - return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) - : null; - } + /** + * Returns the array of supported sample rates if the codec + * supports only discrete values. Otherwise, it returns + * {@code null}. The array is sorted in ascending order. + */ + public int[] getSupportedSampleRates() { + return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) : null; + } - public Range<Integer>[] getSupportedSampleRateRanges() { - return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length); - } + /** + * Returns the array of supported sample rate ranges. The + * array is sorted in ascending order, and the ranges are + * distinct. + */ + public Range<Integer>[] getSupportedSampleRateRanges() { + return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length); + } - public int getMaxInputChannelCount() { - int overall_max = 0; - for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { - int lmax = mInputChannelRanges[i].getUpper(); - if (lmax > overall_max) { - overall_max = lmax; - } + /** + * Returns the maximum number of input channels supported. + * + * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support + * for any number of input channels between 1 and this maximum value. + * + * As of {@link android.os.Build.VERSION_CODES#S}, + * the implied lower limit of 1 channel is no longer valid. + * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is + * superseded by {@link #getInputChannelCountRanges}, + * which returns an array of ranges of channels. + * The {@link #getMaxInputChannelCount} method will return the highest value + * in the ranges returned by {@link #getInputChannelCountRanges} + * + */ + @IntRange(from = 1, to = 255) + public int getMaxInputChannelCount() { + int overall_max = 0; + for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { + int lmax = mInputChannelRanges[i].getUpper(); + if (lmax > overall_max) { + overall_max = lmax; } - return overall_max; } + return overall_max; + } - public int getMinInputChannelCount() { - int overall_min = MAX_INPUT_CHANNEL_COUNT; - for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { - int lmin = mInputChannelRanges[i].getLower(); - if (lmin < overall_min) { - overall_min = lmin; - } + /** + * Returns the minimum number of input channels supported. + * This is often 1, but does vary for certain mime types. + * + * This returns the lowest channel count in the ranges returned by + * {@link #getInputChannelCountRanges}. + */ + @IntRange(from = 1, to = 255) + public int getMinInputChannelCount() { + int overall_min = MAX_INPUT_CHANNEL_COUNT; + for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { + int lmin = mInputChannelRanges[i].getLower(); + if (lmin < overall_min) { + overall_min = lmin; } - return overall_min; - } - - public Range<Integer>[] getInputChannelCountRanges() { - return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length); } + return overall_min; + } - /* no public constructor */ - private AudioCapsLegacyImpl() { } - - public static AudioCapsLegacyImpl create( - MediaFormat info, CodecCapabilities parent) { - if (GetFlag(() -> android.media.codec.Flags.nativeCapabilites())) { - Log.d(TAG, "Legacy implementation is called while native flag is on."); - } - - AudioCapsLegacyImpl caps = new AudioCapsLegacyImpl(); - caps.init(info, parent); - return caps; - } + /* + * Returns an array of ranges representing the number of input channels supported. + * The codec supports any number of input channels within this range. + * + * This supersedes the {@link #getMaxInputChannelCount} method. + * + * For many codecs, this will be a single range [1..N], for some N. + */ + @SuppressLint("ArrayReturn") + @NonNull + public Range<Integer>[] getInputChannelCountRanges() { + return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length); + } - private void init(MediaFormat info, CodecCapabilities parent) { - mParent = parent; - initWithPlatformLimits(); - applyLevelLimits(); - parseFromInfo(info); - } + /* no public constructor */ + private AudioCapabilities() { } - private void initWithPlatformLimits() { - mBitrateRange = Range.create(0, Integer.MAX_VALUE); - mInputChannelRanges = new Range[] {Range.create(1, MAX_INPUT_CHANNEL_COUNT)}; - // mBitrateRange = Range.create(1, 320000); - final int minSampleRate = SystemProperties. - getInt("ro.mediacodec.min_sample_rate", 7350); - final int maxSampleRate = SystemProperties. - getInt("ro.mediacodec.max_sample_rate", 192000); - mSampleRateRanges = new Range[] { Range.create(minSampleRate, maxSampleRate) }; - mSampleRates = null; - } + /** @hide */ + public static AudioCapabilities create( + MediaFormat info, CodecCapabilities parent) { + AudioCapabilities caps = new AudioCapabilities(); + caps.init(info, parent); + return caps; + } - private boolean supports(Integer sampleRate, Integer inputChannels) { - // channels and sample rates are checked orthogonally - if (inputChannels != null) { - int ix = Utils.binarySearchDistinctRanges( - mInputChannelRanges, inputChannels); - if (ix < 0) { - return false; - } - } - if (sampleRate != null) { - int ix = Utils.binarySearchDistinctRanges( - mSampleRateRanges, sampleRate); - if (ix < 0) { - return false; - } - } - return true; - } + private void init(MediaFormat info, CodecCapabilities parent) { + mParent = parent; + initWithPlatformLimits(); + applyLevelLimits(); + parseFromInfo(info); + } - public boolean isSampleRateSupported(int sampleRate) { - return supports(sampleRate, null); - } + private void initWithPlatformLimits() { + mBitrateRange = Range.create(0, Integer.MAX_VALUE); + mInputChannelRanges = new Range[] {Range.create(1, MAX_INPUT_CHANNEL_COUNT)}; + // mBitrateRange = Range.create(1, 320000); + final int minSampleRate = SystemProperties. + getInt("ro.mediacodec.min_sample_rate", 7350); + final int maxSampleRate = SystemProperties. + getInt("ro.mediacodec.max_sample_rate", 192000); + mSampleRateRanges = new Range[] { Range.create(minSampleRate, maxSampleRate) }; + mSampleRates = null; + } - /** modifies rates */ - private void limitSampleRates(int[] rates) { - Arrays.sort(rates); - ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>(); - for (int rate: rates) { - if (supports(rate, null /* channels */)) { - ranges.add(Range.create(rate, rate)); - } + private boolean supports(Integer sampleRate, Integer inputChannels) { + // channels and sample rates are checked orthogonally + if (inputChannels != null) { + int ix = Utils.binarySearchDistinctRanges( + mInputChannelRanges, inputChannels); + if (ix < 0) { + return false; } - mSampleRateRanges = ranges.toArray(new Range[ranges.size()]); - createDiscreteSampleRates(); } - - private void createDiscreteSampleRates() { - mSampleRates = new int[mSampleRateRanges.length]; - for (int i = 0; i < mSampleRateRanges.length; i++) { - mSampleRates[i] = mSampleRateRanges[i].getLower(); + if (sampleRate != null) { + int ix = Utils.binarySearchDistinctRanges( + mSampleRateRanges, sampleRate); + if (ix < 0) { + return false; } } + return true; + } - /** modifies rateRanges */ - private void limitSampleRates(Range<Integer>[] rateRanges) { - sortDistinctRanges(rateRanges); - mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges); + /** + * Query whether the sample rate is supported by the codec. + */ + public boolean isSampleRateSupported(int sampleRate) { + return supports(sampleRate, null); + } - // check if all values are discrete - for (Range<Integer> range: mSampleRateRanges) { - if (!range.getLower().equals(range.getUpper())) { - mSampleRates = null; - return; - } + /** modifies rates */ + private void limitSampleRates(int[] rates) { + Arrays.sort(rates); + ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>(); + for (int rate: rates) { + if (supports(rate, null /* channels */)) { + ranges.add(Range.create(rate, rate)); } - createDiscreteSampleRates(); } + mSampleRateRanges = ranges.toArray(new Range[ranges.size()]); + createDiscreteSampleRates(); + } - private void applyLevelLimits() { - int[] sampleRates = null; - Range<Integer> sampleRateRange = null, bitRates = null; - int maxChannels = MAX_INPUT_CHANNEL_COUNT; - CodecProfileLevel[] profileLevels = mParent.profileLevels; - String mime = mParent.getMimeType(); - - if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) { - sampleRates = new int[] { - 8000, 11025, 12000, - 16000, 22050, 24000, - 32000, 44100, 48000 }; - bitRates = Range.create(8000, 320000); - maxChannels = 2; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) { - sampleRates = new int[] { 8000 }; - bitRates = Range.create(4750, 12200); - maxChannels = 1; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) { - sampleRates = new int[] { 16000 }; - bitRates = Range.create(6600, 23850); - maxChannels = 1; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { - sampleRates = new int[] { - 7350, 8000, - 11025, 12000, 16000, - 22050, 24000, 32000, - 44100, 48000, 64000, - 88200, 96000 }; - bitRates = Range.create(8000, 510000); - maxChannels = 48; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) { - bitRates = Range.create(32000, 500000); - sampleRateRange = Range.create(8000, 192000); - maxChannels = 255; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) { - bitRates = Range.create(6000, 510000); - sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 }; - maxChannels = 255; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) { - sampleRateRange = Range.create(1, 192000); - bitRates = Range.create(1, 10000000); - maxChannels = AudioSystem.OUT_CHANNEL_COUNT_MAX; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { - sampleRateRange = Range.create(1, 655350); - // lossless codec, so bitrate is ignored - maxChannels = 255; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) - || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) { - sampleRates = new int[] { 8000 }; - bitRates = Range.create(64000, 64000); - // platform allows multiple channels for this format - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { - sampleRates = new int[] { 8000 }; - bitRates = Range.create(13000, 13000); - maxChannels = 1; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) { - maxChannels = 6; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) { - maxChannels = 16; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3_JOC)) { - sampleRates = new int[] { 48000 }; - bitRates = Range.create(32000, 6144000); - maxChannels = 16; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC4)) { - sampleRates = new int[] { 44100, 48000, 96000, 192000 }; - bitRates = Range.create(16000, 2688000); - maxChannels = 24; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS)) { - sampleRates = new int[] { 44100, 48000 }; - bitRates = Range.create(96000, 1524000); - maxChannels = 6; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD)) { - for (CodecProfileLevel profileLevel: profileLevels) { - switch (profileLevel.profile) { - case CodecProfileLevel.DTS_HDProfileLBR: - sampleRates = new int[]{ 22050, 24000, 44100, 48000 }; - bitRates = Range.create(32000, 768000); - break; - case CodecProfileLevel.DTS_HDProfileHRA: - case CodecProfileLevel.DTS_HDProfileMA: - sampleRates - = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; - bitRates = Range.create(96000, 24500000); - break; - default: - Log.w(TAG, "Unrecognized profile " - + profileLevel.profile + " for " + mime); - mParent.mError |= ERROR_UNRECOGNIZED; - sampleRates - = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; - bitRates = Range.create(96000, 24500000); - } - } - maxChannels = 8; - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) { - for (CodecProfileLevel profileLevel: profileLevels) { - switch (profileLevel.profile) { - case CodecProfileLevel.DTS_UHDProfileP2: - sampleRates = new int[]{ 48000 }; - bitRates = Range.create(96000, 768000); - maxChannels = 10; - break; - case CodecProfileLevel.DTS_UHDProfileP1: - sampleRates - = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; - bitRates = Range.create(96000, 24500000); - maxChannels = 32; - break; - default: - Log.w(TAG, "Unrecognized profile " - + profileLevel.profile + " for " + mime); - mParent.mError |= ERROR_UNRECOGNIZED; - sampleRates - = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; - bitRates = Range.create(96000, 24500000); - maxChannels = 32; - } - } - } else { - Log.w(TAG, "Unsupported mime " + mime); - mParent.mError |= ERROR_UNSUPPORTED; - } - - // restrict ranges - if (sampleRates != null) { - limitSampleRates(sampleRates); - } else if (sampleRateRange != null) { - limitSampleRates(new Range[] { sampleRateRange }); - } - - Range<Integer> channelRange = Range.create(1, maxChannels); - - applyLimits(new Range[] { channelRange }, bitRates); + private void createDiscreteSampleRates() { + mSampleRates = new int[mSampleRateRanges.length]; + for (int i = 0; i < mSampleRateRanges.length; i++) { + mSampleRates[i] = mSampleRateRanges[i].getLower(); } + } - private void applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates) { - - // clamp & make a local copy - Range<Integer>[] myInputChannels = new Range[inputChannels.length]; - for (int i = 0; i < inputChannels.length; i++) { - int lower = inputChannels[i].clamp(1); - int upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT); - myInputChannels[i] = Range.create(lower, upper); - } - - // sort, intersect with existing, & save channel list - sortDistinctRanges(myInputChannels); - Range<Integer>[] joinedChannelList = - intersectSortedDistinctRanges(myInputChannels, mInputChannelRanges); - mInputChannelRanges = joinedChannelList; + /** modifies rateRanges */ + private void limitSampleRates(Range<Integer>[] rateRanges) { + sortDistinctRanges(rateRanges); + mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges); - if (bitRates != null) { - mBitrateRange = mBitrateRange.intersect(bitRates); + // check if all values are discrete + for (Range<Integer> range: mSampleRateRanges) { + if (!range.getLower().equals(range.getUpper())) { + mSampleRates = null; + return; } } + createDiscreteSampleRates(); + } - private void parseFromInfo(MediaFormat info) { - int maxInputChannels = MAX_INPUT_CHANNEL_COUNT; - Range<Integer>[] channels = new Range[] { Range.create(1, maxInputChannels)}; - Range<Integer> bitRates = POSITIVE_INTEGERS; + private void applyLevelLimits() { + int[] sampleRates = null; + Range<Integer> sampleRateRange = null, bitRates = null; + int maxChannels = MAX_INPUT_CHANNEL_COUNT; + CodecProfileLevel[] profileLevels = mParent.profileLevels; + String mime = mParent.getMimeType(); - if (info.containsKey("sample-rate-ranges")) { - String[] rateStrings = info.getString("sample-rate-ranges").split(","); - Range<Integer>[] rateRanges = new Range[rateStrings.length]; - for (int i = 0; i < rateStrings.length; i++) { - rateRanges[i] = Utils.parseIntRange(rateStrings[i], null); + if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) { + sampleRates = new int[] { + 8000, 11025, 12000, + 16000, 22050, 24000, + 32000, 44100, 48000 }; + bitRates = Range.create(8000, 320000); + maxChannels = 2; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) { + sampleRates = new int[] { 8000 }; + bitRates = Range.create(4750, 12200); + maxChannels = 1; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) { + sampleRates = new int[] { 16000 }; + bitRates = Range.create(6600, 23850); + maxChannels = 1; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { + sampleRates = new int[] { + 7350, 8000, + 11025, 12000, 16000, + 22050, 24000, 32000, + 44100, 48000, 64000, + 88200, 96000 }; + bitRates = Range.create(8000, 510000); + maxChannels = 48; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) { + bitRates = Range.create(32000, 500000); + sampleRateRange = Range.create(8000, 192000); + maxChannels = 255; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) { + bitRates = Range.create(6000, 510000); + sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 }; + maxChannels = 255; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) { + sampleRateRange = Range.create(1, 192000); + bitRates = Range.create(1, 10000000); + maxChannels = AudioSystem.OUT_CHANNEL_COUNT_MAX; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { + sampleRateRange = Range.create(1, 655350); + // lossless codec, so bitrate is ignored + maxChannels = 255; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) + || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) { + sampleRates = new int[] { 8000 }; + bitRates = Range.create(64000, 64000); + // platform allows multiple channels for this format + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { + sampleRates = new int[] { 8000 }; + bitRates = Range.create(13000, 13000); + maxChannels = 1; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) { + maxChannels = 6; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) { + maxChannels = 16; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3_JOC)) { + sampleRates = new int[] { 48000 }; + bitRates = Range.create(32000, 6144000); + maxChannels = 16; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC4)) { + sampleRates = new int[] { 44100, 48000, 96000, 192000 }; + bitRates = Range.create(16000, 2688000); + maxChannels = 24; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS)) { + sampleRates = new int[] { 44100, 48000 }; + bitRates = Range.create(96000, 1524000); + maxChannels = 6; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD)) { + for (CodecProfileLevel profileLevel: profileLevels) { + switch (profileLevel.profile) { + case CodecProfileLevel.DTS_HDProfileLBR: + sampleRates = new int[]{ 22050, 24000, 44100, 48000 }; + bitRates = Range.create(32000, 768000); + break; + case CodecProfileLevel.DTS_HDProfileHRA: + case CodecProfileLevel.DTS_HDProfileMA: + sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; + bitRates = Range.create(96000, 24500000); + break; + default: + Log.w(TAG, "Unrecognized profile " + + profileLevel.profile + " for " + mime); + mParent.mError |= ERROR_UNRECOGNIZED; + sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; + bitRates = Range.create(96000, 24500000); } - limitSampleRates(rateRanges); } - - // we will prefer channel-ranges over max-channel-count - if (info.containsKey("channel-ranges")) { - String[] channelStrings = info.getString("channel-ranges").split(","); - Range<Integer>[] channelRanges = new Range[channelStrings.length]; - for (int i = 0; i < channelStrings.length; i++) { - channelRanges[i] = Utils.parseIntRange(channelStrings[i], null); - } - channels = channelRanges; - } else if (info.containsKey("channel-range")) { - Range<Integer> oneRange = Utils.parseIntRange(info.getString("channel-range"), - null); - channels = new Range[] { oneRange }; - } else if (info.containsKey("max-channel-count")) { - maxInputChannels = Utils.parseIntSafely( - info.getString("max-channel-count"), maxInputChannels); - if (maxInputChannels == 0) { - channels = new Range[] {Range.create(0, 0)}; - } else { - channels = new Range[] {Range.create(1, maxInputChannels)}; + maxChannels = 8; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) { + for (CodecProfileLevel profileLevel: profileLevels) { + switch (profileLevel.profile) { + case CodecProfileLevel.DTS_UHDProfileP2: + sampleRates = new int[]{ 48000 }; + bitRates = Range.create(96000, 768000); + maxChannels = 10; + break; + case CodecProfileLevel.DTS_UHDProfileP1: + sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; + bitRates = Range.create(96000, 24500000); + maxChannels = 32; + break; + default: + Log.w(TAG, "Unrecognized profile " + + profileLevel.profile + " for " + mime); + mParent.mError |= ERROR_UNRECOGNIZED; + sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; + bitRates = Range.create(96000, 24500000); + maxChannels = 32; } - } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { - maxInputChannels = 0; - channels = new Range[] {Range.create(0, 0)}; } - - if (info.containsKey("bitrate-range")) { - bitRates = bitRates.intersect( - Utils.parseIntRange(info.getString("bitrate-range"), bitRates)); - } - - applyLimits(channels, bitRates); + } else { + Log.w(TAG, "Unsupported mime " + mime); + mParent.mError |= ERROR_UNSUPPORTED; } - /** @hide */ - public void getDefaultFormat(MediaFormat format) { - // report settings that have only a single choice - if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) { - format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower()); - } - if (getMaxInputChannelCount() == 1) { - // mono-only format - format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); - } - if (mSampleRates != null && mSampleRates.length == 1) { - format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]); - } + // restrict ranges + if (sampleRates != null) { + limitSampleRates(sampleRates); + } else if (sampleRateRange != null) { + limitSampleRates(new Range[] { sampleRateRange }); } - /* package private */ - // must not contain KEY_PROFILE - static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( - // We don't set level-specific limits for audio codecs today. Key candidates - // would be sample rate, bit rate or channel count. - // MediaFormat.KEY_SAMPLE_RATE, - // MediaFormat.KEY_CHANNEL_COUNT, - // MediaFormat.KEY_BIT_RATE, - MediaFormat.KEY_MIME); - - /** @hide */ - public boolean supportsFormat(MediaFormat format) { - Map<String, Object> map = format.getMap(); - Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE); - Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT); - - if (!supports(sampleRate, channels)) { - return false; - } + Range<Integer> channelRange = Range.create(1, maxChannels); - if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { - return false; - } - - // nothing to do for: - // KEY_CHANNEL_MASK: codecs don't get this - // KEY_IS_ADTS: required feature for all AAC decoders - return true; - } + applyLimits(new Range[] { channelRange }, bitRates); } - /* package private */ static final class AudioCapsNativeImpl implements AudioCapsIntf { - private long mNativeContext; // accessed by native methods - - private Range<Integer> mBitrateRange; - private int[] mSampleRates; - private Range<Integer>[] mSampleRateRanges; - private Range<Integer>[] mInputChannelRanges; - - /** - * Constructor used by JNI. - * - * The Java AudioCapabilities object keeps these subobjects to avoid recontruction. - */ - /* package private */ AudioCapsNativeImpl(Range<Integer> bitrateRange, - int[] sampleRates, Range<Integer>[] sampleRateRanges, - Range<Integer>[] inputChannelRanges) { - mBitrateRange = bitrateRange; - mSampleRates = sampleRates; - mSampleRateRanges = sampleRateRanges; - mInputChannelRanges = inputChannelRanges; - } - - /* no public constructor */ - private AudioCapsNativeImpl() { } + private void applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates) { - public Range<Integer> getBitrateRange() { - return mBitrateRange; + // clamp & make a local copy + Range<Integer>[] myInputChannels = new Range[inputChannels.length]; + for (int i = 0; i < inputChannels.length; i++) { + int lower = inputChannels[i].clamp(1); + int upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT); + myInputChannels[i] = Range.create(lower, upper); } - public int[] getSupportedSampleRates() { - return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) - : null; - } + // sort, intersect with existing, & save channel list + sortDistinctRanges(myInputChannels); + Range<Integer>[] joinedChannelList = + intersectSortedDistinctRanges(myInputChannels, mInputChannelRanges); + mInputChannelRanges = joinedChannelList; - public Range<Integer>[] getSupportedSampleRateRanges() { - return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length); + if (bitRates != null) { + mBitrateRange = mBitrateRange.intersect(bitRates); } + } - public Range<Integer>[] getInputChannelCountRanges() { - return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length); + private void parseFromInfo(MediaFormat info) { + int maxInputChannels = MAX_INPUT_CHANNEL_COUNT; + Range<Integer>[] channels = new Range[] { Range.create(1, maxInputChannels)}; + Range<Integer> bitRates = POSITIVE_INTEGERS; + + if (info.containsKey("sample-rate-ranges")) { + String[] rateStrings = info.getString("sample-rate-ranges").split(","); + Range<Integer>[] rateRanges = new Range[rateStrings.length]; + for (int i = 0; i < rateStrings.length; i++) { + rateRanges[i] = Utils.parseIntRange(rateStrings[i], null); + } + limitSampleRates(rateRanges); } - public int getMaxInputChannelCount() { - return native_getMaxInputChannelCount(); + // we will prefer channel-ranges over max-channel-count + if (info.containsKey("channel-ranges")) { + String[] channelStrings = info.getString("channel-ranges").split(","); + Range<Integer>[] channelRanges = new Range[channelStrings.length]; + for (int i = 0; i < channelStrings.length; i++) { + channelRanges[i] = Utils.parseIntRange(channelStrings[i], null); + } + channels = channelRanges; + } else if (info.containsKey("channel-range")) { + Range<Integer> oneRange = Utils.parseIntRange(info.getString("channel-range"), + null); + channels = new Range[] { oneRange }; + } else if (info.containsKey("max-channel-count")) { + maxInputChannels = Utils.parseIntSafely( + info.getString("max-channel-count"), maxInputChannels); + if (maxInputChannels == 0) { + channels = new Range[] {Range.create(0, 0)}; + } else { + channels = new Range[] {Range.create(1, maxInputChannels)}; + } + } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { + maxInputChannels = 0; + channels = new Range[] {Range.create(0, 0)}; } - public int getMinInputChannelCount() { - return native_getMinInputChannelCount(); + if (info.containsKey("bitrate-range")) { + bitRates = bitRates.intersect( + Utils.parseIntRange(info.getString("bitrate-range"), bitRates)); } - public boolean isSampleRateSupported(int sampleRate) { - return native_isSampleRateSupported(sampleRate); - } + applyLimits(channels, bitRates); + } - // This API is for internal Java implementation only. Should not be called. - public void getDefaultFormat(MediaFormat format) { - throw new UnsupportedOperationException( - "Java Implementation should not call native implemenatation"); + /** @hide */ + public void getDefaultFormat(MediaFormat format) { + // report settings that have only a single choice + if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) { + format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower()); } - - // This API is for internal Java implementation only. Should not be called. - public boolean supportsFormat(MediaFormat format) { - throw new UnsupportedOperationException( - "Java Implementation should not call native implemenatation"); + if (getMaxInputChannelCount() == 1) { + // mono-only format + format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); } - - private native int native_getMaxInputChannelCount(); - private native int native_getMinInputChannelCount(); - private native boolean native_isSampleRateSupported(int sampleRate); - private static native void native_init(); - - static { - System.loadLibrary("media_jni"); - native_init(); + if (mSampleRates != null && mSampleRates.length == 1) { + format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]); } } - private AudioCapsIntf mImpl; + /* package private */ + // must not contain KEY_PROFILE + static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( + // We don't set level-specific limits for audio codecs today. Key candidates would + // be sample rate, bit rate or channel count. + // MediaFormat.KEY_SAMPLE_RATE, + // MediaFormat.KEY_CHANNEL_COUNT, + // MediaFormat.KEY_BIT_RATE, + MediaFormat.KEY_MIME); /** @hide */ - public static AudioCapabilities create( - MediaFormat info, CodecCapabilities parent) { - AudioCapsLegacyImpl impl = AudioCapsLegacyImpl.create(info, parent); - AudioCapabilities caps = new AudioCapabilities(impl); - return caps; - } - - /* package private */ AudioCapabilities(AudioCapsIntf impl) { - mImpl = impl; - } - - /* no public constructor */ - private AudioCapabilities() { } - - /** - * Returns the range of supported bitrates in bits/second. - */ - public Range<Integer> getBitrateRange() { - return mImpl.getBitrateRange(); - } - - /** - * Returns the array of supported sample rates if the codec - * supports only discrete values. Otherwise, it returns - * {@code null}. The array is sorted in ascending order. - */ - public int[] getSupportedSampleRates() { - return mImpl.getSupportedSampleRates(); - } - - /** - * Returns the array of supported sample rate ranges. The - * array is sorted in ascending order, and the ranges are - * distinct. - */ - public Range<Integer>[] getSupportedSampleRateRanges() { - return mImpl.getSupportedSampleRateRanges(); - } - - /* - * Returns an array of ranges representing the number of input channels supported. - * The codec supports any number of input channels within this range. - * - * This supersedes the {@link #getMaxInputChannelCount} method. - * - * For many codecs, this will be a single range [1..N], for some N. - */ - @SuppressLint("ArrayReturn") - @NonNull - public Range<Integer>[] getInputChannelCountRanges() { - return mImpl.getInputChannelCountRanges(); - } - - /** - * Returns the maximum number of input channels supported. - * - * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support - * for any number of input channels between 1 and this maximum value. - * - * As of {@link android.os.Build.VERSION_CODES#S}, - * the implied lower limit of 1 channel is no longer valid. - * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is - * superseded by {@link #getInputChannelCountRanges}, - * which returns an array of ranges of channels. - * The {@link #getMaxInputChannelCount} method will return the highest value - * in the ranges returned by {@link #getInputChannelCountRanges} - * - */ - @IntRange(from = 1, to = 255) - public int getMaxInputChannelCount() { - return mImpl.getMaxInputChannelCount(); - } - - /** - * Returns the minimum number of input channels supported. - * This is often 1, but does vary for certain mime types. - * - * This returns the lowest channel count in the ranges returned by - * {@link #getInputChannelCountRanges}. - */ - @IntRange(from = 1, to = 255) - public int getMinInputChannelCount() { - return mImpl.getMinInputChannelCount(); - } + public boolean supportsFormat(MediaFormat format) { + Map<String, Object> map = format.getMap(); + Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE); + Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT); - /** - * Query whether the sample rate is supported by the codec. - */ - public boolean isSampleRateSupported(int sampleRate) { - return mImpl.isSampleRateSupported(sampleRate); - } + if (!supports(sampleRate, channels)) { + return false; + } - /** @hide */ - public void getDefaultFormat(MediaFormat format) { - mImpl.getDefaultFormat(format); - } + if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { + return false; + } - /** @hide */ - public boolean supportsFormat(MediaFormat format) { - return mImpl.supportsFormat(format); + // nothing to do for: + // KEY_CHANNEL_MASK: codecs don't get this + // KEY_IS_ADTS: required feature for all AAC decoders + return true; } } @@ -4990,10 +4826,4 @@ public final class MediaCodecInfo { mName, mCanonicalName, mFlags, caps.toArray(new CodecCapabilities[caps.size()])); } - - /* package private */ class GenericHelper { - private static Range<Integer> constructIntegerRange(int lower, int upper) { - return Range.create(Integer.valueOf(lower), Integer.valueOf(upper)); - } - } } diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 126291ba4e3d..13dc748aa691 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -25,7 +25,6 @@ cc_library_shared { min_sdk_version: "", srcs: [ - "android_media_CodecCapabilities.cpp", "android_media_ImageWriter.cpp", "android_media_ImageReader.cpp", "android_media_JetPlayer.cpp", @@ -65,7 +64,6 @@ cc_library_shared { "libbinder", "libmedia", "libmedia_codeclist", - "libmedia_codeclist_capabilities", "libmedia_jni_utils", "libmedia_omx", "libmediametrics", diff --git a/media/jni/android_media_CodecCapabilities.cpp b/media/jni/android_media_CodecCapabilities.cpp deleted file mode 100644 index d5e574764181..000000000000 --- a/media/jni/android_media_CodecCapabilities.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2024, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "MediaCodec-JNI" - -#include "android_runtime/AndroidRuntime.h" -#include "jni.h" - -#include <media/AudioCapabilities.h> -#include <media/stagefright/foundation/ADebug.h> -#include <nativehelper/JNIHelp.h> - -namespace android { - -struct fields_t { - jfieldID audioCapsContext; -}; -static fields_t fields; - -// Getters - -static AudioCapabilities* getAudioCapabilities(JNIEnv *env, jobject thiz) { - AudioCapabilities* const p = (AudioCapabilities*)env->GetLongField( - thiz, fields.audioCapsContext); - return p; -} - -} // namespace android - -// ---------------------------------------------------------------------------- - -using namespace android; - -// AudioCapabilities - -static void android_media_AudioCapabilities_native_init(JNIEnv *env, jobject /* thiz */) { - jclass audioCapsImplClazz - = env->FindClass("android/media/MediaCodecInfo$AudioCapabilities$AudioCapsNativeImpl"); - if (audioCapsImplClazz == NULL) { - return; - } - - fields.audioCapsContext = env->GetFieldID(audioCapsImplClazz, "mNativeContext", "J"); - if (fields.audioCapsContext == NULL) { - return; - } - - env->DeleteLocalRef(audioCapsImplClazz); -} - -static jint android_media_AudioCapabilities_getMaxInputChannelCount(JNIEnv *env, jobject thiz) { - AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz); - if (audioCaps == nullptr) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); - return 0; - } - - int32_t maxInputChannelCount = audioCaps->getMaxInputChannelCount(); - return maxInputChannelCount; -} - -static jint android_media_AudioCapabilities_getMinInputChannelCount(JNIEnv *env, jobject thiz) { - AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz); - if (audioCaps == nullptr) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); - return 0; - } - - int32_t minInputChannelCount = audioCaps->getMinInputChannelCount(); - return minInputChannelCount; -} - -static jboolean android_media_AudioCapabilities_isSampleRateSupported(JNIEnv *env, jobject thiz, - int sampleRate) { - AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz); - if (audioCaps == nullptr) { - jniThrowException(env, "java/lang/IllegalStateException", NULL); - return 0; - } - - bool res = audioCaps->isSampleRateSupported(sampleRate); - return res; -} - -// ---------------------------------------------------------------------------- - -static const JNINativeMethod gAudioCapsMethods[] = { - {"native_init", "()V", (void *)android_media_AudioCapabilities_native_init}, - {"native_getMaxInputChannelCount", "()I", (void *)android_media_AudioCapabilities_getMaxInputChannelCount}, - {"native_getMinInputChannelCount", "()I", (void *)android_media_AudioCapabilities_getMinInputChannelCount}, - {"native_isSampleRateSupported", "(I)Z", (void *)android_media_AudioCapabilities_isSampleRateSupported} -}; - -int register_android_media_CodecCapabilities(JNIEnv *env) { - int result = AndroidRuntime::registerNativeMethods(env, - "android/media/MediaCodecInfo$AudioCapabilities$AudioCapsNativeImpl", - gAudioCapsMethods, NELEM(gAudioCapsMethods)); - if (result != JNI_OK) { - return result; - } - - return result; -}
\ No newline at end of file diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index fcba150f0db5..d05ee551c172 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -1465,7 +1465,6 @@ static int register_android_media_MediaPlayer(JNIEnv *env) extern int register_android_media_ImageReader(JNIEnv *env); extern int register_android_media_ImageWriter(JNIEnv *env); extern int register_android_media_JetPlayer(JNIEnv *env); -extern int register_android_media_CodecCapabilities(JNIEnv *env); extern int register_android_media_Crypto(JNIEnv *env); extern int register_android_media_Drm(JNIEnv *env); extern int register_android_media_Descrambler(JNIEnv *env); @@ -1580,11 +1579,6 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) goto bail; } - if (register_android_media_CodecCapabilities(env) < 0) { - ALOGE("ERROR: CodecCapabilities native registration failed"); - goto bail; - } - if (register_android_media_Crypto(env) < 0) { ALOGE("ERROR: MediaCodec native registration failed"); goto bail; |