Fix profile-level setting.
On some old devices, the encoding level needs to be set with the encoding profile, but not on newer devices. The profile/level override is applied by following https://developer.android.com/guide/topics/media/sharing-video PiperOrigin-RevId: 427008536
This commit is contained in:
parent
fab5dfa156
commit
31aa9d458d
@ -18,6 +18,7 @@ package androidx.media3.transformer;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.SDK_INT;
|
import static androidx.media3.common.util.Util.SDK_INT;
|
||||||
import static androidx.media3.transformer.CodecFactoryUtil.createCodec;
|
import static androidx.media3.transformer.CodecFactoryUtil.createCodec;
|
||||||
@ -151,30 +152,44 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
// Applying suggested profile/level settings from
|
// Applying suggested profile/level settings from
|
||||||
// https://developer.android.com/guide/topics/media/sharing-video#b-frames_and_encoding_profiles
|
// https://developer.android.com/guide/topics/media/sharing-video#b-frames_and_encoding_profiles
|
||||||
if (Util.SDK_INT >= 29) {
|
if (Util.SDK_INT >= 29) {
|
||||||
if (EncoderUtil.isProfileLevelSupported(
|
int supportedEncodingLevel =
|
||||||
encoderInfo,
|
EncoderUtil.findHighestSupportedEncodingLevel(
|
||||||
mimeType,
|
encoderInfo, mimeType, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
||||||
MediaCodecInfo.CodecProfileLevel.AVCProfileHigh,
|
if (supportedEncodingLevel != EncoderUtil.LEVEL_UNSET) {
|
||||||
EncoderUtil.LEVEL_UNSET)) {
|
|
||||||
// Use the highest supported profile and use B-frames.
|
// Use the highest supported profile and use B-frames.
|
||||||
mediaFormat.setInteger(
|
mediaFormat.setInteger(
|
||||||
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
||||||
|
mediaFormat.setInteger(MediaFormat.KEY_LEVEL, supportedEncodingLevel);
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, 1);
|
mediaFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, 1);
|
||||||
}
|
}
|
||||||
} else if (Util.SDK_INT >= 26) {
|
} else if (Util.SDK_INT >= 26) {
|
||||||
if (EncoderUtil.isProfileLevelSupported(
|
int supportedEncodingLevel =
|
||||||
encoderInfo,
|
EncoderUtil.findHighestSupportedEncodingLevel(
|
||||||
mimeType,
|
encoderInfo, mimeType, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
||||||
MediaCodecInfo.CodecProfileLevel.AVCProfileHigh,
|
if (supportedEncodingLevel != EncoderUtil.LEVEL_UNSET) {
|
||||||
EncoderUtil.LEVEL_UNSET)) {
|
// Use the highest-supported profile, but disable the generation of B-frames using
|
||||||
// Use the highest-supported profile, but disable the generation of B-frames. This
|
// MediaFormat.KEY_LATENCY. This accommodates some limitations in the MediaMuxer in these
|
||||||
// accommodates some limitations in the MediaMuxer in these system versions.
|
// system versions.
|
||||||
mediaFormat.setInteger(
|
mediaFormat.setInteger(
|
||||||
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh);
|
||||||
|
mediaFormat.setInteger(MediaFormat.KEY_LEVEL, supportedEncodingLevel);
|
||||||
|
// TODO(b/210593256): Set KEY_LATENCY to 2 to enable B-frame production after switching to
|
||||||
|
// in-app muxing.
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_LATENCY, 1);
|
mediaFormat.setInteger(MediaFormat.KEY_LATENCY, 1);
|
||||||
}
|
}
|
||||||
|
} else if (Util.SDK_INT >= 23) {
|
||||||
|
int supportedLevel =
|
||||||
|
EncoderUtil.findHighestSupportedEncodingLevel(
|
||||||
|
encoderInfo, mimeType, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
|
||||||
|
checkState(supportedLevel != EncoderUtil.LEVEL_UNSET);
|
||||||
|
// Use the baseline profile for safest results, as encoding in baseline is required per
|
||||||
|
// https://source.android.com/compatibility/5.0/android-5.0-cdd#5_2_video_encoding
|
||||||
|
mediaFormat.setInteger(
|
||||||
|
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
|
||||||
|
mediaFormat.setInteger(MediaFormat.KEY_LEVEL, supportedLevel);
|
||||||
} else {
|
} else {
|
||||||
// Use the baseline profile for safest results.
|
// Use the baseline profile for safest results, as encoding in baseline is required per
|
||||||
|
// https://source.android.com/compatibility/5.0/android-5.0-cdd#5_2_video_encoding
|
||||||
mediaFormat.setInteger(
|
mediaFormat.setInteger(
|
||||||
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
|
MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
|
||||||
}
|
}
|
||||||
@ -270,11 +285,9 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
@Nullable String codecs = null;
|
@Nullable String codecs = null;
|
||||||
if (profileLevel != null
|
if (profileLevel != null
|
||||||
&& requestedFormat.sampleMimeType.equals(mimeType)
|
&& requestedFormat.sampleMimeType.equals(mimeType)
|
||||||
&& EncoderUtil.isProfileLevelSupported(
|
&& profileLevel.second
|
||||||
pickedEncoder,
|
<= EncoderUtil.findHighestSupportedEncodingLevel(
|
||||||
mimeType,
|
pickedEncoder, mimeType, /* profile= */ profileLevel.first)) {
|
||||||
/* profile= */ profileLevel.first,
|
|
||||||
/* level= */ profileLevel.second)) {
|
|
||||||
codecs = requestedFormat.codecs;
|
codecs = requestedFormat.codecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,28 +113,26 @@ public final class EncoderUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the {@link MediaCodecInfo encoder} supports the given profile and level.
|
* Finds the highest supported encoding level given a profile.
|
||||||
*
|
*
|
||||||
* @param encoderInfo The {@link MediaCodecInfo encoderInfo}.
|
* @param encoderInfo The {@link MediaCodecInfo encoderInfo}.
|
||||||
* @param mimeType The {@link MimeTypes MIME type}.
|
* @param mimeType The {@link MimeTypes MIME type}.
|
||||||
* @param profile The encoding profile.
|
* @param profile The encoding profile.
|
||||||
* @param level The encoding level, specify {@link #LEVEL_UNSET} if checking whether the encoder
|
* @return The highest supported encoding level, as documented in {@link
|
||||||
* supports a specific profile.
|
* MediaCodecInfo.CodecProfileLevel}, or {@link #LEVEL_UNSET} if the profile is not supported.
|
||||||
* @return Whether the profile and level (if set) is supported by the encoder.
|
|
||||||
*/
|
*/
|
||||||
public static boolean isProfileLevelSupported(
|
public static int findHighestSupportedEncodingLevel(
|
||||||
MediaCodecInfo encoderInfo, String mimeType, int profile, int level) {
|
MediaCodecInfo encoderInfo, String mimeType, int profile) {
|
||||||
// TODO(b/214964116): Merge into MediaCodecUtil.
|
// TODO(b/214964116): Merge into MediaCodecUtil.
|
||||||
MediaCodecInfo.CodecProfileLevel[] profileLevels =
|
MediaCodecInfo.CodecProfileLevel[] profileLevels =
|
||||||
encoderInfo.getCapabilitiesForType(mimeType).profileLevels;
|
encoderInfo.getCapabilitiesForType(mimeType).profileLevels;
|
||||||
|
|
||||||
for (MediaCodecInfo.CodecProfileLevel profileLevel : profileLevels) {
|
for (MediaCodecInfo.CodecProfileLevel profileLevel : profileLevels) {
|
||||||
if (profileLevel.profile == profile
|
if (profileLevel.profile == profile) {
|
||||||
&& (level == LEVEL_UNSET || profileLevel.level == level)) {
|
return profileLevel.level;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return LEVEL_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user