diff options
author | Praveen Chavan <pchavan@codeaurora.org> | 2016-01-07 22:36:51 +0100 |
---|---|---|
committer | Daniel Hillenbrand <codeworkx@cyanogenmod.org> | 2016-01-07 13:45:38 -0800 |
commit | 3626f48bf1293ba1e8b15309df9a698a77fe786e (patch) | |
tree | 061c8b27a80c527db34272f79f7c42d7903f0a60 /src/com/android/camera/VideoModule.java | |
parent | 06ac71fabf96e0a6d6ef5b0a96f729b4a1c0e412 (diff) | |
download | android_packages_apps_Snap-3626f48bf1293ba1e8b15309df9a698a77fe786e.tar.gz android_packages_apps_Snap-3626f48bf1293ba1e8b15309df9a698a77fe786e.tar.bz2 android_packages_apps_Snap-3626f48bf1293ba1e8b15309df9a698a77fe786e.zip |
SnapdragonCamera: Add support for high-speed video recording
[1] Use combination of MediaRecorder.setCaptureRate and
setVideoFrameRate API to achieve HFR/HSR
------------------------------------------------------------
CaptureRate videoFrameRate Recorded-video
------------------------------------------------------------
120 30 slow-mo @30fps
120 120 high-speed-video @120fps
------------------------------------------------------------
Deprecate usage of custom fields added to media-profiles for
checking max-capabilities. Instead, introduce high-speed profiles
and advertize correct values (resolution, fps) to indicate
target capabilities.
Add conversion routines in CameraSettings to convert from
normal quality level to time-lapse/high-speed quality.
Also, add back 4KDCI and VGA support
TODO: Implement bitrate scaling if AOSP does not implement
in native.
Change-Id: Ic1d5ed8ef52348cab2383abe304056e0401f7069
Diffstat (limited to 'src/com/android/camera/VideoModule.java')
-rw-r--r-- | src/com/android/camera/VideoModule.java | 180 |
1 files changed, 119 insertions, 61 deletions
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 70cfba011..b9bf36d35 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -892,8 +892,35 @@ public class VideoModule implements CameraModule, mActivity.getString(R.string.pref_video_time_lapse_frame_interval_default)); mTimeBetweenTimeLapseFrameCaptureMs = Integer.parseInt(frameIntervalStr); mCaptureTimeLapse = (mTimeBetweenTimeLapseFrameCaptureMs != 0); - // TODO: This should be checked instead directly +1000. - if (mCaptureTimeLapse) quality += 1000; + + int hfrRate = 0; + String highFrameRate = mPreferences.getString( + CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE, + mActivity. getString(R.string.pref_camera_hfr_default)); + if (("hfr".equals(highFrameRate.substring(0,3))) || + ("hsr".equals(highFrameRate.substring(0,3)))) { + String rate = highFrameRate.substring(3); + Log.i(TAG,"HFR :" + highFrameRate + " : rate = " + rate); + try { + hfrRate = Integer.parseInt(rate); + } catch (NumberFormatException nfe) { + Log.e(TAG, "Invalid hfr rate " + rate); + } + } + + int mappedQuality = quality; + if (mCaptureTimeLapse) { + mappedQuality = CameraSettings.getTimeLapseQualityFor(quality); + } else if (hfrRate > 0) { + mappedQuality = CameraSettings.getHighSpeedQualityFor(quality); + Log.i(TAG,"NOTE: HighSpeed quality (" + mappedQuality + ") for (" + quality + ")"); + } + + if (CamcorderProfile.hasProfile(mCameraId, mappedQuality)) { + quality = mappedQuality; + } else { + Log.e(TAG,"NOTE: Quality " + mappedQuality + " is not supported ! Will use " + quality); + } mProfile = CamcorderProfile.get(mCameraId, quality); getDesiredPreviewSize(); qcomReadVideoPreferences(); @@ -909,8 +936,8 @@ public class VideoModule implements CameraModule, } private boolean is4KEnabled() { - if (mProfile.quality == CamcorderProfile.QUALITY_2160P /*|| - mProfile.quality == CamcorderProfile.QUALITY_4kDCI*/) { + if (mProfile.quality == CamcorderProfile.QUALITY_2160P || + mProfile.quality == CamcorderProfile.QUALITY_4KDCI) { return true; } else { return false; @@ -933,6 +960,32 @@ public class VideoModule implements CameraModule, } } + private boolean isSessionSupportedByEncoder(int w, int h, int fps) { + int expectedMBsPerSec = w * h * fps; + + List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders(); + for (VideoEncoderCap videoEncoder: videoEncoders) { + if (videoEncoder.mCodec == mVideoEncoder) { + int maxMBsPerSec = (videoEncoder.mMaxFrameWidth * videoEncoder.mMaxFrameHeight + * videoEncoder.mMaxFrameRate); + if (expectedMBsPerSec > maxMBsPerSec) { + Log.e(TAG,"Selected codec " + mVideoEncoder + + " does not support width(" + w + + ") X height ("+ h + + "@ " + fps +" fps"); + Log.e(TAG, "Max capabilities: " + + "MaxFrameWidth = " + videoEncoder.mMaxFrameWidth + " , " + + "MaxFrameHeight = " + videoEncoder.mMaxFrameHeight + " , " + + "MaxFrameRate = " + videoEncoder.mMaxFrameRate); + return false; + } else { + return true; + } + } + } + return false; + } + boolean isHFREnabled(int videoWidth, int videoHeight) { if ((null == mPreferences) || (null == mParameters)) { return false; @@ -942,7 +995,7 @@ public class VideoModule implements CameraModule, CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE, mActivity. getString(R.string.pref_camera_hfr_default)); - if(!("off".equals(HighFrameRate))) { + if (!("off".equals(HighFrameRate))) { Size size = null; try { if (isSupported(HighFrameRate.substring(3), mParameters.getSupportedVideoHighFrameRateModes())) { @@ -967,25 +1020,8 @@ public class VideoModule implements CameraModule, } int hfrFps = Integer.parseInt(HighFrameRate.substring(3)); - int inputBitrate = videoWidth * videoHeight * hfrFps; - - boolean supported = false; - List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders(); - for (VideoEncoderCap videoEncoder: videoEncoders) { -//TODO: How to handle HFRFrameWidth and HFRFrameHeight -/* if (videoEncoder.mCodec == mVideoEncoder) { - int maxBitrate = (videoEncoder.mMaxHFRFrameWidth * - videoEncoder.mMaxHFRFrameHeight * - videoEncoder.mMaxHFRMode); - if (inputBitrate > 0 && inputBitrate <= maxBitrate ) { - supported = true; - } - break; - } -*/ - } - return supported; + return isSessionSupportedByEncoder(videoWidth, videoHeight, hfrFps); } return false; @@ -1518,25 +1554,61 @@ public class VideoModule implements CameraModule, // Unlock the camera object before passing it to media recorder. mCameraDevice.unlock(); mMediaRecorder.setCamera(mCameraDevice.getCamera()); + String hfr = mParameters.getVideoHighFrameRate(); - if (!mCaptureTimeLapse && ((hfr == null) || ("off".equals(hfr)))) { - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); - mProfile.audioCodec = mAudioEncoder; - } else { - mProfile.audioCodec = -1; //not set + String hsr = mParameters.get(CameraSettings.KEY_VIDEO_HSR); + Log.i(TAG,"NOTE: hfr = " + hfr + " : hsr = " + hsr); + + int captureRate = 0; + boolean isHFR = (hfr != null && !hfr.equals("off")); + boolean isHSR = (hsr != null && !hsr.equals("off")); + + try { + captureRate = isHFR ? Integer.parseInt(hfr) : + isHSR ? Integer.parseInt(hsr) : 0; + } catch (NumberFormatException nfe) { + Log.e(TAG, "Invalid hfr(" + hfr + ") or hsr(" + hsr + ")"); } mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mProfile.videoCodec = mVideoEncoder; + mProfile.audioCodec = mAudioEncoder; mProfile.duration = mMaxVideoDurationInMs; - mMediaRecorder.setProfile(mProfile); + // Set params individually for HFR case, as we do not want to encode audio + if ((isHFR || isHSR) && captureRate > 0) { + mMediaRecorder.setOutputFormat(mProfile.fileFormat); + mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate); + mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate); + mMediaRecorder.setVideoEncoder(mProfile.videoCodec); + } else { + if (!mCaptureTimeLapse) { + mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); + } + + mMediaRecorder.setProfile(mProfile); + } + mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight); mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs); if (mCaptureTimeLapse) { double fps = 1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs; setCaptureRate(mMediaRecorder, fps); + } else if (captureRate > 0) { + Log.i(TAG, "Setting capture-rate = " + captureRate); + mMediaRecorder.setCaptureRate(captureRate); + // for HFR, encoder's target-framerate = capture-rate + if (isHSR) { + Log.i(TAG, "Setting fps = " + captureRate + " for HSR"); + mMediaRecorder.setVideoFrameRate(captureRate); + } + // for HFR, encoder's taget-framerate = 30fps (from profile) + if (isHFR) { + Log.i(TAG, "Setting fps = 30 for HFR"); + mMediaRecorder.setVideoFrameRate(30); + } + // TODO : bitrate correction..check with google } setRecordLocation(); @@ -2181,6 +2253,7 @@ public class VideoModule implements CameraModule, private void qcomSetCameraParameters(){ // add QCOM Parameters here // Set color effect parameter. + Log.i(TAG,"NOTE: qcomSetCameraParameters " + videoWidth + " x " + videoHeight); String colorEffect = mPreferences.getString( CameraSettings.KEY_VIDEOCAMERA_COLOR_EFFECT, mActivity.getString(R.string.pref_camera_coloreffect_default)); @@ -2286,18 +2359,21 @@ public class VideoModule implements CameraModule, String HighFrameRate = mPreferences.getString( CameraSettings.KEY_VIDEO_HIGH_FRAME_RATE, mActivity. getString(R.string.pref_camera_hfr_default)); - if (("hfr".equals(HighFrameRate.substring(0,3))) || - ("hsr".equals(HighFrameRate.substring(0,3)))) { + boolean isHFR = "hfr".equals(HighFrameRate.substring(0,3)); + boolean isHSR = "hsr".equals(HighFrameRate.substring(0,3)); + + if (isHFR || isHSR) { String hfrRate = HighFrameRate.substring(3); - if ("hfr".equals(HighFrameRate.substring(0,3))) { + if (isHFR) { mUnsupportedHFRVideoSize = true; } else { mUnsupportedHSRVideoSize = true; } String hfrsize = videoWidth+"x"+videoHeight; - Log.v(TAG, "current set resolution is : "+hfrsize); + Log.v(TAG, "current set resolution is : "+hfrsize+ " : Rate is : " + hfrRate ); try { Size size = null; + Log.i(TAG,"supported rate = " + mParameters.getSupportedVideoHighFrameRateModes()); if (isSupported(hfrRate, mParameters.getSupportedVideoHighFrameRateModes())) { int index = mParameters.getSupportedVideoHighFrameRateModes().indexOf( hfrRate); @@ -2305,7 +2381,7 @@ public class VideoModule implements CameraModule, } if (size != null) { if (videoWidth <= size.width && videoHeight <= size.height) { - if ("hfr".equals(HighFrameRate.substring(0,3))) { + if (isHFR) { mUnsupportedHFRVideoSize = false; } else { mUnsupportedHSRVideoSize = false; @@ -2318,35 +2394,16 @@ public class VideoModule implements CameraModule, } int hfrFps = Integer.parseInt(hfrRate); - int inputBitrate = videoWidth*videoHeight*hfrFps; - - //check if codec supports the resolution, otherwise throw toast - List<VideoEncoderCap> videoEncoders = EncoderCapabilities.getVideoEncoders(); - for (VideoEncoderCap videoEncoder: videoEncoders) { - if (videoEncoder.mCodec == mVideoEncoder){ -/* TODO: - int maxBitrate = (videoEncoder.mMaxHFRFrameWidth * - videoEncoder.mMaxHFRFrameHeight * - videoEncoder.mMaxHFRMode); - if (inputBitrate > maxBitrate ) { - Log.e(TAG,"Selected codec "+mVideoEncoder+ - " does not support HFR " + HighFrameRate + " with "+ videoWidth - + "x" + videoHeight +" resolution"); - Log.e(TAG, "Codec capabilities: " + - "mMaxHFRFrameWidth = " + videoEncoder.mMaxHFRFrameWidth + " , " + - "mMaxHFRFrameHeight = " + videoEncoder.mMaxHFRFrameHeight + " , " + - "mMaxHFRMode = " + videoEncoder.mMaxHFRMode); - if ("hfr".equals(HighFrameRate.substring(0,3))) { - mUnsupportedHFRVideoSize = true; - } else { - mUnsupportedHSRVideoSize = true; - } - } - break; -*/ + + if (!isSessionSupportedByEncoder(videoWidth, videoHeight, hfrFps)) { + if (isHFR) { + mUnsupportedHFRVideoSize = true; + } else { + mUnsupportedHSRVideoSize = true; } } - if ("hfr".equals(HighFrameRate.substring(0,3))) { + + if (isHFR) { mParameters.set(CameraSettings.KEY_VIDEO_HSR, "off"); if (mUnsupportedHFRVideoSize) { mParameters.setVideoHighFrameRate("off"); @@ -2496,6 +2553,7 @@ public class VideoModule implements CameraModule, forceFlashOffIfSupported(!mPreviewFocused); videoWidth = mProfile.videoFrameWidth; videoHeight = mProfile.videoFrameHeight; + String recordSize = videoWidth + "x" + videoHeight; Log.e(TAG,"Video dimension in App->"+recordSize); if (CameraUtil.isSupported(mParameters, "video-size")) { |