Move Encoder quality API to VideoEncoderSettings.

Some other minor nits and adjustments to the API logic.

PiperOrigin-RevId: 459490431
This commit is contained in:
samrobinson 2022-07-07 12:54:02 +00:00 committed by Rohit Singh
parent cb87b7432f
commit 91f1777741
5 changed files with 88 additions and 88 deletions

View File

@ -56,7 +56,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
@Nullable private EncoderSelector encoderSelector; @Nullable private EncoderSelector encoderSelector;
@Nullable private VideoEncoderSettings requestedVideoEncoderSettings; @Nullable private VideoEncoderSettings requestedVideoEncoderSettings;
private boolean enableFallback; private boolean enableFallback;
private boolean automaticQualityAdjustment;
/** Creates a new {@link Builder}. */ /** Creates a new {@link Builder}. */
public Builder(Context context) { public Builder(Context context) {
@ -80,15 +79,9 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
* <p>Values in {@code requestedVideoEncoderSettings} may be ignored to improve encoding quality * <p>Values in {@code requestedVideoEncoderSettings} may be ignored to improve encoding quality
* and/or reduce failures. * and/or reduce failures.
* *
* <ul> * <p>{@link VideoEncoderSettings#profile} and {@link VideoEncoderSettings#level} are ignored
* <li>{@link VideoEncoderSettings#bitrate} is ignored if {@link * for {@link MimeTypes#VIDEO_H264}. Consider implementing {@link Codec.EncoderFactory} if such
* Builder#setAutomaticQualityAdjustment(boolean)} is enabled and {@link * adjustments are unwanted.
* VideoEncoderSettings#bitrateMode} is VBR.
* <li>{@link VideoEncoderSettings#profile} and {@link VideoEncoderSettings#level} are ignored
* for {@link MimeTypes#VIDEO_H264}
* </ul>
*
* <p>Consider implementing {@link Codec.EncoderFactory} if such adjustments are unwanted.
* *
* <p>{@code requestedVideoEncoderSettings} should be handled with care because there is no * <p>{@code requestedVideoEncoderSettings} should be handled with care because there is no
* fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile} * fallback support for it. For example, using incompatible {@link VideoEncoderSettings#profile}
@ -119,19 +112,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
return this; return this;
} }
/**
* Sets whether to use automatic quality adjustment.
*
* <p>With this enabled, encoders are configured to output high quality video.
*
* <p>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. */ /** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */
@SuppressWarnings("deprecation")
public DefaultEncoderFactory build() { public DefaultEncoderFactory build() {
if (encoderSelector == null) { if (encoderSelector == null) {
encoderSelector = EncoderSelector.DEFAULT; encoderSelector = EncoderSelector.DEFAULT;
@ -140,11 +122,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT; requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT;
} }
return new DefaultEncoderFactory( return new DefaultEncoderFactory(
context, context, encoderSelector, requestedVideoEncoderSettings, enableFallback);
encoderSelector,
requestedVideoEncoderSettings,
enableFallback,
automaticQualityAdjustment);
} }
} }
@ -152,7 +130,6 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
private final EncoderSelector videoEncoderSelector; private final EncoderSelector videoEncoderSelector;
private final VideoEncoderSettings requestedVideoEncoderSettings; private final VideoEncoderSettings requestedVideoEncoderSettings;
private final boolean enableFallback; private final boolean enableFallback;
private final boolean automaticQualityAdjustment;
/** /**
* @deprecated Use {@link Builder} instead. * @deprecated Use {@link Builder} instead.
@ -182,25 +159,10 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
EncoderSelector videoEncoderSelector, EncoderSelector videoEncoderSelector,
VideoEncoderSettings requestedVideoEncoderSettings, VideoEncoderSettings requestedVideoEncoderSettings,
boolean enableFallback) { 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.context = context;
this.videoEncoderSelector = videoEncoderSelector; this.videoEncoderSelector = videoEncoderSelector;
this.requestedVideoEncoderSettings = requestedVideoEncoderSettings; this.requestedVideoEncoderSettings = requestedVideoEncoderSettings;
this.enableFallback = enableFallback; this.enableFallback = enableFallback;
this.automaticQualityAdjustment = automaticQualityAdjustment;
} }
@Override @Override
@ -276,11 +238,11 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(format.frameRate)); mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, round(format.frameRate));
int bitrate; int bitrate;
if (automaticQualityAdjustment) {
if (supportedVideoEncoderSettings.enableHighQualityTargeting) {
bitrate = bitrate =
new DeviceMappedEncoderBitrateProvider() new DeviceMappedEncoderBitrateProvider()
.getBitrate( .getBitrate(encoderInfo.getName(), format.width, format.height, format.frameRate);
encoderInfo.getName(), format.width, format.height, round(format.frameRate));
} else if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) { } else if (supportedVideoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE) {
bitrate = supportedVideoEncoderSettings.bitrate; bitrate = supportedVideoEncoderSettings.bitrate;
} else { } else {
@ -367,46 +329,54 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
return null; return null;
} }
List<MediaCodecInfo> encodersForMimeType = encoderSelector.selectEncoderInfos(mimeType); ImmutableList<MediaCodecInfo> filteredEncoderInfos =
if (encodersForMimeType.isEmpty()) { encoderSelector.selectEncoderInfos(mimeType);
if (filteredEncoderInfos.isEmpty()) {
return null; return null;
} }
if (!enableFallback) { if (!enableFallback) {
return new VideoEncoderQueryResult( return new VideoEncoderQueryResult(
encodersForMimeType.get(0), requestedFormat, videoEncoderSettings); filteredEncoderInfos.get(0), requestedFormat, videoEncoderSettings);
} }
ImmutableList<MediaCodecInfo> filteredEncoders = filteredEncoderInfos =
filterEncodersByResolution( filterEncodersByResolution(
encodersForMimeType, mimeType, requestedFormat.width, requestedFormat.height); filteredEncoderInfos, mimeType, requestedFormat.width, requestedFormat.height);
if (filteredEncoders.isEmpty()) { if (filteredEncoderInfos.isEmpty()) {
return null; return null;
} }
// The supported resolution is the same for all remaining encoders. // The supported resolution is the same for all remaining encoders.
Size finalResolution = Size finalResolution =
checkNotNull( checkNotNull(
EncoderUtil.getSupportedResolution( EncoderUtil.getSupportedResolution(
filteredEncoders.get(0), mimeType, requestedFormat.width, requestedFormat.height)); filteredEncoderInfos.get(0),
mimeType,
requestedFormat.width,
requestedFormat.height));
int requestedBitrate = int requestedBitrate =
videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE videoEncoderSettings.bitrate != VideoEncoderSettings.NO_VALUE
? videoEncoderSettings.bitrate ? videoEncoderSettings.bitrate
: getSuggestedBitrate( : getSuggestedBitrate(
finalResolution.getWidth(), finalResolution.getHeight(), requestedFormat.frameRate); finalResolution.getWidth(), finalResolution.getHeight(), requestedFormat.frameRate);
filteredEncoders = filterEncodersByBitrate(filteredEncoders, mimeType, requestedBitrate);
if (filteredEncoders.isEmpty()) { filteredEncoderInfos =
filterEncodersByBitrate(filteredEncoderInfos, mimeType, requestedBitrate);
if (filteredEncoderInfos.isEmpty()) {
return null; return null;
} }
filteredEncoders = filteredEncoderInfos =
filterEncodersByBitrateMode(filteredEncoders, mimeType, videoEncoderSettings.bitrateMode); filterEncodersByBitrateMode(
if (filteredEncoders.isEmpty()) { filteredEncoderInfos, mimeType, videoEncoderSettings.bitrateMode);
if (filteredEncoderInfos.isEmpty()) {
return null; return null;
} }
MediaCodecInfo pickedEncoder = filteredEncoders.get(0); MediaCodecInfo pickedEncoderInfo = filteredEncoderInfos.get(0);
int closestSupportedBitrate = int closestSupportedBitrate =
EncoderUtil.getSupportedBitrateRange(pickedEncoder, mimeType).clamp(requestedBitrate); EncoderUtil.getSupportedBitrateRange(pickedEncoderInfo, mimeType).clamp(requestedBitrate);
VideoEncoderSettings.Builder supportedEncodingSettingBuilder = VideoEncoderSettings.Builder supportedEncodingSettingBuilder =
videoEncoderSettings.buildUpon().setBitrate(closestSupportedBitrate); videoEncoderSettings.buildUpon().setBitrate(closestSupportedBitrate);
@ -414,7 +384,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|| videoEncoderSettings.level == VideoEncoderSettings.NO_VALUE || videoEncoderSettings.level == VideoEncoderSettings.NO_VALUE
|| videoEncoderSettings.level || videoEncoderSettings.level
> EncoderUtil.findHighestSupportedEncodingLevel( > EncoderUtil.findHighestSupportedEncodingLevel(
pickedEncoder, mimeType, videoEncoderSettings.profile)) { pickedEncoderInfo, mimeType, videoEncoderSettings.profile)) {
supportedEncodingSettingBuilder.setEncodingProfileLevel( supportedEncodingSettingBuilder.setEncodingProfileLevel(
VideoEncoderSettings.NO_VALUE, VideoEncoderSettings.NO_VALUE); VideoEncoderSettings.NO_VALUE, VideoEncoderSettings.NO_VALUE);
} }
@ -428,7 +398,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
.setAverageBitrate(closestSupportedBitrate) .setAverageBitrate(closestSupportedBitrate)
.build(); .build();
return new VideoEncoderQueryResult( return new VideoEncoderQueryResult(
pickedEncoder, supportedEncoderFormat, supportedEncodingSettingBuilder.build()); pickedEncoderInfo, supportedEncoderFormat, supportedEncodingSettingBuilder.build());
} }
/** Returns a list of encoders that support the requested resolution most closely. */ /** Returns a list of encoders that support the requested resolution most closely. */
@ -642,7 +612,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
* </ul> * </ul>
*/ */
private static int getSuggestedBitrate(int width, int height, float frameRate) { private static int getSuggestedBitrate(int width, int height, float frameRate) {
// TODO(b/210591626) Implement bitrate estimation. // TODO(b/210591626) Refactor into a BitrateProvider.
// Assume medium motion factor. // Assume medium motion factor.
// 1080p60 -> 16.6Mbps, 720p30 -> 3.7Mbps. // 1080p60 -> 16.6Mbps, 720p30 -> 3.7Mbps.
return (int) (width * height * frameRate * 0.07 * 2); return (int) (width * height * frameRate * 0.07 * 2);

View File

@ -25,10 +25,14 @@ import androidx.media3.common.util.Util;
public class DeviceMappedEncoderBitrateProvider implements EncoderBitrateProvider { public class DeviceMappedEncoderBitrateProvider implements EncoderBitrateProvider {
@Override @Override
public int getBitrate(String encoderName, int width, int height, int frameRate) { public int getBitrate(String encoderName, int width, int height, float frameRate) {
double bitrateMultiplier = double bitrateMultiplier =
getBitrateMultiplierFromMapping( getBitrateMultiplierFromMapping(
encoderName, Util.SDK_INT, Build.MODEL, "" + width + "x" + height, frameRate); encoderName,
Util.SDK_INT,
Build.MODEL,
"" + width + "x" + height,
Math.round(frameRate));
return (int) (width * height * frameRate * bitrateMultiplier); return (int) (width * height * frameRate * bitrateMultiplier);
} }

View File

@ -26,11 +26,11 @@ public interface EncoderBitrateProvider {
/** /**
* Returns a recommended bitrate that the encoder should target. * Returns a recommended bitrate that the encoder should target.
* *
* @param encoderName The name of the encoder, see {@link MediaCodecInfo#getName()} * @param encoderName The name of the encoder, see {@link MediaCodecInfo#getName()}.
* @param width The output width of the video after encoding. * @param width The output width of the video after encoding.
* @param height The output height of the video after encoding. * @param height The output height of the video after encoding.
* @param frameRate The expected output frame rate of the video after encoding. * @param frameRate The expected output frame rate of the video after encoding.
* @return The bitrate the encoder should target. * @return The bitrate the encoder should target.
*/ */
int getBitrate(String encoderName, int width, int height, int frameRate); int getBitrate(String encoderName, int width, int height, float frameRate);
} }

View File

@ -20,7 +20,7 @@ import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.util.List; import com.google.common.collect.ImmutableList;
/** Selector of {@link MediaCodec} encoder instances. */ /** Selector of {@link MediaCodec} encoder instances. */
@UnstableApi @UnstableApi
@ -37,8 +37,8 @@ public interface EncoderSelector {
* order. * order.
* *
* @param mimeType The {@linkplain MimeTypes MIME type} for which an encoder is required. * @param mimeType The {@linkplain MimeTypes MIME type} for which an encoder is required.
* @return An unmodifiable list of {@linkplain MediaCodecInfo encoders} that support the {@code * @return An immutable list of {@linkplain MediaCodecInfo encoders} that support the {@code
* mimeType}. The list may be empty. * mimeType}. The list may be empty.
*/ */
List<MediaCodecInfo> selectEncoderInfos(String mimeType); ImmutableList<MediaCodecInfo> selectEncoderInfos(String mimeType);
} }

View File

@ -16,7 +16,10 @@
package androidx.media3.transformer; package androidx.media3.transformer;
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR;
import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.ElementType.TYPE_USE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -48,14 +51,11 @@ public final class VideoEncoderSettings {
public static final VideoEncoderSettings DEFAULT = new Builder().build(); public static final VideoEncoderSettings DEFAULT = new Builder().build();
/** /**
* The allowed values for {@code bitrateMode}, one of * The allowed values for {@code bitrateMode}.
* *
* <ul> * <ul>
* <li>Constant quality: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CQ}.
* <li>Variable bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}. * <li>Variable bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}.
* <li>Constant bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR}. * <li>Constant bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR}.
* <li>Constant bitrate with frame drops: {@link
* MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR_FD}, available from API31.
* </ul> * </ul>
*/ */
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
@ -63,10 +63,8 @@ public final class VideoEncoderSettings {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE) @Target(TYPE_USE)
@IntDef({ @IntDef({
MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ, BITRATE_MODE_VBR,
MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR, BITRATE_MODE_CBR,
MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR,
MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD
}) })
public @interface BitrateMode {} public @interface BitrateMode {}
@ -80,11 +78,12 @@ public final class VideoEncoderSettings {
private float iFrameIntervalSeconds; private float iFrameIntervalSeconds;
private int operatingRate; private int operatingRate;
private int priority; private int priority;
private boolean enableHighQualityTargeting;
/** Creates a new instance. */ /** Creates a new instance. */
public Builder() { public Builder() {
this.bitrate = NO_VALUE; this.bitrate = NO_VALUE;
this.bitrateMode = MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR; this.bitrateMode = BITRATE_MODE_VBR;
this.profile = NO_VALUE; this.profile = NO_VALUE;
this.level = NO_VALUE; this.level = NO_VALUE;
this.colorProfile = DEFAULT_COLOR_PROFILE; this.colorProfile = DEFAULT_COLOR_PROFILE;
@ -102,11 +101,14 @@ public final class VideoEncoderSettings {
this.iFrameIntervalSeconds = videoEncoderSettings.iFrameIntervalSeconds; this.iFrameIntervalSeconds = videoEncoderSettings.iFrameIntervalSeconds;
this.operatingRate = videoEncoderSettings.operatingRate; this.operatingRate = videoEncoderSettings.operatingRate;
this.priority = videoEncoderSettings.priority; this.priority = videoEncoderSettings.priority;
this.enableHighQualityTargeting = videoEncoderSettings.enableHighQualityTargeting;
} }
/** /**
* Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}. * Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}.
* *
* <p>Can not be set if enabling {@link #setEnableHighQualityTargeting(boolean)}.
*
* @param bitrate The {@link VideoEncoderSettings#bitrate}. * @param bitrate The {@link VideoEncoderSettings#bitrate}.
* @return This builder. * @return This builder.
*/ */
@ -119,16 +121,13 @@ public final class VideoEncoderSettings {
* Sets {@link VideoEncoderSettings#bitrateMode}. The default value is {@code * Sets {@link VideoEncoderSettings#bitrateMode}. The default value is {@code
* MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR}. * MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR}.
* *
* <p>Only {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR} and {@link * <p>Value must be in {@link BitrateMode}.
* MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR} are allowed.
* *
* @param bitrateMode The {@link VideoEncoderSettings#bitrateMode}. * @param bitrateMode The {@link VideoEncoderSettings#bitrateMode}.
* @return This builder. * @return This builder.
*/ */
public Builder setBitrateMode(@BitrateMode int bitrateMode) { public Builder setBitrateMode(@BitrateMode int bitrateMode) {
checkArgument( checkArgument(bitrateMode == BITRATE_MODE_VBR || bitrateMode == BITRATE_MODE_CBR);
bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR
|| bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
this.bitrateMode = bitrateMode; this.bitrateMode = bitrateMode;
return this; return this;
} }
@ -194,8 +193,28 @@ public final class VideoEncoderSettings {
return this; return this;
} }
/**
* Sets whether to enable automatic adjustment of the bitrate to target a high quality encoding.
*
* <p>Default value is {@code false}.
*
* <p>Requires {@link android.media.MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}.
*
* <p>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. */ /** Builds the instance. */
public VideoEncoderSettings build() { 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( return new VideoEncoderSettings(
bitrate, bitrate,
bitrateMode, bitrateMode,
@ -204,13 +223,14 @@ public final class VideoEncoderSettings {
colorProfile, colorProfile,
iFrameIntervalSeconds, iFrameIntervalSeconds,
operatingRate, operatingRate,
priority); priority,
enableHighQualityTargeting);
} }
} }
/** The encoding bitrate. */ /** The encoding bitrate. */
public final int bitrate; public final int bitrate;
/** One of {@linkplain BitrateMode the allowed modes}. */ /** One of {@linkplain BitrateMode}. */
public final @BitrateMode int bitrateMode; public final @BitrateMode int bitrateMode;
/** The encoding profile. */ /** The encoding profile. */
public final int profile; public final int profile;
@ -224,6 +244,8 @@ public final class VideoEncoderSettings {
public final int operatingRate; public final int operatingRate;
/** The encoder {@link MediaFormat#KEY_PRIORITY priority}. */ /** The encoder {@link MediaFormat#KEY_PRIORITY priority}. */
public final int 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( private VideoEncoderSettings(
int bitrate, int bitrate,
@ -233,7 +255,8 @@ public final class VideoEncoderSettings {
int colorProfile, int colorProfile,
float iFrameIntervalSeconds, float iFrameIntervalSeconds,
int operatingRate, int operatingRate,
int priority) { int priority,
boolean enableHighQualityTargeting) {
this.bitrate = bitrate; this.bitrate = bitrate;
this.bitrateMode = bitrateMode; this.bitrateMode = bitrateMode;
this.profile = profile; this.profile = profile;
@ -242,6 +265,7 @@ public final class VideoEncoderSettings {
this.iFrameIntervalSeconds = iFrameIntervalSeconds; this.iFrameIntervalSeconds = iFrameIntervalSeconds;
this.operatingRate = operatingRate; this.operatingRate = operatingRate;
this.priority = priority; this.priority = priority;
this.enableHighQualityTargeting = enableHighQualityTargeting;
} }
/** /**
@ -267,7 +291,8 @@ public final class VideoEncoderSettings {
&& colorProfile == that.colorProfile && colorProfile == that.colorProfile
&& iFrameIntervalSeconds == that.iFrameIntervalSeconds && iFrameIntervalSeconds == that.iFrameIntervalSeconds
&& operatingRate == that.operatingRate && operatingRate == that.operatingRate
&& priority == that.priority; && priority == that.priority
&& enableHighQualityTargeting == that.enableHighQualityTargeting;
} }
@Override @Override
@ -281,6 +306,7 @@ public final class VideoEncoderSettings {
result = 31 * result + Float.floatToIntBits(iFrameIntervalSeconds); result = 31 * result + Float.floatToIntBits(iFrameIntervalSeconds);
result = 31 * result + operatingRate; result = 31 * result + operatingRate;
result = 31 * result + priority; result = 31 * result + priority;
result = 31 * result + (enableHighQualityTargeting ? 1 : 0);
return result; return result;
} }
} }