• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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