am d995d23c: am 29f4a0b4: am b5caee71: Merge "media: minor fixes for MediaCodecInfo" into lmp-dev
* commit 'd995d23ccb968258a6270722af7bd5b98bec329a': media: minor fixes for MediaCodecInfo
This commit is contained in:
@@ -450,10 +450,16 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
|
||||
private void applyLevelLimits() {
|
||||
if (mParent.getMime().equalsIgnoreCase(
|
||||
MediaFormat.MIMETYPE_AUDIO_FLAC)) {
|
||||
String mime = mParent.getMime();
|
||||
if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
|
||||
mComplexityRange = Range.create(0, 8);
|
||||
mBitControl = (1 << BITRATE_MODE_CQ);
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
|
||||
|| mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
|
||||
|| mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
|
||||
|| mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
|
||||
|| mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
|
||||
mBitControl = (1 << BITRATE_MODE_CBR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,11 +520,12 @@ public final class MediaCodecInfo {
|
||||
|
||||
/** @hide */
|
||||
public void setDefaultFormat(MediaFormat format) {
|
||||
if (mQualityRange.getUpper() != mQualityRange.getLower()
|
||||
// don't list trivial quality/complexity as default for now
|
||||
if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
|
||||
&& mDefaultQuality != null) {
|
||||
format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
|
||||
}
|
||||
if (mComplexityRange.getUpper() != mComplexityRange.getLower()
|
||||
if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
|
||||
&& mDefaultComplexity != null) {
|
||||
format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
|
||||
}
|
||||
@@ -985,34 +992,34 @@ public final class MediaCodecInfo {
|
||||
|
||||
if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
|
||||
// codec supports profiles that we don't know.
|
||||
// Extend ranges clipped to platform limits.
|
||||
// Use supplied values clipped to platform limits
|
||||
if (widths != null) {
|
||||
mWidthRange = mWidthRange.extend(widths);
|
||||
mWidthRange = SIZE_RANGE.intersect(widths);
|
||||
}
|
||||
if (heights != null) {
|
||||
mHeightRange = mHeightRange.extend(heights);
|
||||
mHeightRange = SIZE_RANGE.intersect(heights);
|
||||
}
|
||||
if (counts != null) {
|
||||
mBlockCountRange = mBlockCountRange.extend(
|
||||
mBlockCountRange = POSITIVE_INTEGERS.intersect(
|
||||
Utils.factorRange(counts, mBlockWidth * mBlockHeight
|
||||
/ blockSize.getWidth() / blockSize.getHeight()));
|
||||
}
|
||||
if (blockRates != null) {
|
||||
mBlocksPerSecondRange = mBlocksPerSecondRange.extend(
|
||||
mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
|
||||
Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
|
||||
/ blockSize.getWidth() / blockSize.getHeight()));
|
||||
}
|
||||
if (blockRatios != null) {
|
||||
mBlockAspectRatioRange = mBlockAspectRatioRange.extend(
|
||||
mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
|
||||
Utils.scaleRange(blockRatios,
|
||||
mBlockHeight / blockSize.getHeight(),
|
||||
mBlockWidth / blockSize.getWidth()));
|
||||
}
|
||||
if (ratios != null) {
|
||||
mAspectRatioRange = mAspectRatioRange.extend(ratios);
|
||||
mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
|
||||
}
|
||||
if (frameRates != null) {
|
||||
mFrameRateRange = mFrameRateRange.extend(frameRates);
|
||||
mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
|
||||
}
|
||||
} else {
|
||||
// no unsupported profile/levels, so restrict values to known limits
|
||||
@@ -1235,7 +1242,6 @@ public final class MediaCodecInfo {
|
||||
Log.w(TAG, "Unrecognized level "
|
||||
+ profileLevel.level + " for " + mime);
|
||||
errors |= ERROR_UNRECOGNIZED;
|
||||
supported = false;
|
||||
}
|
||||
switch (profileLevel.profile) {
|
||||
case CodecProfileLevel.AVCProfileHigh:
|
||||
@@ -1245,7 +1251,7 @@ public final class MediaCodecInfo {
|
||||
case CodecProfileLevel.AVCProfileExtended:
|
||||
case CodecProfileLevel.AVCProfileHigh422:
|
||||
case CodecProfileLevel.AVCProfileHigh444:
|
||||
Log.w(TAG, "Unrecognized profile "
|
||||
Log.w(TAG, "Unsupported profile "
|
||||
+ profileLevel.profile + " for " + mime);
|
||||
errors |= ERROR_UNSUPPORTED;
|
||||
supported = false;
|
||||
@@ -1271,7 +1277,9 @@ public final class MediaCodecInfo {
|
||||
int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
|
||||
applyMacroBlockLimits(
|
||||
maxLengthInBlocks, maxLengthInBlocks,
|
||||
maxBlocks, maxBlocksPerSecond, 16, 16, 1, 1);
|
||||
maxBlocks, maxBlocksPerSecond,
|
||||
16 /* blockWidth */, 16 /* blockHeight */,
|
||||
1 /* widthAlignment */, 1 /* heightAlignment */);
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
|
||||
int maxWidth = 11, maxHeight = 9, maxRate = 15;
|
||||
maxBlocks = 99;
|
||||
@@ -1369,7 +1377,9 @@ public final class MediaCodecInfo {
|
||||
maxRate = Math.max(FR, maxRate);
|
||||
}
|
||||
applyMacroBlockLimits(maxWidth, maxHeight,
|
||||
maxBlocks, maxBlocksPerSecond, 16, 16, 1, 1);
|
||||
maxBlocks, maxBlocksPerSecond,
|
||||
16 /* blockWidth */, 16 /* blockHeight */,
|
||||
1 /* widthAlignment */, 1 /* heightAlignment */);
|
||||
mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
|
||||
int maxWidth = 11, maxHeight = 9, maxRate = 15;
|
||||
@@ -1432,7 +1442,9 @@ public final class MediaCodecInfo {
|
||||
maxRate = Math.max(FR, maxRate);
|
||||
}
|
||||
applyMacroBlockLimits(maxWidth, maxHeight,
|
||||
maxBlocks, maxBlocksPerSecond, 16, 16, 1, 1);
|
||||
maxBlocks, maxBlocksPerSecond,
|
||||
16 /* blockWidth */, 16 /* blockHeight */,
|
||||
1 /* widthAlignment */, 1 /* heightAlignment */);
|
||||
mFrameRateRange = Range.create(1, maxRate);
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
|
||||
mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
|
||||
@@ -1465,6 +1477,12 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
errors &= ~ERROR_NONE_SUPPORTED;
|
||||
}
|
||||
|
||||
final int blockSize =
|
||||
mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
|
||||
applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
|
||||
maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
|
||||
1 /* widthAlignment */, 1 /* heightAlignment */);
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
|
||||
maxBlocks = 36864;
|
||||
maxBlocksPerSecond = maxBlocks * 15;
|
||||
@@ -1493,17 +1511,17 @@ public final class MediaCodecInfo {
|
||||
FR = 30; FS = 2228224; BR = 12000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel4:
|
||||
FR = 30; FS = 2228224; BR = 30000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel41:
|
||||
FR = 60; FS = 2228224; BR = 20000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel41:
|
||||
FR = 60; FS = 2228224; BR = 20000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel41:
|
||||
FR = 60; FS = 2228224; BR = 50000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel5:
|
||||
FR = 30; FS = 8912896; BR = 25000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel5:
|
||||
FR = 30; FS = 8912896; BR = 25000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel5:
|
||||
FR = 30; FS = 8912896; BR = 100000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel51:
|
||||
FR = 60; FS = 8912896; BR = 40000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel51:
|
||||
FR = 60; FS = 8912896; BR = 40000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel51:
|
||||
FR = 60; FS = 8912896; BR = 160000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel52:
|
||||
FR = 120; FS = 8912896; BR = 60000; break;
|
||||
@@ -1513,13 +1531,13 @@ public final class MediaCodecInfo {
|
||||
FR = 30; FS = 35651584; BR = 60000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel6:
|
||||
FR = 30; FS = 35651584; BR = 240000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel61:
|
||||
FR = 60; FS = 35651584; BR = 120000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel61:
|
||||
FR = 60; FS = 35651584; BR = 120000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel61:
|
||||
FR = 60; FS = 35651584; BR = 480000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel62:
|
||||
FR = 120; FS = 35651584; BR = 240000; break;
|
||||
case CodecProfileLevel.HEVCMainTierLevel62:
|
||||
FR = 120; FS = 35651584; BR = 240000; break;
|
||||
case CodecProfileLevel.HEVCHighTierLevel62:
|
||||
FR = 120; FS = 35651584; BR = 800000; break;
|
||||
default:
|
||||
Log.w(TAG, "Unrecognized level "
|
||||
@@ -1557,9 +1575,13 @@ public final class MediaCodecInfo {
|
||||
|
||||
applyMacroBlockLimits(
|
||||
maxLengthInBlocks, maxLengthInBlocks,
|
||||
maxBlocks, maxBlocksPerSecond, 8, 8, 1, 1);
|
||||
maxBlocks, maxBlocksPerSecond,
|
||||
8 /* blockWidth */, 8 /* blockHeight */,
|
||||
1 /* widthAlignment */, 1 /* heightAlignment */);
|
||||
} else {
|
||||
Log.w(TAG, "Unsupported mime " + mime);
|
||||
// using minimal bitrate here. should be overriden by
|
||||
// info from media_codecs.xml
|
||||
maxBps = 64000;
|
||||
errors |= ERROR_UNSUPPORTED;
|
||||
}
|
||||
@@ -1628,21 +1650,26 @@ public final class MediaCodecInfo {
|
||||
|
||||
if (mMime.toLowerCase().startsWith("audio/")) {
|
||||
mAudioCaps = AudioCapabilities.create(info, this);
|
||||
mAudioCaps.setDefaultFormat(mDefaultFormat);
|
||||
} else if (mMime.toLowerCase().startsWith("video/")) {
|
||||
mVideoCaps = VideoCapabilities.create(info, this);
|
||||
}
|
||||
if (encoder) {
|
||||
mEncoderCaps = EncoderCapabilities.create(info, this);
|
||||
mEncoderCaps.setDefaultFormat(mDefaultFormat);
|
||||
}
|
||||
|
||||
for (Feature feat: getValidFeatures()) {
|
||||
Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
|
||||
String key = MediaFormat.KEY_FEATURE_ + feat.mName;
|
||||
Integer yesNo = (Integer)map.get(key);
|
||||
if (yesNo == null) {
|
||||
continue;
|
||||
} else if (yesNo > 0) {
|
||||
mFlagsRequired |= feat.mValue;
|
||||
mDefaultFormat.setInteger(key, 1);
|
||||
} else {
|
||||
mFlagsSupported |= feat.mValue;
|
||||
mDefaultFormat.setInteger(key, 1);
|
||||
}
|
||||
// TODO restrict features by mFlagsVerified once all codecs reliably verify them
|
||||
}
|
||||
@@ -1652,10 +1679,14 @@ public final class MediaCodecInfo {
|
||||
* A class that supports querying the audio capabilities of a codec.
|
||||
*/
|
||||
public static final class AudioCapabilities extends BaseCapabilities {
|
||||
private static final String TAG = "AudioCapabilities";
|
||||
|
||||
private int[] mSampleRates;
|
||||
private Range<Integer>[] mSampleRateRanges;
|
||||
private int mMaxInputChannelCount;
|
||||
|
||||
private static final int MAX_INPUT_CHANNEL_COUNT = 30;
|
||||
|
||||
/**
|
||||
* Returns the array of supported sample rates if the codec
|
||||
* supports only discrete values. Otherwise, it returns
|
||||
@@ -1702,7 +1733,7 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
|
||||
private void initWithPlatformLimits() {
|
||||
mMaxInputChannelCount = 30;
|
||||
mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT;
|
||||
// mBitrateRange = Range.create(1, 320000);
|
||||
mSampleRateRanges = new Range[] { Range.create(8000, 96000) };
|
||||
mSampleRates = null;
|
||||
@@ -1758,7 +1789,7 @@ public final class MediaCodecInfo {
|
||||
|
||||
// check if all values are discrete
|
||||
for (Range<Integer> range: mSampleRateRanges) {
|
||||
if (range.getLower() != range.getUpper()) {
|
||||
if (!range.getLower().equals(range.getUpper())) {
|
||||
mSampleRates = null;
|
||||
return;
|
||||
}
|
||||
@@ -1777,7 +1808,7 @@ public final class MediaCodecInfo {
|
||||
8000, 11025, 12000,
|
||||
16000, 22050, 24000,
|
||||
32000, 44100, 48000 };
|
||||
bitRates = Range.create(8192, 327680);
|
||||
bitRates = Range.create(8000, 320000);
|
||||
maxChannels = 2;
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
|
||||
sampleRates = new int[] { 8000 };
|
||||
@@ -1807,11 +1838,23 @@ public final class MediaCodecInfo {
|
||||
} else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
|
||||
sampleRateRange = Range.create(1, 96000);
|
||||
bitRates = Range.create(1, 10000000);
|
||||
maxChannels = 6;
|
||||
maxChannels = 8;
|
||||
} 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 {
|
||||
Log.w(TAG, "Unsupported mime " + mime);
|
||||
mParent.mError |= ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// restrict ranges
|
||||
@@ -1832,7 +1875,7 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
|
||||
private void parseFromInfo(MediaFormat info) {
|
||||
int maxInputChannels = 1;
|
||||
int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
|
||||
Range<Integer> bitRates = POSITIVE_INTEGERS;
|
||||
|
||||
if (info.containsKey("sample-rate-ranges")) {
|
||||
@@ -1844,7 +1887,8 @@ public final class MediaCodecInfo {
|
||||
limitSampleRates(rateRanges);
|
||||
}
|
||||
if (info.containsKey("max-channel-count")) {
|
||||
maxInputChannels = info.getInteger("max-channel-count");
|
||||
maxInputChannels = Utils.parseIntSafely(
|
||||
info.getString("max-channel-count"), maxInputChannels);
|
||||
}
|
||||
if (info.containsKey("bitrate-range")) {
|
||||
bitRates = bitRates.intersect(
|
||||
@@ -1853,6 +1897,21 @@ public final class MediaCodecInfo {
|
||||
applyLimits(maxInputChannels, bitRates);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setDefaultFormat(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 (mMaxInputChannelCount == 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]);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean supportsFormat(MediaFormat format) {
|
||||
Map<String, Object> map = format.getMap();
|
||||
|
||||
@@ -210,6 +210,19 @@ class Utils {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static int parseIntSafely(Object o, int fallback) {
|
||||
try {
|
||||
String s = (String)o;
|
||||
return Integer.parseInt(s);
|
||||
} catch (ClassCastException e) {
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (NullPointerException e) {
|
||||
return fallback;
|
||||
}
|
||||
Log.w(TAG, "could not parse integer '" + o + "'");
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static Range<Integer> parseIntRange(Object o, Range<Integer> fallback) {
|
||||
try {
|
||||
String s = (String)o;
|
||||
|
||||
Reference in New Issue
Block a user