1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.android.exoplayer2.transformer; 18 19 import static com.google.android.exoplayer2.util.Assertions.checkArgument; 20 import static java.lang.annotation.ElementType.TYPE_USE; 21 22 import android.annotation.SuppressLint; 23 import android.media.MediaCodecInfo; 24 import android.media.MediaFormat; 25 import androidx.annotation.IntDef; 26 import androidx.annotation.Nullable; 27 import androidx.annotation.VisibleForTesting; 28 import com.google.android.exoplayer2.Format; 29 import java.lang.annotation.Documented; 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.lang.annotation.Target; 33 34 /** Represents the video encoder settings. */ 35 public final class VideoEncoderSettings { 36 37 /** A value for various fields to indicate that the field's value is unknown or not applicable. */ 38 public static final int NO_VALUE = Format.NO_VALUE; 39 /** The default encoding color profile. */ 40 public static final int DEFAULT_COLOR_PROFILE = 41 MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface; 42 /** The default I-frame interval in seconds. */ 43 public static final float DEFAULT_I_FRAME_INTERVAL_SECONDS = 1.0f; 44 45 /** A default {@link VideoEncoderSettings}. */ 46 public static final VideoEncoderSettings DEFAULT = new Builder().build(); 47 48 /** 49 * The allowed values for {@code bitrateMode}, one of 50 * 51 * <ul> 52 * <li>Constant quality: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CQ}. 53 * <li>Variable bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR}. 54 * <li>Constant bitrate: {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR}. 55 * <li>Constant bitrate with frame drops: {@link 56 * MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR_FD}, available from API31. 57 * </ul> 58 */ 59 @SuppressLint("InlinedApi") 60 @Documented 61 @Retention(RetentionPolicy.SOURCE) 62 @Target(TYPE_USE) 63 @IntDef({ 64 MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ, 65 MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR, 66 MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR, 67 MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD 68 }) 69 public @interface BitrateMode {} 70 71 /** Builds {@link VideoEncoderSettings} instances. */ 72 public static final class Builder { 73 private int bitrate; 74 private @BitrateMode int bitrateMode; 75 private int profile; 76 private int level; 77 private int colorProfile; 78 private float iFrameIntervalSeconds; 79 private int operatingRate; 80 private int priority; 81 82 /** Creates a new instance. */ Builder()83 public Builder() { 84 this.bitrate = NO_VALUE; 85 this.bitrateMode = MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR; 86 this.profile = NO_VALUE; 87 this.level = NO_VALUE; 88 this.colorProfile = DEFAULT_COLOR_PROFILE; 89 this.iFrameIntervalSeconds = DEFAULT_I_FRAME_INTERVAL_SECONDS; 90 this.operatingRate = NO_VALUE; 91 this.priority = NO_VALUE; 92 } 93 Builder(VideoEncoderSettings videoEncoderSettings)94 private Builder(VideoEncoderSettings videoEncoderSettings) { 95 this.bitrate = videoEncoderSettings.bitrate; 96 this.bitrateMode = videoEncoderSettings.bitrateMode; 97 this.profile = videoEncoderSettings.profile; 98 this.level = videoEncoderSettings.level; 99 this.colorProfile = videoEncoderSettings.colorProfile; 100 this.iFrameIntervalSeconds = videoEncoderSettings.iFrameIntervalSeconds; 101 this.operatingRate = videoEncoderSettings.operatingRate; 102 this.priority = videoEncoderSettings.priority; 103 } 104 105 /** 106 * Sets {@link VideoEncoderSettings#bitrate}. The default value is {@link #NO_VALUE}. 107 * 108 * @param bitrate The {@link VideoEncoderSettings#bitrate}. 109 * @return This builder. 110 */ setBitrate(int bitrate)111 public Builder setBitrate(int bitrate) { 112 this.bitrate = bitrate; 113 return this; 114 } 115 116 /** 117 * Sets {@link VideoEncoderSettings#bitrateMode}. The default value is {@code 118 * MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR}. 119 * 120 * <p>Only {@link MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_VBR} and {@link 121 * MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR} are allowed. 122 * 123 * @param bitrateMode The {@link VideoEncoderSettings#bitrateMode}. 124 * @return This builder. 125 */ setBitrateMode(@itrateMode int bitrateMode)126 public Builder setBitrateMode(@BitrateMode int bitrateMode) { 127 checkArgument( 128 bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR 129 || bitrateMode == MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR); 130 this.bitrateMode = bitrateMode; 131 return this; 132 } 133 134 /** 135 * Sets {@link VideoEncoderSettings#profile} and {@link VideoEncoderSettings#level}. The default 136 * values are both {@link #NO_VALUE}. 137 * 138 * <p>The value must be one of the values defined in {@link MediaCodecInfo.CodecProfileLevel}, 139 * or {@link #NO_VALUE}. 140 * 141 * <p>Profile and level settings will be ignored when using {@link DefaultEncoderFactory} and 142 * encoding to H264. 143 * 144 * @param encodingProfile The {@link VideoEncoderSettings#profile}. 145 * @param encodingLevel The {@link VideoEncoderSettings#level}. 146 * @return This builder. 147 */ setEncodingProfileLevel(int encodingProfile, int encodingLevel)148 public Builder setEncodingProfileLevel(int encodingProfile, int encodingLevel) { 149 this.profile = encodingProfile; 150 this.level = encodingLevel; 151 return this; 152 } 153 154 /** 155 * Sets {@link VideoEncoderSettings#colorProfile}. The default value is {@link 156 * #DEFAULT_COLOR_PROFILE}. 157 * 158 * <p>The value must be one of the {@code COLOR_*} constants defined in {@link 159 * MediaCodecInfo.CodecCapabilities}. 160 * 161 * @param colorProfile The {@link VideoEncoderSettings#colorProfile}. 162 * @return This builder. 163 */ setColorProfile(int colorProfile)164 public Builder setColorProfile(int colorProfile) { 165 this.colorProfile = colorProfile; 166 return this; 167 } 168 169 /** 170 * Sets {@link VideoEncoderSettings#iFrameIntervalSeconds}. The default value is {@link 171 * #DEFAULT_I_FRAME_INTERVAL_SECONDS}. 172 * 173 * @param iFrameIntervalSeconds The {@link VideoEncoderSettings#iFrameIntervalSeconds}. 174 * @return This builder. 175 */ setiFrameIntervalSeconds(float iFrameIntervalSeconds)176 public Builder setiFrameIntervalSeconds(float iFrameIntervalSeconds) { 177 this.iFrameIntervalSeconds = iFrameIntervalSeconds; 178 return this; 179 } 180 181 /** 182 * Sets encoding operating rate and priority. The default values are {@link #NO_VALUE}. 183 * 184 * @param operatingRate The {@link MediaFormat#KEY_OPERATING_RATE operating rate}. 185 * @param priority The {@link MediaFormat#KEY_PRIORITY priority}. 186 * @return This builder. 187 */ 188 @VisibleForTesting setEncoderPerformanceParameters(int operatingRate, int priority)189 public Builder setEncoderPerformanceParameters(int operatingRate, int priority) { 190 this.operatingRate = operatingRate; 191 this.priority = priority; 192 return this; 193 } 194 195 /** Builds the instance. */ build()196 public VideoEncoderSettings build() { 197 return new VideoEncoderSettings( 198 bitrate, 199 bitrateMode, 200 profile, 201 level, 202 colorProfile, 203 iFrameIntervalSeconds, 204 operatingRate, 205 priority); 206 } 207 } 208 209 /** The encoding bitrate. */ 210 public final int bitrate; 211 /** One of {@linkplain BitrateMode the allowed modes}. */ 212 public final @BitrateMode int bitrateMode; 213 /** The encoding profile. */ 214 public final int profile; 215 /** The encoding level. */ 216 public final int level; 217 /** The encoding color profile. */ 218 public final int colorProfile; 219 /** The encoding I-Frame interval in seconds. */ 220 public final float iFrameIntervalSeconds; 221 /** The encoder {@link MediaFormat#KEY_OPERATING_RATE operating rate}. */ 222 public final int operatingRate; 223 /** The encoder {@link MediaFormat#KEY_PRIORITY priority}. */ 224 public final int priority; 225 VideoEncoderSettings( int bitrate, int bitrateMode, int profile, int level, int colorProfile, float iFrameIntervalSeconds, int operatingRate, int priority)226 private VideoEncoderSettings( 227 int bitrate, 228 int bitrateMode, 229 int profile, 230 int level, 231 int colorProfile, 232 float iFrameIntervalSeconds, 233 int operatingRate, 234 int priority) { 235 this.bitrate = bitrate; 236 this.bitrateMode = bitrateMode; 237 this.profile = profile; 238 this.level = level; 239 this.colorProfile = colorProfile; 240 this.iFrameIntervalSeconds = iFrameIntervalSeconds; 241 this.operatingRate = operatingRate; 242 this.priority = priority; 243 } 244 245 /** 246 * Returns a {@link VideoEncoderSettings.Builder} initialized with the values of this instance. 247 */ buildUpon()248 public Builder buildUpon() { 249 return new Builder(this); 250 } 251 252 @Override equals(@ullable Object o)253 public boolean equals(@Nullable Object o) { 254 if (this == o) { 255 return true; 256 } 257 if (!(o instanceof VideoEncoderSettings)) { 258 return false; 259 } 260 VideoEncoderSettings that = (VideoEncoderSettings) o; 261 return bitrate == that.bitrate 262 && bitrateMode == that.bitrateMode 263 && profile == that.profile 264 && level == that.level 265 && colorProfile == that.colorProfile 266 && iFrameIntervalSeconds == that.iFrameIntervalSeconds 267 && operatingRate == that.operatingRate 268 && priority == that.priority; 269 } 270 271 @Override hashCode()272 public int hashCode() { 273 int result = 7; 274 result = 31 * result + bitrate; 275 result = 31 * result + bitrateMode; 276 result = 31 * result + profile; 277 result = 31 * result + level; 278 result = 31 * result + colorProfile; 279 result = 31 * result + Float.floatToIntBits(iFrameIntervalSeconds); 280 result = 31 * result + operatingRate; 281 result = 31 * result + priority; 282 return result; 283 } 284 } 285