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.NonNull; 20 21 import java.util.Arrays; 22 import java.util.Collections; 23 import java.util.List; 24 25 /** 26 * Describes a set of encoding profiles for a given media (audio and/or video) profile. 27 * These settings are read-only. 28 * 29 * <p>Currently, this is used to describe camera recording profile with more detail than {@link 30 * CamcorderProfile}, by providing encoding parameters for more than just the default audio 31 * and/or video codec. 32 * 33 * <p>The compressed output from a camera recording session contains two tracks: 34 * one for audio and one for video. 35 * <p>In the future audio-only recording profiles may be defined. 36 * 37 * <p>Each media profile specifies a set of audio and a set of video specific settings. 38 * <ul> 39 * <li> The file output format 40 * <li> Default file duration 41 * <p>Video-specific settings are: 42 * <li> Video codec format 43 * <li> Video bit rate in bits per second 44 * <li> Video frame rate in frames per second 45 * <li> Video frame width and height, 46 * <li> Video encoder profile. 47 * <p>Audio-specific settings are: 48 * <li> Audio codec format 49 * <li> Audio bit rate in bits per second, 50 * <li> Audio sample rate 51 * <li> Number of audio channels for recording. 52 * </ul> 53 */ 54 public final class EncoderProfiles 55 { 56 /** 57 * Default recording duration in seconds before the session is terminated. 58 * This is useful for applications like MMS that have a limited file size requirement. 59 * This could be 0 if there is no default recording duration. 60 */ getDefaultDurationSeconds()61 public int getDefaultDurationSeconds() { 62 return durationSecs; 63 } 64 65 /** 66 * Recommended output file format 67 * @see android.media.MediaRecorder.OutputFormat 68 */ getRecommendedFileFormat()69 public @MediaRecorder.OutputFormatValues int getRecommendedFileFormat() { 70 return fileFormat; 71 } 72 73 /** 74 * Configuration for a video encoder. 75 */ 76 public final static class VideoProfile { 77 /** 78 * The video encoder being used for the video track 79 * @see android.media.MediaRecorder.VideoEncoder 80 */ getCodec()81 public @MediaRecorder.VideoEncoderValues int getCodec() { 82 return codec; 83 } 84 85 /** 86 * The media type of the video encoder being used for the video track 87 * @see android.media.MediaFormat#KEY_MIME 88 */ getMediaType()89 public @NonNull String getMediaType() { 90 if (codec == MediaRecorder.VideoEncoder.H263) { 91 return MediaFormat.MIMETYPE_VIDEO_H263; 92 } else if (codec == MediaRecorder.VideoEncoder.H264) { 93 return MediaFormat.MIMETYPE_VIDEO_AVC; 94 } else if (codec == MediaRecorder.VideoEncoder.MPEG_4_SP) { 95 return MediaFormat.MIMETYPE_VIDEO_MPEG4; 96 } else if (codec == MediaRecorder.VideoEncoder.VP8) { 97 return MediaFormat.MIMETYPE_VIDEO_VP8; 98 } else if (codec == MediaRecorder.VideoEncoder.HEVC) { 99 return MediaFormat.MIMETYPE_VIDEO_HEVC; 100 } 101 // we should never be here 102 throw new RuntimeException("Unknown codec"); 103 } 104 105 /** 106 * The target video output bitrate in bits per second 107 * <p> 108 * This is the target recorded video output bitrate if the application configures the video 109 * recording via {@link MediaRecorder#setProfile} without specifying any other 110 * {@link MediaRecorder} encoding parameters. For example, for high speed quality profiles 111 * (from {@link CamcorderProfile#QUALITY_HIGH_SPEED_LOW} to {@link 112 * CamcorderProfile#QUALITY_HIGH_SPEED_2160P}), this is the bitrate where the video is 113 * recorded with. If the application intends to record slow motion videos with the high 114 * speed quality profiles, it must set a different video bitrate that is corresponding to 115 * the desired recording output bit rate (i.e., the encoded video bitrate during normal 116 * playback) via {@link MediaRecorder#setVideoEncodingBitRate}. For example, if {@link 117 * CamcorderProfile#QUALITY_HIGH_SPEED_720P} advertises 240fps {@link #getFrameRate} and 118 * 64Mbps {@link #getBitrate} in the high speed VideoProfile, and the application 119 * intends to record 1/8 factor slow motion recording videos, the application must set 30fps 120 * via {@link MediaRecorder#setVideoFrameRate} and 8Mbps ( {@link #getBitrate} * slow motion 121 * factor) via {@link MediaRecorder#setVideoEncodingBitRate}. Failing to do so will result 122 * in videos with unexpected frame rate and bit rate, or {@link MediaRecorder} error if the 123 * output bit rate exceeds the encoder limit. If the application intends to do the video 124 * recording with {@link MediaCodec} encoder, it must set each individual field of {@link 125 * MediaFormat} similarly according to this VideoProfile. 126 * </p> 127 * 128 * @see #getFrameRate 129 * @see MediaRecorder 130 * @see MediaCodec 131 * @see MediaFormat 132 */ getBitrate()133 public int getBitrate() { 134 return bitrate; 135 } 136 137 /** 138 * The target video frame rate in frames per second. 139 * <p> 140 * This is the target recorded video output frame rate per second if the application 141 * configures the video recording via {@link MediaRecorder#setProfile} without specifying 142 * any other {@link MediaRecorder} encoding parameters. For example, for high speed quality 143 * profiles (from {@link CamcorderProfile#QUALITY_HIGH_SPEED_LOW} to {@link 144 * CamcorderProfile#QUALITY_HIGH_SPEED_2160P}), this is the frame rate where the video is 145 * recorded and played back with. If the application intends to create slow motion use case 146 * with the high speed quality profiles, it must set a different video frame rate that is 147 * corresponding to the desired output (playback) frame rate via {@link 148 * MediaRecorder#setVideoFrameRate}. For example, if {@link 149 * CamcorderProfile#QUALITY_HIGH_SPEED_720P} advertises 240fps {@link #getFrameRate} 150 * in the VideoProfile, and the application intends to create 1/8 factor slow motion 151 * recording videos, the application must set 30fps via {@link 152 * MediaRecorder#setVideoFrameRate}. Failing to do so will result in high speed videos with 153 * normal speed playback frame rate (240fps for above example). If the application intends 154 * to do the video recording with {@link MediaCodec} encoder, it must set each individual 155 * field of {@link MediaFormat} similarly according to this VideoProfile. 156 * </p> 157 * 158 * @see #getBitrate 159 * @see MediaRecorder 160 * @see MediaCodec 161 * @see MediaFormat 162 */ getFrameRate()163 public int getFrameRate() { 164 return frameRate; 165 } 166 167 /** 168 * The target video frame width in pixels 169 */ getWidth()170 public int getWidth() { 171 return width; 172 } 173 174 /** 175 * The target video frame height in pixels 176 */ getHeight()177 public int getHeight() { 178 return height; 179 } 180 181 /** 182 * The video encoder profile being used for the video track. 183 * <p> 184 * This value is negative if there is no profile defined for the video codec. 185 * 186 * @see MediaRecorder#setVideoEncodingProfileLevel 187 * @see MediaFormat#KEY_PROFILE 188 */ getProfile()189 public int getProfile() { 190 return profile; 191 } 192 193 // Constructor called by JNI and CamcorderProfile VideoProfile(int codec, int width, int height, int frameRate, int bitrate, int profile)194 /* package private */ VideoProfile(int codec, 195 int width, 196 int height, 197 int frameRate, 198 int bitrate, 199 int profile) { 200 this.codec = codec; 201 this.width = width; 202 this.height = height; 203 this.frameRate = frameRate; 204 this.bitrate = bitrate; 205 this.profile = profile; 206 } 207 208 private int codec; 209 private int width; 210 private int height; 211 private int frameRate; 212 private int bitrate; 213 private int profile; 214 } 215 216 /** 217 * Returns the defined audio encoder profiles. 218 * <p> 219 * The list may be empty. This means there are no audio encoder 220 * profiles defined. Otherwise, the first profile is the default 221 * audio profile. 222 */ getAudioProfiles()223 public @NonNull List<AudioProfile> getAudioProfiles() { 224 return audioProfiles; 225 } 226 227 /** 228 * Returns the defined video encoder profiles. 229 * <p> 230 * The list may be empty. This means there are no video encoder 231 * profiles defined. Otherwise, the first profile is the default 232 * video profile. 233 */ getVideoProfiles()234 public @NonNull List<VideoProfile> getVideoProfiles() { 235 return videoProfiles; 236 } 237 238 /** 239 * Configuration for an audio encoder. 240 */ 241 public final static class AudioProfile { 242 /** 243 * The audio encoder being used for the audio track. 244 * @see android.media.MediaRecorder.AudioEncoder 245 */ getCodec()246 public @MediaRecorder.AudioEncoderValues int getCodec() { 247 return codec; 248 } 249 250 /** 251 * The media type of the audio encoder being used for the video track 252 * @see android.media.MediaFormat#KEY_MIME 253 */ getMediaType()254 public @NonNull String getMediaType() { 255 if (codec == MediaRecorder.AudioEncoder.AMR_NB) { 256 return MediaFormat.MIMETYPE_AUDIO_AMR_NB; 257 } else if (codec == MediaRecorder.AudioEncoder.AMR_WB) { 258 return MediaFormat.MIMETYPE_AUDIO_AMR_WB; 259 } else if (codec == MediaRecorder.AudioEncoder.AAC 260 || codec == MediaRecorder.AudioEncoder.HE_AAC 261 || codec == MediaRecorder.AudioEncoder.AAC_ELD) { 262 return MediaFormat.MIMETYPE_AUDIO_AAC; 263 } else if (codec == MediaRecorder.AudioEncoder.VORBIS) { 264 return MediaFormat.MIMETYPE_AUDIO_VORBIS; 265 } else if (codec == MediaRecorder.AudioEncoder.OPUS) { 266 return MediaFormat.MIMETYPE_AUDIO_OPUS; 267 } 268 // we should never be here 269 throw new RuntimeException("Unknown codec"); 270 } 271 272 /** 273 * The target audio output bitrate in bits per second 274 */ getBitrate()275 public int getBitrate() { 276 return bitrate; 277 } 278 279 /** 280 * The audio sampling rate used for the audio track 281 */ getSampleRate()282 public int getSampleRate() { 283 return sampleRate; 284 } 285 286 /** 287 * The number of audio channels used for the audio track 288 */ getChannels()289 public int getChannels() { 290 return channels; 291 } 292 293 /** 294 * The audio encoder profile being used for the audio track 295 * <p> 296 * This value is negative if there is no profile defined for the audio codec. 297 * @see MediaFormat#KEY_PROFILE 298 */ getProfile()299 public int getProfile() { 300 if (codec == MediaRecorder.AudioEncoder.AAC) { 301 return MediaCodecInfo.CodecProfileLevel.AACObjectMain; 302 } else if (codec == MediaRecorder.AudioEncoder.HE_AAC) { 303 return MediaCodecInfo.CodecProfileLevel.AACObjectHE; 304 } else if (codec == MediaRecorder.AudioEncoder.AAC_ELD) { 305 return MediaCodecInfo.CodecProfileLevel.AACObjectELD; 306 } 307 return profile; 308 } 309 310 311 // Constructor called by JNI and CamcorderProfile AudioProfile( int codec, int channels, int sampleRate, int bitrate, int profile)312 /* package private */ AudioProfile( 313 int codec, 314 int channels, 315 int sampleRate, 316 int bitrate, 317 int profile) { 318 this.codec = codec; 319 this.channels = channels; 320 this.sampleRate = sampleRate; 321 this.bitrate = bitrate; 322 this.profile = profile; 323 } 324 325 private int codec; 326 private int channels; 327 private int sampleRate; 328 private int bitrate; 329 private int profile; // this contains the profile if codec itself does not 330 } 331 332 private int durationSecs; 333 private int fileFormat; 334 // non-modifiable lists 335 private @NonNull List<AudioProfile> audioProfiles; 336 private @NonNull List<VideoProfile> videoProfiles; 337 338 // Constructor called by JNI and CamcorderProfile EncoderProfiles( int duration, int fileFormat, VideoProfile[] videoProfiles, AudioProfile[] audioProfiles)339 /* package private */ EncoderProfiles( 340 int duration, 341 int fileFormat, 342 VideoProfile[] videoProfiles, 343 AudioProfile[] audioProfiles) { 344 this.durationSecs = duration; 345 this.fileFormat = fileFormat; 346 this.videoProfiles = Collections.unmodifiableList(Arrays.asList(videoProfiles)); 347 this.audioProfiles = Collections.unmodifiableList(Arrays.asList(audioProfiles)); 348 } 349 } 350