Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d42cf0d4 authored by Lajos Molnar's avatar Lajos Molnar Committed by Android (Google) Code Review
Browse files

Merge "media: added advanced HDR-ready CamcorderProfiles"

parents 17d7492e ed4b9472
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -20571,13 +20571,24 @@ package android.media {
  }
  public static final class EncoderProfiles.VideoProfile {
    method public int getBitDepth();
    method public int getBitrate();
    method public int getChromaSubsampling();
    method public int getCodec();
    method public int getFrameRate();
    method public int getHdrFormat();
    method public int getHeight();
    method @NonNull public String getMediaType();
    method public int getProfile();
    method public int getWidth();
    field public static final int HDR_DOLBY_VISION = 4; // 0x4
    field public static final int HDR_HDR10 = 2; // 0x2
    field public static final int HDR_HDR10PLUS = 3; // 0x3
    field public static final int HDR_HLG = 1; // 0x1
    field public static final int HDR_NONE = 0; // 0x0
    field public static final int YUV_420 = 0; // 0x0
    field public static final int YUV_422 = 1; // 0x1
    field public static final int YUV_444 = 2; // 0x2
  }
  public class ExifInterface {
@@ -22686,12 +22697,15 @@ package android.media {
  }
  public final class MediaRecorder.VideoEncoder {
    field public static final int AV1 = 8; // 0x8
    field public static final int DEFAULT = 0; // 0x0
    field public static final int DOLBY_VISION = 7; // 0x7
    field public static final int H263 = 1; // 0x1
    field public static final int H264 = 2; // 0x2
    field public static final int HEVC = 5; // 0x5
    field public static final int MPEG_4_SP = 3; // 0x3
    field public static final int VP8 = 4; // 0x4
    field public static final int VP9 = 6; // 0x6
  }
  public final class MediaRecorder.VideoSource {
+28 −8
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
@@ -526,9 +529,17 @@ public class CamcorderProfile
    }

    /**
     * Returns all encoder profiles of a camcorder profile for the given camera at
     * the given quality level.
     *
     * This change id controls the kind of video profiles returned by {@link #getAll}.
     * @hide
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    public static final long RETURN_ADVANCED_VIDEO_PROFILES = 206033068L; // buganizer id

    /**
     * Returns all basic encoder profiles of a camcorder profile for
     * the given camera at the given quality level.
     * <p>
     * Quality levels QUALITY_LOW, QUALITY_HIGH are guaranteed to be supported, while
     * other levels may or may not be supported. The supported levels can be checked using
     * {@link #hasProfile(int, int)}.
@@ -537,19 +548,26 @@ public class CamcorderProfile
     * QUALITY_LOW/QUALITY_HIGH have to match one of qcif, cif, 480p, 720p, 1080p or 2160p.
     * E.g. if the device supports 480p, 720p, 1080p and 2160p, then low is 480p and high is
     * 2160p.
     *
     * <p>
     * The same is true for time lapse quality levels, i.e. QUALITY_TIME_LAPSE_LOW,
     * QUALITY_TIME_LAPSE_HIGH are guaranteed to be supported and have to match one of
     * qcif, cif, 480p, 720p, 1080p, or 2160p.
     *
     * <p>
     * For high speed quality levels, they may or may not be supported. If a subset of the levels
     * are supported, QUALITY_HIGH_SPEED_LOW and QUALITY_HIGH_SPEED_HIGH are guaranteed to be
     * supported and have to match one of 480p, 720p, or 1080p.
     *
     * <p>
     * A camcorder recording session with higher quality level usually has higher output
     * bit rate, better video and/or audio recording quality, larger video frame
     * resolution and higher audio sampling rate, etc, than those with lower quality
     * level.
     * <p>
     * <b>Note:</b> as of {@link android.os.Build.VERSION_CODES#TIRAMISU Android TIRAMISU},
     * this method can return advanced encoder profiles.
     * <p>Apps targeting {@link Build.VERSION_CODES#S_V2} or before will only receive basic
     * video encoder profiles that use output YUV 4:2:0 8-bit content.
     * Apps targeting {@link Build.VERSION_CODES#TIRAMISU} or above will also receive advanced
     * video encoder profiles that may output 10-bit, YUV 4:2:2/4:4:4 or HDR content.
     *
     * @param cameraId the id for the camera. Numeric camera ids from the list received by invoking
     *                 {@link CameraManager#getCameraIdList} can be used as long as they are
@@ -602,7 +620,9 @@ public class CamcorderProfile
        } catch (NumberFormatException e) {
            return null;
        }
        return native_get_camcorder_profiles(id, quality);
        return native_get_camcorder_profiles(
                id, quality,
                CompatChanges.isChangeEnabled(RETURN_ADVANCED_VIDEO_PROFILES));
    }

    /**
@@ -712,7 +732,7 @@ public class CamcorderProfile
    private static native final CamcorderProfile native_get_camcorder_profile(
            int cameraId, int quality);
    private static native final EncoderProfiles native_get_camcorder_profiles(
            int cameraId, int quality);
            int cameraId, int quality, boolean advanced);
    private static native final boolean native_has_camcorder_profile(
            int cameraId, int quality);
}
+139 −1
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package android.media;

import android.annotation.IntDef;
import android.annotation.NonNull;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -97,6 +100,12 @@ public final class EncoderProfiles
                return MediaFormat.MIMETYPE_VIDEO_VP8;
            } else if (codec == MediaRecorder.VideoEncoder.HEVC) {
                return MediaFormat.MIMETYPE_VIDEO_HEVC;
            } else if (codec == MediaRecorder.VideoEncoder.VP9) {
                return MediaFormat.MIMETYPE_VIDEO_VP9;
            } else if (codec == MediaRecorder.VideoEncoder.DOLBY_VISION) {
                return MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION;
            } else if (codec == MediaRecorder.VideoEncoder.AV1) {
                return MediaFormat.MIMETYPE_VIDEO_AV1;
            }
            // we should never be here
            throw new RuntimeException("Unknown codec");
@@ -190,19 +199,73 @@ public final class EncoderProfiles
            return profile;
        }

        /**
         * The bit depth of the encoded video.
         * <p>
         * This value is effectively 8 or 10, but some devices may
         * support additional values.
         */
        public int getBitDepth() {
            return bitDepth;
        }

        /**
         * The chroma subsampling of the encoded video.
         * <p>
         * For most devices this is always YUV_420 but some devices may
         * support additional values.
         *
         * @see #YUV_420
         * @see #YUV_422
         * @see #YUV_444
         */
        public @ChromaSubsampling int getChromaSubsampling() {
            return chromaSubsampling;
        }

        /**
         * The HDR format of the encoded video.
         * <p>
         * This is one of the HDR_ values.
         * @see #HDR_NONE
         * @see #HDR_HLG
         * @see #HDR_HDR10
         * @see #HDR_HDR10PLUS
         * @see #HDR_DOLBY_VISION
         */
        public @HdrFormat int getHdrFormat() {
            return hdrFormat;
        }

        // Constructor called by JNI and CamcorderProfile
        /* package private */ VideoProfile(int codec,
                             int width,
                             int height,
                             int frameRate,
                             int bitrate,
                             int profile) {
                             int profile,
                             int chromaSubsampling,
                             int bitDepth,
                             int hdrFormat) {
            this.codec = codec;
            this.width = width;
            this.height = height;
            this.frameRate = frameRate;
            this.bitrate = bitrate;
            this.profile = profile;
            this.chromaSubsampling = chromaSubsampling;
            this.bitDepth = bitDepth;
            this.hdrFormat = hdrFormat;
        }

        /* package private */ VideoProfile(int codec,
                             int width,
                             int height,
                             int frameRate,
                             int bitrate,
                             int profile) {
            this(codec, width, height, frameRate, bitrate, profile,
                 YUV_420, 8 /* bitDepth */, HDR_NONE);
        }

        private int codec;
@@ -211,6 +274,81 @@ public final class EncoderProfiles
        private int frameRate;
        private int bitrate;
        private int profile;
        private int chromaSubsampling;
        private int bitDepth;
        private int hdrFormat;

        /** @hide */
        @IntDef({
            HDR_NONE,
            HDR_HLG,
            HDR_HDR10,
            HDR_HDR10PLUS,
            HDR_DOLBY_VISION,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface HdrFormat {}

        /** Not HDR (SDR).
         *  <p>
         *  An HDR format specifying SDR (Standard Dynamic
         *  Range) recording. */
        public static final int HDR_NONE = 0;

        /** HLG (Hybrid-Log Gamma).
         *  <p>
         *  An HDR format specifying HLG. */
        public static final int HDR_HLG = 1;

        /** HDR10.
         *  <p>
         *  An HDR format specifying HDR10. */
        public static final int HDR_HDR10 = 2;

        /** HDR10+.
         *  <p>
         *  An HDR format specifying HDR10+. */
        public static final int HDR_HDR10PLUS = 3;

        /**
         *  Dolby Vision
         *  <p>
         *  An HDR format specifying Dolby Vision. For this format
         *  the codec is always a Dolby Vision encoder. The encoder
         *  profile specifies which Dolby Vision version is being
         *  used.
         *
         *  @see #getProfile
         */
        public static final int HDR_DOLBY_VISION = 4;

        /** @hide */
        @IntDef({
            YUV_420,
            YUV_422,
            YUV_444,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ChromaSubsampling {}


        /** YUV 4:2:0.
         *  <p>
         *  A chroma subsampling where the U and V planes are subsampled
         *  by 2 both horizontally and vertically. */
        public static final int YUV_420 = 0;

        /** YUV 4:2:2.
         *  <p>
         *  A chroma subsampling where the U and V planes are subsampled
         *  by 2 horizontally alone. */
        public static final int YUV_422 = 1;

        /** YUV 4:4:4.
         *  <p>
         *  A chroma subsampling where the U and V planes are not
         *  subsampled. */
        public static final int YUV_444 = 2;
    }

    /**
+6 −0
Original line number Diff line number Diff line
@@ -705,6 +705,9 @@ public class MediaRecorder implements AudioRouting,
        public static final int MPEG_4_SP = 3;
        public static final int VP8 = 4;
        public static final int HEVC = 5;
        public static final int VP9 = 6;
        public static final int DOLBY_VISION = 7;
        public static final int AV1 = 8;
    }

    /**
@@ -717,6 +720,9 @@ public class MediaRecorder implements AudioRouting,
        VideoEncoder.MPEG_4_SP,
        VideoEncoder.VP8,
        VideoEncoder.HEVC,
        VideoEncoder.VP9,
        VideoEncoder.DOLBY_VISION,
        VideoEncoder.AV1,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface VideoEncoderValues {}
+17 −4
Original line number Diff line number Diff line
@@ -225,7 +225,7 @@ android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject /*

static jobject
android_media_MediaProfiles_native_get_camcorder_profiles(JNIEnv *env, jobject /* thiz */, jint id,
                                                          jint quality)
                                                          jint quality, jboolean advanced)
{
    ALOGV("native_get_camcorder_profiles: %d %d", id, quality);
    if (!isCamcorderQualityKnown(quality)) {
@@ -251,7 +251,7 @@ android_media_MediaProfiles_native_get_camcorder_profiles(JNIEnv *env, jobject /

    jclass videoProfileClazz = env->FindClass("android/media/EncoderProfiles$VideoProfile");
    jmethodID videoProfileConstructorMethodID =
        env->GetMethodID(videoProfileClazz, "<init>", "(IIIIII)V");
        env->GetMethodID(videoProfileClazz, "<init>", "(IIIIIIIII)V");

    jclass audioProfileClazz = env->FindClass("android/media/EncoderProfiles$AudioProfile");
    jmethodID audioProfileConstructorMethodID =
@@ -262,6 +262,16 @@ android_media_MediaProfiles_native_get_camcorder_profiles(JNIEnv *env, jobject /
    {
        int i = 0;
        for (const MediaProfiles::VideoCodec *vc : cp->getVideoCodecs()) {
            chroma_subsampling cs = vc->getChromaSubsampling();
            int bitDepth = vc->getBitDepth();
            hdr_format hdr = vc->getHdrFormat();

            bool isAdvanced =
                (bitDepth != 8 || cs != CHROMA_SUBSAMPLING_YUV_420 || hdr != HDR_FORMAT_NONE);
            if (static_cast<bool>(advanced) && !isAdvanced) {
                continue;
            }

            jobject videoCodec = env->NewObject(videoProfileClazz,
                                                videoProfileConstructorMethodID,
                                                vc->getCodec(),
@@ -269,7 +279,10 @@ android_media_MediaProfiles_native_get_camcorder_profiles(JNIEnv *env, jobject /
                                                vc->getFrameHeight(),
                                                vc->getFrameRate(),
                                                vc->getBitrate(),
                                                vc->getProfile());
                                                vc->getProfile(),
                                                static_cast<int>(cs),
                                                bitDepth,
                                                static_cast<int>(hdr));
            env->SetObjectArrayElement(videoCodecs, i++, videoCodec);
        }
    }
@@ -400,7 +413,7 @@ static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
    {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
    {"native_get_camcorder_profile",           "(II)Landroid/media/CamcorderProfile;",
                                                                         (void *)android_media_MediaProfiles_native_get_camcorder_profile},
    {"native_get_camcorder_profiles",          "(II)Landroid/media/EncoderProfiles;",
    {"native_get_camcorder_profiles",          "(IIZ)Landroid/media/EncoderProfiles;",
                                                                         (void *)android_media_MediaProfiles_native_get_camcorder_profiles},
    {"native_has_camcorder_profile",           "(II)Z",
                                                                         (void *)android_media_MediaProfiles_native_has_camcorder_profile},