Merge "media: check profile, level and bitrate for isFormatSupported" into nyc-dev
This commit is contained in:
@@ -567,6 +567,34 @@ public final class MediaCodecInfo {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
|
||||||
|
Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL);
|
||||||
|
|
||||||
|
if (profile != null) {
|
||||||
|
if (!supportsProfileLevel(profile, level)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we recognize this profile, check that this format is supported by the
|
||||||
|
// highest level supported by the codec for that profile. (Ignore specified
|
||||||
|
// level beyond the above profile/level check as level is only used as a
|
||||||
|
// guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
|
||||||
|
// even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
|
||||||
|
// 1080p format is not supported even if codec supports Main Profile Level High,
|
||||||
|
// as Simple Profile does not support 1080p.
|
||||||
|
CodecCapabilities levelCaps = null;
|
||||||
|
int maxLevel = 0;
|
||||||
|
for (CodecProfileLevel pl : profileLevels) {
|
||||||
|
if (pl.profile == profile && pl.level > maxLevel) {
|
||||||
|
maxLevel = pl.level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
|
||||||
|
if (levelCaps != null && !levelCaps.isFormatSupported(format)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
|
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -579,6 +607,57 @@ public final class MediaCodecInfo {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean supportsBitrate(
|
||||||
|
Range<Integer> bitrateRange, MediaFormat format) {
|
||||||
|
Map<String, Object> map = format.getMap();
|
||||||
|
|
||||||
|
// consider max bitrate over average bitrate for support
|
||||||
|
Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
|
||||||
|
Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
|
||||||
|
if (bitrate == null) {
|
||||||
|
bitrate = maxBitrate;
|
||||||
|
} else if (maxBitrate != null) {
|
||||||
|
bitrate = Math.max(bitrate, maxBitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitrate != null && bitrate > 0) {
|
||||||
|
return bitrateRange.contains(bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean supportsProfileLevel(int profile, Integer level) {
|
||||||
|
for (CodecProfileLevel pl: profileLevels) {
|
||||||
|
if (pl.profile != profile) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AAC does not use levels
|
||||||
|
if (level == null || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// H.263 levels are not completely ordered:
|
||||||
|
// Level45 support only implies Level10 support
|
||||||
|
if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
|
||||||
|
if (pl.level != level && pl.level == CodecProfileLevel.H263Level45
|
||||||
|
&& level > CodecProfileLevel.H263Level10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pl.level >= level) {
|
||||||
|
// if we recognize the listed profile/level, we must also recognize the
|
||||||
|
// profile/level arguments.
|
||||||
|
if (createFromProfileLevel(mMime, profile, pl.level) != null) {
|
||||||
|
return createFromProfileLevel(mMime, profile, level) != null;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// errors while reading profile levels - accessed from sister capabilities
|
// errors while reading profile levels - accessed from sister capabilities
|
||||||
int mError;
|
int mError;
|
||||||
|
|
||||||
@@ -1004,10 +1083,15 @@ public final class MediaCodecInfo {
|
|||||||
Map<String, Object> map = format.getMap();
|
Map<String, Object> map = format.getMap();
|
||||||
Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
|
Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
|
||||||
Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
|
Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
|
||||||
|
|
||||||
if (!supports(sampleRate, channels)) {
|
if (!supports(sampleRate, channels)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// nothing to do for:
|
// nothing to do for:
|
||||||
// KEY_CHANNEL_MASK: codecs don't get this
|
// KEY_CHANNEL_MASK: codecs don't get this
|
||||||
// KEY_IS_ADTS: required feature for all AAC decoders
|
// KEY_IS_ADTS: required feature for all AAC decoders
|
||||||
@@ -1310,8 +1394,7 @@ public final class MediaCodecInfo {
|
|||||||
return supports(width, height, null);
|
return supports(width, height, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean supports(
|
private boolean supports(Integer width, Integer height, Number rate) {
|
||||||
Integer width, Integer height, Number rate) {
|
|
||||||
boolean ok = true;
|
boolean ok = true;
|
||||||
|
|
||||||
if (ok && width != null) {
|
if (ok && width != null) {
|
||||||
@@ -1353,9 +1436,16 @@ public final class MediaCodecInfo {
|
|||||||
Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
|
Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
|
||||||
Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
|
Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
|
||||||
|
|
||||||
// we ignore color-format for now as it is not reliably reported by codec
|
if (!supports(width, height, rate)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return supports(width, height, rate);
|
if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we ignore color-format for now as it is not reliably reported by codec
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no public constructor */
|
/* no public constructor */
|
||||||
|
|||||||
@@ -185,11 +185,19 @@ public final class MediaFormat {
|
|||||||
public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
|
public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key describing the bitrate in bits/sec.
|
* A key describing the average bitrate in bits/sec.
|
||||||
* The associated value is an integer
|
* The associated value is an integer
|
||||||
*/
|
*/
|
||||||
public static final String KEY_BIT_RATE = "bitrate";
|
public static final String KEY_BIT_RATE = "bitrate";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key describing the max bitrate in bits/sec.
|
||||||
|
* This is usually over a one-second sliding window (e.g. over any window of one second).
|
||||||
|
* The associated value is an integer
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String KEY_MAX_BIT_RATE = "max-bitrate";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key describing the color format of the content in a video format.
|
* A key describing the color format of the content in a video format.
|
||||||
* Constants are declared in {@link android.media.MediaCodecInfo.CodecCapabilities}.
|
* Constants are declared in {@link android.media.MediaCodecInfo.CodecCapabilities}.
|
||||||
|
|||||||
Reference in New Issue
Block a user