diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java index d6ba06c05c..b609b1c023 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/DefaultEncoderFactory.java @@ -56,7 +56,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { @Nullable private EncoderSelector encoderSelector; @Nullable private VideoEncoderSettings requestedVideoEncoderSettings; private boolean enableFallback; - private boolean automaticQualityAdjustment; /** Creates a new {@link Builder}. */ public Builder(Context context) { @@ -80,15 +79,9 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { *
Values in {@code requestedVideoEncoderSettings} may be ignored to improve encoding quality * and/or reduce failures. * - *
Consider implementing {@link Codec.EncoderFactory} if such adjustments are unwanted. + *
{@link VideoEncoderSettings#profile} and {@link VideoEncoderSettings#level} are ignored + * for {@link MimeTypes#VIDEO_H264}. Consider implementing {@link Codec.EncoderFactory} if such + * adjustments are unwanted. * *
{@code requestedVideoEncoderSettings} should be handled with care because there is no * fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile} @@ -119,19 +112,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { return this; } - /** - * Sets whether to use automatic quality adjustment. - * - *
With this enabled, encoders are configured to output high quality video. - * - *
Default value is {@code false}.
- */
- public Builder setAutomaticQualityAdjustment(boolean automaticQualityAdjustment) {
- this.automaticQualityAdjustment = automaticQualityAdjustment;
- return this;
- }
-
/** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */
+ @SuppressWarnings("deprecation")
public DefaultEncoderFactory build() {
if (encoderSelector == null) {
encoderSelector = EncoderSelector.DEFAULT;
@@ -140,11 +122,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT;
}
return new DefaultEncoderFactory(
- context,
- encoderSelector,
- requestedVideoEncoderSettings,
- enableFallback,
- automaticQualityAdjustment);
+ context, encoderSelector, requestedVideoEncoderSettings, enableFallback);
}
}
@@ -152,7 +130,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
private final EncoderSelector videoEncoderSelector;
private final VideoEncoderSettings requestedVideoEncoderSettings;
private final boolean enableFallback;
- private final boolean automaticQualityAdjustment;
/**
* @deprecated Use {@link Builder} instead.
@@ -182,25 +159,10 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
EncoderSelector videoEncoderSelector,
VideoEncoderSettings requestedVideoEncoderSettings,
boolean enableFallback) {
- this(
- context,
- videoEncoderSelector,
- requestedVideoEncoderSettings,
- enableFallback,
- /* automaticQualityAdjustment= */ false);
- }
-
- private DefaultEncoderFactory(
- Context context,
- EncoderSelector videoEncoderSelector,
- VideoEncoderSettings requestedVideoEncoderSettings,
- boolean enableFallback,
- boolean automaticQualityAdjustment) {
this.context = context;
this.videoEncoderSelector = videoEncoderSelector;
this.requestedVideoEncoderSettings = requestedVideoEncoderSettings;
this.enableFallback = enableFallback;
- this.automaticQualityAdjustment = automaticQualityAdjustment;
}
@Override
@@ -276,11 +238,11 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(format.frameRate));
int bitrate;
- if (automaticQualityAdjustment) {
+
+ if (supportedVideoEncoderSettings.enableHighQualityTargeting) {
bitrate =
new DeviceMappedEncoderBitrateProvider()
- .getBitrate(
- encoderInfo.getName(), format.width, format.height, round(format.frameRate));
+ .getBitrate(encoderInfo.getName(), format.width, format.height, format.frameRate);
} else if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) {
bitrate = supportedVideoEncoderSettings.bitrate;
} else {
@@ -367,46 +329,54 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
return null;
}
- List Can not be set if enabling {@link #setEnableHighQualityTargeting(boolean)}.
+ *
* @param bitrate The {@link VideoEncoderSettings#bitrate}.
* @return This builder.
*/
@@ -119,16 +121,13 @@ public final class VideoEncoderSettings {
* Sets {@link VideoEncoderSettings#bitrateMode}. The default value is {@code
* MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR}.
*
- * Only {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR} and {@link
- * MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR} are allowed.
+ * Value must be in {@link BitrateMode}.
*
* @param bitrateMode The {@link VideoEncoderSettings#bitrateMode}.
* @return This builder.
*/
public Builder setBitrateMode(@BitrateMode int bitrateMode) {
- checkArgument(
- bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR
- || bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
+ checkArgument(bitrateMode == BITRATE_MODE_VBR || bitrateMode == BITRATE_MODE_CBR);
this.bitrateMode = bitrateMode;
return this;
}
@@ -194,8 +193,28 @@ public final class VideoEncoderSettings {
return this;
}
+ /**
+ * Sets whether to enable automatic adjustment of the bitrate to target a high quality encoding.
+ *
+ * Default value is {@code false}.
+ *
+ * Requires {@link android.media.MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}.
+ *
+ * Can not be enabled alongside setting a custom bitrate with {@link #setBitrate(int)}.
+ */
+ public Builder setEnableHighQualityTargeting(boolean enableHighQualityTargeting) {
+ this.enableHighQualityTargeting = enableHighQualityTargeting;
+ return this;
+ }
+
/** Builds the instance. */
public VideoEncoderSettings build() {
+ checkState(
+ !enableHighQualityTargeting || bitrate == NO_VALUE,
+ "Bitrate can not be set if enabling high quality targeting.");
+ checkState(
+ !enableHighQualityTargeting || bitrateMode == BITRATE_MODE_VBR,
+ "Bitrate mode must be VBR if enabling high quality targeting.");
return new VideoEncoderSettings(
bitrate,
bitrateMode,
@@ -204,13 +223,14 @@ public final class VideoEncoderSettings {
colorProfile,
iFrameIntervalSeconds,
operatingRate,
- priority);
+ priority,
+ enableHighQualityTargeting);
}
}
/** The encoding bitrate. */
public final int bitrate;
- /** One of {@linkplain BitrateMode the allowed modes}. */
+ /** One of {@linkplain BitrateMode}. */
public final @BitrateMode int bitrateMode;
/** The encoding profile. */
public final int profile;
@@ -224,6 +244,8 @@ public final class VideoEncoderSettings {
public final int operatingRate;
/** The encoder {@link MediaFormat#KEY_PRIORITY priority}. */
public final int priority;
+ /** Whether the encoder should automatically set the bitrate to target a high quality encoding. */
+ public final boolean enableHighQualityTargeting;
private VideoEncoderSettings(
int bitrate,
@@ -233,7 +255,8 @@ public final class VideoEncoderSettings {
int colorProfile,
float iFrameIntervalSeconds,
int operatingRate,
- int priority) {
+ int priority,
+ boolean enableHighQualityTargeting) {
this.bitrate = bitrate;
this.bitrateMode = bitrateMode;
this.profile = profile;
@@ -242,6 +265,7 @@ public final class VideoEncoderSettings {
this.iFrameIntervalSeconds = iFrameIntervalSeconds;
this.operatingRate = operatingRate;
this.priority = priority;
+ this.enableHighQualityTargeting = enableHighQualityTargeting;
}
/**
@@ -267,7 +291,8 @@ public final class VideoEncoderSettings {
&& colorProfile == that.colorProfile
&& iFrameIntervalSeconds == that.iFrameIntervalSeconds
&& operatingRate == that.operatingRate
- && priority == that.priority;
+ && priority == that.priority
+ && enableHighQualityTargeting == that.enableHighQualityTargeting;
}
@Override
@@ -281,6 +306,7 @@ public final class VideoEncoderSettings {
result = 31 * result + Float.floatToIntBits(iFrameIntervalSeconds);
result = 31 * result + operatingRate;
result = 31 * result + priority;
+ result = 31 * result + (enableHighQualityTargeting ? 1 : 0);
return result;
}
}
- *
*/
@SuppressLint("InlinedApi")
@@ -63,10 +63,8 @@ public final class VideoEncoderSettings {
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ,
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR,
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR,
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD
+ BITRATE_MODE_VBR,
+ BITRATE_MODE_CBR,
})
public @interface BitrateMode {}
@@ -80,11 +78,12 @@ public final class VideoEncoderSettings {
private float iFrameIntervalSeconds;
private int operatingRate;
private int priority;
+ private boolean enableHighQualityTargeting;
/** Creates a new instance. */
public Builder() {
this.bitrate = NO_VALUE;
- this.bitrateMode = MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
+ this.bitrateMode = BITRATE_MODE_VBR;
this.profile = NO_VALUE;
this.level = NO_VALUE;
this.colorProfile = DEFAULT_COLOR_PROFILE;
@@ -102,11 +101,14 @@ public final class VideoEncoderSettings {
this.iFrameIntervalSeconds = videoEncoderSettings.iFrameIntervalSeconds;
this.operatingRate = videoEncoderSettings.operatingRate;
this.priority = videoEncoderSettings.priority;
+ this.enableHighQualityTargeting = videoEncoderSettings.enableHighQualityTargeting;
}
/**
* Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}.
*
+ *