From 18a8ecb60012335259135a45cbe05d8bf0f93190 Mon Sep 17 00:00:00 2001 From: Weijie Wang Date: Thu, 17 Aug 2017 16:49:51 +0800 Subject: SnapdragonCamera: Support HLG and HDR10 Support HLG and HDR10 Change-Id: I1dd8a40a85e9cc0115515217b4ec75a726b6f41e --- src/com/android/camera/CameraSettings.java | 38 ++++++++++++++++++++++ src/com/android/camera/CaptureModule.java | 36 ++++++++++++++++++-- src/com/android/camera/SettingsActivity.java | 2 ++ src/com/android/camera/SettingsManager.java | 37 ++++++++++++++++++++- .../android/camera/util/SettingTranslation.java | 15 +++++++++ src/com/android/camera/util/VendorTagUtil.java | 25 +++++++++++++- 6 files changed, 149 insertions(+), 4 deletions(-) (limited to 'src/com/android') diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java index 541c65704..7ccf19b8f 100644 --- a/src/com/android/camera/CameraSettings.java +++ b/src/com/android/camera/CameraSettings.java @@ -338,6 +338,44 @@ public class CameraSettings { VIDEO_ENCODER_BITRATE.put("1280x720:120", 35000000); VIDEO_ENCODER_BITRATE.put("1280x720:240", 72000000); VIDEO_ENCODER_BITRATE.put("720:480:120", 5200000); + //4k DCI + VIDEO_ENCODER_BITRATE.put("4096x2160:60" + MediaRecorder.VideoEncoder.HEVC, 70840000); + VIDEO_ENCODER_BITRATE.put("4096x2160:90" + MediaRecorder.VideoEncoder.HEVC, 84700000); + VIDEO_ENCODER_BITRATE.put("4096x2160:120" + MediaRecorder.VideoEncoder.HEVC, 106260000); + //4k UHD + VIDEO_ENCODER_BITRATE.put("3840x2160:60" + MediaRecorder.VideoEncoder.HEVC, 61600000); + VIDEO_ENCODER_BITRATE.put("3840x2160:90" + MediaRecorder.VideoEncoder.HEVC, 73920000); + VIDEO_ENCODER_BITRATE.put("3840x2160:120" + MediaRecorder.VideoEncoder.HEVC, 92400000); + //QHD + VIDEO_ENCODER_BITRATE.put("2560x1440:60" + MediaRecorder.VideoEncoder.HEVC, 38808000); + VIDEO_ENCODER_BITRATE.put("2560x1440:90" + MediaRecorder.VideoEncoder.HEVC, 51744000); + VIDEO_ENCODER_BITRATE.put("2560x1440:120" + MediaRecorder.VideoEncoder.HEVC, 56595000); + VIDEO_ENCODER_BITRATE.put("2560x1440:240" + MediaRecorder.VideoEncoder.HEVC, 88935000); + //HD 1080p + VIDEO_ENCODER_BITRATE.put("1920x1080:60" + MediaRecorder.VideoEncoder.HEVC, 24640000); + VIDEO_ENCODER_BITRATE.put("1920x1080:90" + MediaRecorder.VideoEncoder.HEVC, 30800000); + VIDEO_ENCODER_BITRATE.put("1920x1080:120" + MediaRecorder.VideoEncoder.HEVC, 38500000); + VIDEO_ENCODER_BITRATE.put("1920x1080:240" + MediaRecorder.VideoEncoder.HEVC, 61600000); + //HD 720p + VIDEO_ENCODER_BITRATE.put("1280x720:60" + MediaRecorder.VideoEncoder.HEVC, 18480000); + VIDEO_ENCODER_BITRATE.put("1280x720:90" + MediaRecorder.VideoEncoder.HEVC, 24640000); + VIDEO_ENCODER_BITRATE.put("1280x720:120" + MediaRecorder.VideoEncoder.HEVC, 26950000); + VIDEO_ENCODER_BITRATE.put("1280x720:240" + MediaRecorder.VideoEncoder.HEVC, 42350000); + //VGA + VIDEO_ENCODER_BITRATE.put("640x480:60" + MediaRecorder.VideoEncoder.HEVC, 1892352); + VIDEO_ENCODER_BITRATE.put("640x480:90" + MediaRecorder.VideoEncoder.HEVC, 2464000); + VIDEO_ENCODER_BITRATE.put("640x480:120" + MediaRecorder.VideoEncoder.HEVC, 3027640); + VIDEO_ENCODER_BITRATE.put("640x480:240" + MediaRecorder.VideoEncoder.HEVC, 4928000); + //CIF + VIDEO_ENCODER_BITRATE.put("352x288:60" + MediaRecorder.VideoEncoder.HEVC, 887040); + VIDEO_ENCODER_BITRATE.put("352x288:90" + MediaRecorder.VideoEncoder.HEVC, 1078000); + VIDEO_ENCODER_BITRATE.put("352x288:120" + MediaRecorder.VideoEncoder.HEVC, 1416800); + VIDEO_ENCODER_BITRATE.put("352x288:240" + MediaRecorder.VideoEncoder.HEVC, 2310000); + //QVGA + VIDEO_ENCODER_BITRATE.put("320x240:60" + MediaRecorder.VideoEncoder.HEVC, 630784); + VIDEO_ENCODER_BITRATE.put("320x240:90" + MediaRecorder.VideoEncoder.HEVC, 770000); + VIDEO_ENCODER_BITRATE.put("320x240:120" + MediaRecorder.VideoEncoder.HEVC, 1016400); + VIDEO_ENCODER_BITRATE.put("320x240:240" + MediaRecorder.VideoEncoder.HEVC, 1617000); //resolution, fps and encoder type VIDEO_ENCODER_BITRATE.put("3840x2160:60:" + MediaRecorder.VideoEncoder.H264, 67200000); diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index 5b029df86..a6669971e 100644 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -55,13 +55,14 @@ import android.location.Location; import android.media.AudioManager; import android.media.CamcorderProfile; import android.media.CameraProfile; +import android.media.EncoderCapabilities; +import android.media.EncoderCapabilities.VideoEncoderCap; import android.media.Image; import android.media.ImageReader; import android.media.MediaActionSound; import android.media.MediaMetadataRetriever; import android.media.MediaRecorder; -import android.media.EncoderCapabilities; -import android.media.EncoderCapabilities.VideoEncoderCap; +import android.media.MediaCodecInfo; import android.net.Uri; import android.os.Bundle; import android.os.Debug; @@ -222,6 +223,7 @@ public class CaptureModule implements CameraModule, PhotoController, new CaptureRequest.Key<>("org.codeaurora.qcamera3.saturation.use_saturation", Integer.class); public static final CaptureRequest.Key histMode = new CaptureRequest.Key<>("org.codeaurora.qcamera3.histogram.enable", byte.class); + public static CameraCharacteristics.Key buckets = new CameraCharacteristics.Key<>("org.codeaurora.qcamera3.histogram.buckets", Integer.class); public static CameraCharacteristics.Key maxCount = @@ -3260,6 +3262,7 @@ public class CaptureModule implements CameraModule, PhotoController, mCaptureSession[cameraId] = cameraCaptureSession; try { setUpVideoCaptureRequestBuilder(mVideoRequestBuilder, cameraId); + mCurrentSession.setRepeatingRequest(mVideoRequestBuilder.build(), mCaptureCallback, mCameraHandler); } catch (CameraAccessException e) { @@ -3325,6 +3328,7 @@ public class CaptureModule implements CameraModule, PhotoController, applyVideoFlash(builder); applyFaceDetection(builder); applyZoom(builder, cameraId); + applyVideoEncoderProfile(builder); } private void updateVideoFlash() { @@ -3368,6 +3372,25 @@ public class CaptureModule implements CameraModule, PhotoController, } } + private void applyVideoEncoderProfile(CaptureRequest.Builder builder) { + int profile = SettingTranslation.getVideoEncoderProfile( + mSettingsManager.getValue(SettingsManager.KEY_VIDEO_ENCODER_PROFILE)); + int mode = 0; + switch(profile) { + case MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10: + mode = 1; + break; + case MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10: + mode = 2; + break; + } + VendorTagUtil.setHDRVideoMode(builder, (byte)mode); + } + + private boolean isVideoEncoderProfileSupported() { + return !mSettingsManager.getValue(SettingsManager.KEY_VIDEO_ENCODER_PROFILE).equals("off"); + } + private long getTimeLapseVideoLength(long deltaMs) { // For better approximation calculate fractional number of frames captured. // This will update the video time at a higher resolution. @@ -3631,6 +3654,15 @@ public class CaptureModule implements CameraModule, PhotoController, mProfile.fileFormat = MediaRecorder.OutputFormat.THREE_GPP; } } + + if ( isVideoEncoderProfileSupported() + && VendorTagUtil.isHDRVideoModeSupported(mCameraDevice[cameraId])) { + int videoEncoderProfile = SettingTranslation.getVideoEncoderProfile( + mSettingsManager.getValue(SettingsManager.KEY_VIDEO_ENCODER_PROFILE)); + mMediaRecorder.setVideoEncodingProfileLevel(videoEncoderProfile, + MediaCodecInfo.CodecProfileLevel.HEVCMainTierLevel1); + } + mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setOutputFormat(mProfile.fileFormat); diff --git a/src/com/android/camera/SettingsActivity.java b/src/com/android/camera/SettingsActivity.java index 8d732b73a..74957bd63 100644 --- a/src/com/android/camera/SettingsActivity.java +++ b/src/com/android/camera/SettingsActivity.java @@ -82,6 +82,8 @@ public class SettingsActivity extends PreferenceActivity { if (key.equals(SettingsManager.KEY_VIDEO_QUALITY)) { updatePreference(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE); updatePreference(SettingsManager.KEY_VIDEO_ENCODER); + }else if ( key.equals(SettingsManager.KEY_VIDEO_ENCODER) ) { + updatePreference(SettingsManager.KEY_VIDEO_ENCODER_PROFILE); } List list = mSettingsManager.getDependentKeys(key); if (list != null) { diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java index af796c6a7..d5539318e 100644 --- a/src/com/android/camera/SettingsManager.java +++ b/src/com/android/camera/SettingsManager.java @@ -150,6 +150,7 @@ public class SettingsManager implements ListMenu.SettingsListener { public static final HashMap KEY_ISO_INDEX = new HashMap(); public static final String KEY_BSGC_DETECTION = "pref_camera2_bsgc_key"; public static final String KEY_ZSL = "pref_camera2_zsl_key"; + public static final String KEY_VIDEO_ENCODER_PROFILE = "pref_camera2_videoencoderprofile_key"; private static final String TAG = "SnapCam_SettingsManager"; @@ -166,6 +167,7 @@ public class SettingsManager implements ListMenu.SettingsListener { private JSONObject mDependency; private int mCameraId; private Set mFilteredKeys; + private static Map> VIDEO_ENCODER_PROFILE_TABLE = new HashMap<>(); public Map getValuesMap() { return mValuesMap; @@ -185,6 +187,10 @@ public class SettingsManager implements ListMenu.SettingsListener { KEY_ISO_INDEX.put("400", 4); KEY_ISO_INDEX.put("800", 5); KEY_ISO_INDEX.put("1600", 6); + Set h265 = new HashSet<>(); + h265.add("HEVCProfileMain10"); + h265.add("HEVCProfileMain10HDR10"); + VIDEO_ENCODER_PROFILE_TABLE.put("h265", h265); } private SettingsManager(Context context) { @@ -394,6 +400,7 @@ public class SettingsManager implements ListMenu.SettingsListener { turnOn.remove(it.next()); } + for (String keyToTurnOn: turnOn) { Set dependsOnSet = mDependendsOnMap.get(keyToTurnOn); if (dependsOnSet == null || dependsOnSet.size() == 0) continue; @@ -754,6 +761,7 @@ public class SettingsManager implements ListMenu.SettingsListener { // These list can be changed run-time filterHFROptions(); filterVideoEncoderOptions(); + filterVideoEncoderProfileOptions(); if (!mIsFrontCameraPresent || !isFacingFront(mCameraId)) { removePreference(mPreferenceGroup, KEY_SELFIE_FLASH); @@ -766,6 +774,8 @@ public class SettingsManager implements ListMenu.SettingsListener { mFilteredKeys.add(zoom.getKey()); } } + + } private void runTimeUpdateDependencyOptions(ListPreference pref) { @@ -775,6 +785,8 @@ public class SettingsManager implements ListMenu.SettingsListener { filterVideoEncoderOptions(); } else if (pref.getKey().equals(KEY_SCENE_MODE)) { filterChromaflashPictureSizeOptions(); + } else if ( pref.getKey().equals(KEY_VIDEO_ENCODER) ) { + filterVideoEncoderProfileOptions(); } } @@ -898,6 +910,20 @@ public class SettingsManager implements ListMenu.SettingsListener { } } + private void filterVideoEncoderProfileOptions() { + ListPreference videoEncoderProfilePref = + mPreferenceGroup.findPreference(KEY_VIDEO_ENCODER_PROFILE); + ListPreference videoEncoderPref = mPreferenceGroup.findPreference(KEY_VIDEO_ENCODER); + if ( videoEncoderProfilePref != null && videoEncoderPref != null ) { + String videoEncoder = videoEncoderPref.getValue(); + videoEncoderProfilePref.reloadInitialEntriesAndEntryValues(); + if ( filterUnsupportedOptions(videoEncoderProfilePref, + getSupportedVideoEncoderProfile(videoEncoder)) ) { + mFilteredKeys.add(videoEncoderProfilePref.getKey()); + } + } + } + private List getSupportedChromaFlashPictureSize() { StreamConfigurationMap map = mCharacteristics.get(getCurrentCameraId()).get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); @@ -1184,7 +1210,7 @@ public class SettingsManager implements ListMenu.SettingsListener { String resolutionFpsEncoder = key + ":" + profile.videoCodec; if (CameraSettings.VIDEO_ENCODER_BITRATE.containsKey(resolutionFpsEncoder)) { bitRate = CameraSettings.VIDEO_ENCODER_BITRATE.get(resolutionFpsEncoder); - } else if (CameraSettings.VIDEO_ENCODER_BITRATE.containsKey(key) ) { + } else if (CameraSettings.VIDEO_ENCODER_BITRATE.containsKey(key)) { bitRate = CameraSettings.VIDEO_ENCODER_BITRATE.get(key); } else { Log.i(TAG, "No pre-defined bitrate for "+key); @@ -1442,6 +1468,15 @@ public class SettingsManager implements ListMenu.SettingsListener { return modes; } + public List getSupportedVideoEncoderProfile(String videoEncoder) { + List profile = new ArrayList<>(); + profile.add("off"); + if ( VIDEO_ENCODER_PROFILE_TABLE.containsKey(videoEncoder) ) { + profile.addAll(VIDEO_ENCODER_PROFILE_TABLE.get(videoEncoder)); + } + return profile; + } + public boolean isHistogramSupport(){ String value = getValue(KEY_HISTOGRAM); return value != null && value.equals("enable"); diff --git a/src/com/android/camera/util/SettingTranslation.java b/src/com/android/camera/util/SettingTranslation.java index 6aee0ede0..2151f66e0 100644 --- a/src/com/android/camera/util/SettingTranslation.java +++ b/src/com/android/camera/util/SettingTranslation.java @@ -29,6 +29,7 @@ package com.android.camera.util; import android.hardware.camera2.CameraMetadata; +import android.media.MediaCodecInfo; import android.media.MediaRecorder; import java.util.HashMap; @@ -39,6 +40,7 @@ public class SettingTranslation { private static final TwoWayMap VIDEO_ENCODER_TABLE = new TwoWayMap(); private static final TwoWayMap AUDIO_ENCODER_TABLE = new TwoWayMap(); private static final TwoWayMap NOISE_REDUCTION_TABLE = new TwoWayMap(); + private static final TwoWayMap VIDEO_ENCODER_PROFILE_TABLE = new TwoWayMap(); static { VIDEO_ENCODER_TABLE.put("default", MediaRecorder.VideoEncoder.DEFAULT); @@ -69,6 +71,11 @@ public class SettingTranslation { NOISE_REDUCTION_TABLE.put("minimal", CameraMetadata.NOISE_REDUCTION_MODE_MINIMAL); NOISE_REDUCTION_TABLE.put("zero-shutter-lag", CameraMetadata .NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG); + + VIDEO_ENCODER_PROFILE_TABLE.put("HEVCProfileMain10", + MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10); + VIDEO_ENCODER_PROFILE_TABLE.put("HEVCProfileMain10HDR10", + MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10); } public static int getVideoEncoder(String key) { @@ -95,6 +102,14 @@ public class SettingTranslation { return NOISE_REDUCTION_TABLE.get(key); } + public static int getVideoEncoderProfile(String key) { + return VIDEO_ENCODER_PROFILE_TABLE.get(key); + } + + public static String getVideoEncoderProfile(int key) { + return VIDEO_ENCODER_PROFILE_TABLE.get(key); + } + private static class TwoWayMap { private Map strToInt = new HashMap<>(); private Map intToStr = new HashMap<>(); diff --git a/src/com/android/camera/util/VendorTagUtil.java b/src/com/android/camera/util/VendorTagUtil.java index 9c2f6cc1c..fb8aee010 100644 --- a/src/com/android/camera/util/VendorTagUtil.java +++ b/src/com/android/camera/util/VendorTagUtil.java @@ -28,6 +28,8 @@ */ package com.android.camera.util; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.util.Log; @@ -52,7 +54,8 @@ public class VendorTagUtil { private static CaptureRequest.Key ISO_EXP = new CaptureRequest.Key<>("org.codeaurora.qcamera3.iso_exp_priority.use_iso_exp_priority", Long.class); - + private static final CaptureRequest.Key HDRVideoMode = + new CaptureRequest.Key<>("org.quic.camera2.streamconfigs.HDRVideoMode", Byte.class); private static boolean isSupported(CaptureRequest.Builder builder, CaptureRequest.Key key) { @@ -62,6 +65,7 @@ public class VendorTagUtil { }catch(IllegalArgumentException exception){ supported = false; Log.d(TAG, "vendor tag " + key.getName() + " is not supported"); + exception.printStackTrace(); } if ( supported ) { Log.d(TAG, "vendor tag " + key.getName() + " is supported"); @@ -131,4 +135,23 @@ public class VendorTagUtil { return isSupported(builder, ISO_EXP); } + public static void setHDRVideoMode(CaptureRequest.Builder builder, byte mode) { + if ( isHDRVideoModeSupported(builder) ) { + builder.set(HDRVideoMode, mode); + } + } + + public static boolean isHDRVideoModeSupported(CaptureRequest.Builder builder) { + return isSupported(builder, HDRVideoMode); + } + + public static boolean isHDRVideoModeSupported(CameraDevice camera) { + try { + CaptureRequest.Builder builder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); + return isHDRVideoModeSupported(builder); + }catch(CameraAccessException exception) { + exception.printStackTrace(); + return false; + } + } } -- cgit v1.2.3