1 /* 2 * Copyright (C) 2021 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 android.media; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 22 import java.lang.annotation.Retention; 23 import java.lang.annotation.RetentionPolicy; 24 import java.util.Arrays; 25 import java.util.Collections; 26 import java.util.List; 27 28 /** 29 * Describes a set of encoding profiles for a given media (audio and/or video) profile. 30 * These settings are read-only. 31 * 32 * <p>Currently, this is used to describe camera recording profile with more detail than {@link 33 * CamcorderProfile}, by providing encoding parameters for more than just the default audio 34 * and/or video codec. 35 * 36 * <p>The compressed output from a camera recording session contains two tracks: 37 * one for audio and one for video. 38 * <p>In the future audio-only recording profiles may be defined. 39 * 40 * <p>Each media profile specifies a set of audio and a set of video specific settings. 41 * <ul> 42 * <li> The file output format 43 * <li> Default file duration 44 * <p>Video-specific settings are: 45 * <li> Video codec format 46 * <li> Video bit rate in bits per second 47 * <li> Video frame rate in frames per second 48 * <li> Video frame width and height, 49 * <li> Video encoder profile. 50 * <p>Audio-specific settings are: 51 * <li> Audio codec format 52 * <li> Audio bit rate in bits per second, 53 * <li> Audio sample rate 54 * <li> Number of audio channels for recording. 55 * </ul> 56 */ 57 public final class EncoderProfiles 58 { 59 /** 60 * Default recording duration in seconds before the session is terminated. 61 * This is useful for applications like MMS that have a limited file size requirement. 62 * This could be 0 if there is no default recording duration. 63 */ getDefaultDurationSeconds()64 public int getDefaultDurationSeconds() { 65 return durationSecs; 66 } 67 68 /** 69 * Recommended output file format 70 * @see android.media.MediaRecorder.OutputFormat 71 */ getRecommendedFileFormat()72 public @MediaRecorder.OutputFormatValues int getRecommendedFileFormat() { 73 return fileFormat; 74 } 75 76 /** 77 * Configuration for a video encoder. 78 */ 79 public final static class VideoProfile { 80 /** 81 * The video encoder being used for the video track 82 * @see android.media.MediaRecorder.VideoEncoder 83 */ getCodec()84 public @MediaRecorder.VideoEncoderValues int getCodec() { 85 return codec; 86 } 87 88 /** 89 * The media type of the video encoder being used for the video track 90 * @see android.media.MediaFormat#KEY_MIME 91 */ getMediaType()92 public @NonNull String getMediaType() { 93 if (codec == MediaRecorder.VideoEncoder.H263) { 94 return MediaFormat.MIMETYPE_VIDEO_H263; 95 } else if (codec == MediaRecorder.VideoEncoder.H264) { 96 return MediaFormat.MIMETYPE_VIDEO_AVC; 97 } else if (codec == MediaRecorder.VideoEncoder.MPEG_4_SP) { 98 return MediaFormat.MIMETYPE_VIDEO_MPEG4; 99 } else if (codec == MediaRecorder.VideoEncoder.VP8) { 100 return MediaFormat.MIMETYPE_VIDEO_VP8; 101 } else if (codec == MediaRecorder.VideoEncoder.HEVC) { 102 return MediaFormat.MIMETYPE_VIDEO_HEVC; 103 } else if (codec == MediaRecorder.VideoEncoder.VP9) { 104 return MediaFormat.MIMETYPE_VIDEO_VP9; 105 } else if (codec == MediaRecorder.VideoEncoder.DOLBY_VISION) { 106 return MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION; 107 } else if (codec == MediaRecorder.VideoEncoder.AV1) { 108 return MediaFormat.MIMETYPE_VIDEO_AV1; 109 } 110 // we should never be here 111 throw new RuntimeException("Unknown codec"); 112 } 113 114 /** 115 * The target video output bitrate in bits per second 116 * <p> 117 * This is the target recorded video output bitrate if the application configures the video 118 * recording via {@link MediaRecorder#setProfile} without specifying any other 119 * {@link MediaRecorder} encoding parameters. For example, for high speed quality profiles 120 * (from {@link CamcorderProfile#QUALITY_HIGH_SPEED_LOW} to {@link 121 * CamcorderProfile#QUALITY_HIGH_SPEED_2160P}), this is the bitrate where the video is 122 * recorded with. If the application intends to record slow motion videos with the high 123 * speed quality profiles, it must set a different video bitrate that is corresponding to 124 * the desired recording output bit rate (i.e., the encoded video bitrate during normal 125 * playback) via {@link MediaRecorder#setVideoEncodingBitRate}. For example, if {@link 126 * CamcorderProfile#QUALITY_HIGH_SPEED_720P} advertises 240fps {@link #getFrameRate} and 127 * 64Mbps {@link #getBitrate} in the high speed VideoProfile, and the application 128 * intends to record 1/8 factor slow motion recording videos, the application must set 30fps 129 * via {@link MediaRecorder#setVideoFrameRate} and 8Mbps ( {@link #getBitrate} * slow motion 130 * factor) via {@link MediaRecorder#setVideoEncodingBitRate}. Failing to do so will result 131 * in videos with unexpected frame rate and bit rate, or {@link MediaRecorder} error if the 132 * output bit rate exceeds the encoder limit. If the application intends to do the video 133 * recording with {@link MediaCodec} encoder, it must set each individual field of {@link 134 * MediaFormat} similarly according to this VideoProfile. 135 * </p> 136 * 137 * @see #getFrameRate 138 * @see MediaRecorder 139 * @see MediaCodec 140 * @see MediaFormat 141 */ getBitrate()142 public int getBitrate() { 143 return bitrate; 144 } 145 146 /** 147 * The target video frame rate in frames per second. 148 * <p> 149 * This is the target recorded video output frame rate per second if the application 150 * configures the video recording via {@link MediaRecorder#setProfile} without specifying 151 * any other {@link MediaRecorder} encoding parameters. For example, for high speed quality 152 * profiles (from {@link CamcorderProfile#QUALITY_HIGH_SPEED_LOW} to {@link 153 * CamcorderProfile#QUALITY_HIGH_SPEED_2160P}), this is the frame rate where the video is 154 * recorded and played back with. If the application intends to create slow motion use case 155 * with the high speed quality profiles, it must set a different video frame rate that is 156 * corresponding to the desired output (playback) frame rate via {@link 157 * MediaRecorder#setVideoFrameRate}. For example, if {@link 158 * CamcorderProfile#QUALITY_HIGH_SPEED_720P} advertises 240fps {@link #getFrameRate} 159 * in the VideoProfile, and the application intends to create 1/8 factor slow motion 160 * recording videos, the application must set 30fps via {@link 161 * MediaRecorder#setVideoFrameRate}. Failing to do so will result in high speed videos with 162 * normal speed playback frame rate (240fps for above example). If the application intends 163 * to do the video recording with {@link MediaCodec} encoder, it must set each individual 164 * field of {@link MediaFormat} similarly according to this VideoProfile. 165 * </p> 166 * 167 * @see #getBitrate 168 * @see MediaRecorder 169 * @see MediaCodec 170 * @see MediaFormat 171 */ getFrameRate()172 public int getFrameRate() { 173 return frameRate; 174 } 175 176 /** 177 * The target video frame width in pixels 178 */ getWidth()179 public int getWidth() { 180 return width; 181 } 182 183 /** 184 * The target video frame height in pixels 185 */ getHeight()186 public int getHeight() { 187 return height; 188 } 189 190 /** 191 * The video encoder profile being used for the video track. 192 * <p> 193 * This value is negative if there is no profile defined for the video codec. 194 * 195 * @see MediaRecorder#setVideoEncodingProfileLevel 196 * @see MediaFormat#KEY_PROFILE 197 */ getProfile()198 public int getProfile() { 199 return profile; 200 } 201 202 /** 203 * The bit depth of the encoded video. 204 * <p> 205 * This value is effectively 8 or 10, but some devices may 206 * support additional values. 207 */ getBitDepth()208 public int getBitDepth() { 209 return bitDepth; 210 } 211 212 /** 213 * The chroma subsampling of the encoded video. 214 * <p> 215 * For most devices this is always YUV_420 but some devices may 216 * support additional values. 217 * 218 * @see #YUV_420 219 * @see #YUV_422 220 * @see #YUV_444 221 */ getChromaSubsampling()222 public @ChromaSubsampling int getChromaSubsampling() { 223 return chromaSubsampling; 224 } 225 226 /** 227 * The HDR format of the encoded video. 228 * <p> 229 * This is one of the HDR_ values. 230 * @see #HDR_NONE 231 * @see #HDR_HLG 232 * @see #HDR_HDR10 233 * @see #HDR_HDR10PLUS 234 * @see #HDR_DOLBY_VISION 235 */ getHdrFormat()236 public @HdrFormat int getHdrFormat() { 237 return hdrFormat; 238 } 239 240 // Constructor called by JNI and CamcorderProfile VideoProfile(int codec, int width, int height, int frameRate, int bitrate, int profile, int chromaSubsampling, int bitDepth, int hdrFormat)241 /* package private */ VideoProfile(int codec, 242 int width, 243 int height, 244 int frameRate, 245 int bitrate, 246 int profile, 247 int chromaSubsampling, 248 int bitDepth, 249 int hdrFormat) { 250 this.codec = codec; 251 this.width = width; 252 this.height = height; 253 this.frameRate = frameRate; 254 this.bitrate = bitrate; 255 this.profile = profile; 256 this.chromaSubsampling = chromaSubsampling; 257 this.bitDepth = bitDepth; 258 this.hdrFormat = hdrFormat; 259 } 260 VideoProfile(int codec, int width, int height, int frameRate, int bitrate, int profile)261 /* package private */ VideoProfile(int codec, 262 int width, 263 int height, 264 int frameRate, 265 int bitrate, 266 int profile) { 267 this(codec, width, height, frameRate, bitrate, profile, 268 YUV_420, 8 /* bitDepth */, HDR_NONE); 269 } 270 271 private int codec; 272 private int width; 273 private int height; 274 private int frameRate; 275 private int bitrate; 276 private int profile; 277 private int chromaSubsampling; 278 private int bitDepth; 279 private int hdrFormat; 280 281 /** @hide */ 282 @IntDef({ 283 HDR_NONE, 284 HDR_HLG, 285 HDR_HDR10, 286 HDR_HDR10PLUS, 287 HDR_DOLBY_VISION, 288 }) 289 @Retention(RetentionPolicy.SOURCE) 290 public @interface HdrFormat {} 291 292 /** Not HDR (SDR). 293 * <p> 294 * An HDR format specifying SDR (Standard Dynamic 295 * Range) recording. */ 296 public static final int HDR_NONE = 0; 297 298 /** HLG (Hybrid-Log Gamma). 299 * <p> 300 * An HDR format specifying HLG. */ 301 public static final int HDR_HLG = 1; 302 303 /** HDR10. 304 * <p> 305 * An HDR format specifying HDR10. */ 306 public static final int HDR_HDR10 = 2; 307 308 /** HDR10+. 309 * <p> 310 * An HDR format specifying HDR10+. */ 311 public static final int HDR_HDR10PLUS = 3; 312 313 /** 314 * Dolby Vision 315 * <p> 316 * An HDR format specifying Dolby Vision. For this format 317 * the codec is always a Dolby Vision encoder. The encoder 318 * profile specifies which Dolby Vision version is being 319 * used. 320 * 321 * @see #getProfile 322 */ 323 public static final int HDR_DOLBY_VISION = 4; 324 325 /** @hide */ 326 @IntDef({ 327 YUV_420, 328 YUV_422, 329 YUV_444, 330 }) 331 @Retention(RetentionPolicy.SOURCE) 332 public @interface ChromaSubsampling {} 333 334 335 /** YUV 4:2:0. 336 * <p> 337 * A chroma subsampling where the U and V planes are subsampled 338 * by 2 both horizontally and vertically. */ 339 public static final int YUV_420 = 0; 340 341 /** YUV 4:2:2. 342 * <p> 343 * A chroma subsampling where the U and V planes are subsampled 344 * by 2 horizontally alone. */ 345 public static final int YUV_422 = 1; 346 347 /** YUV 4:4:4. 348 * <p> 349 * A chroma subsampling where the U and V planes are not 350 * subsampled. */ 351 public static final int YUV_444 = 2; 352 } 353 354 /** 355 * Returns the defined audio encoder profiles. 356 * <p> 357 * The list may be empty. This means there are no audio encoder 358 * profiles defined. Otherwise, the first profile is the default 359 * audio profile. 360 */ getAudioProfiles()361 public @NonNull List<AudioProfile> getAudioProfiles() { 362 return audioProfiles; 363 } 364 365 /** 366 * Returns the defined video encoder profiles. 367 * <p> 368 * The list may be empty. This means there are no video encoder 369 * profiles defined. Otherwise, the first profile is the default 370 * video profile. 371 */ getVideoProfiles()372 public @NonNull List<VideoProfile> getVideoProfiles() { 373 return videoProfiles; 374 } 375 376 /** 377 * Configuration for an audio encoder. 378 */ 379 public final static class AudioProfile { 380 /** 381 * The audio encoder being used for the audio track. 382 * @see android.media.MediaRecorder.AudioEncoder 383 */ getCodec()384 public @MediaRecorder.AudioEncoderValues int getCodec() { 385 return codec; 386 } 387 388 /** 389 * The media type of the audio encoder being used for the video track 390 * @see android.media.MediaFormat#KEY_MIME 391 */ getMediaType()392 public @NonNull String getMediaType() { 393 if (codec == MediaRecorder.AudioEncoder.AMR_NB) { 394 return MediaFormat.MIMETYPE_AUDIO_AMR_NB; 395 } else if (codec == MediaRecorder.AudioEncoder.AMR_WB) { 396 return MediaFormat.MIMETYPE_AUDIO_AMR_WB; 397 } else if (codec == MediaRecorder.AudioEncoder.AAC 398 || codec == MediaRecorder.AudioEncoder.HE_AAC 399 || codec == MediaRecorder.AudioEncoder.AAC_ELD) { 400 return MediaFormat.MIMETYPE_AUDIO_AAC; 401 } else if (codec == MediaRecorder.AudioEncoder.VORBIS) { 402 return MediaFormat.MIMETYPE_AUDIO_VORBIS; 403 } else if (codec == MediaRecorder.AudioEncoder.OPUS) { 404 return MediaFormat.MIMETYPE_AUDIO_OPUS; 405 } 406 // we should never be here 407 throw new RuntimeException("Unknown codec"); 408 } 409 410 /** 411 * The target audio output bitrate in bits per second 412 */ getBitrate()413 public int getBitrate() { 414 return bitrate; 415 } 416 417 /** 418 * The audio sampling rate used for the audio track 419 */ getSampleRate()420 public int getSampleRate() { 421 return sampleRate; 422 } 423 424 /** 425 * The number of audio channels used for the audio track 426 */ getChannels()427 public int getChannels() { 428 return channels; 429 } 430 431 /** 432 * The audio encoder profile being used for the audio track 433 * <p> 434 * This value is negative if there is no profile defined for the audio codec. 435 * @see MediaFormat#KEY_PROFILE 436 */ getProfile()437 public int getProfile() { 438 if (codec == MediaRecorder.AudioEncoder.AAC) { 439 return MediaCodecInfo.CodecProfileLevel.AACObjectMain; 440 } else if (codec == MediaRecorder.AudioEncoder.HE_AAC) { 441 return MediaCodecInfo.CodecProfileLevel.AACObjectHE; 442 } else if (codec == MediaRecorder.AudioEncoder.AAC_ELD) { 443 return MediaCodecInfo.CodecProfileLevel.AACObjectELD; 444 } 445 return profile; 446 } 447 448 449 // Constructor called by JNI and CamcorderProfile AudioProfile( int codec, int channels, int sampleRate, int bitrate, int profile)450 /* package private */ AudioProfile( 451 int codec, 452 int channels, 453 int sampleRate, 454 int bitrate, 455 int profile) { 456 this.codec = codec; 457 this.channels = channels; 458 this.sampleRate = sampleRate; 459 this.bitrate = bitrate; 460 this.profile = profile; 461 } 462 463 private int codec; 464 private int channels; 465 private int sampleRate; 466 private int bitrate; 467 private int profile; // this contains the profile if codec itself does not 468 } 469 470 private int durationSecs; 471 private int fileFormat; 472 // non-modifiable lists 473 private @NonNull List<AudioProfile> audioProfiles; 474 private @NonNull List<VideoProfile> videoProfiles; 475 476 // Constructor called by JNI and CamcorderProfile EncoderProfiles( int duration, int fileFormat, VideoProfile[] videoProfiles, AudioProfile[] audioProfiles)477 /* package private */ EncoderProfiles( 478 int duration, 479 int fileFormat, 480 VideoProfile[] videoProfiles, 481 AudioProfile[] audioProfiles) { 482 this.durationSecs = duration; 483 this.fileFormat = fileFormat; 484 this.videoProfiles = Collections.unmodifiableList(Arrays.asList(videoProfiles)); 485 this.audioProfiles = Collections.unmodifiableList(Arrays.asList(audioProfiles)); 486 } 487 } 488