Move Encoder quality API to VideoEncoderSettings.
Some other minor nits and adjustments to the API logic. PiperOrigin-RevId: 459490431
This commit is contained in:
parent
cb87b7432f
commit
91f1777741
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user