summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByunghun Jeon <bjeon@codeaurora.org>2016-07-19 12:54:50 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-16 16:14:10 -0700
commitf75ea7ead9b0b13af757951e70b3376b3873cb53 (patch)
tree135023b4eb0efb813d3ab3029bae85f0dcb3f087
parent2fceef1ed0dfb3cb35062b6f6ebe8ca68e7bf87c (diff)
downloadandroid_packages_apps_Snap-f75ea7ead9b0b13af757951e70b3376b3873cb53.tar.gz
android_packages_apps_Snap-f75ea7ead9b0b13af757951e70b3376b3873cb53.tar.bz2
android_packages_apps_Snap-f75ea7ead9b0b13af757951e70b3376b3873cb53.zip
SnapdragonCamera: Add High Framerate Video capture
Add high framerate video capture. Only show supported options for current video size. CRs-Fixed: 1045405 Change-Id: Ib0dd7e63c167ead0fd734382d3ad4fdc7a64f8cc
-rw-r--r--assets/dependency.json7
-rw-r--r--res/xml/capture_preferences.xml9
-rw-r--r--src/com/android/camera/CaptureModule.java135
-rw-r--r--src/com/android/camera/CaptureUI.java1
-rw-r--r--src/com/android/camera/SettingsManager.java102
5 files changed, 226 insertions, 28 deletions
diff --git a/assets/dependency.json b/assets/dependency.json
index 390adcde4..39f9f91b0 100644
--- a/assets/dependency.json
+++ b/assets/dependency.json
@@ -53,5 +53,12 @@
"off":{},
"on":
{"pref_camera2_mpo_key":"on"}
+ },
+ "pref_camera2_video_time_lapse_frame_interval_key":
+ {
+ "default":
+ {"pref_camera2_hfr_key":"off"}
+ ,
+ "0":{}
}
}
diff --git a/res/xml/capture_preferences.xml b/res/xml/capture_preferences.xml
index 2f0849442..9ffe7d537 100644
--- a/res/xml/capture_preferences.xml
+++ b/res/xml/capture_preferences.xml
@@ -280,10 +280,19 @@
camera:entryValues="@array/pref_camera2_videosnap_entryvalues"
camera:key="pref_camera2_videosnap_key"
camera:title="@string/pref_camera2_videosnap_title" />
+
<ListPreference
camera:defaultValue="off"
camera:key="pref_camera2_trackingfocus_key"
camera:entries="@array/pref_camera2_trackingfocus_entries"
camera:entryValues="@array/pref_camera2_trackingfocus_entryvalues"
camera:title="@string/pref_camera2_trackingfocus_title"/>
+
+ <IconListPreference
+ camera:defaultValue="@string/pref_camera_hfr_default"
+ camera:entries="@array/pref_camera_hfr_entries"
+ camera:entryValues="@array/pref_camera_hfr_entryvalues"
+ camera:key="pref_camera2_hfr_key"
+ camera:singleIcon="@drawable/ic_settings_fps"
+ camera:title="@string/pref_camera_hfr_title" />
</PreferenceGroup>
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 899f40f7d..db0cef352 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -35,6 +35,7 @@ import android.graphics.RectF;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
@@ -62,6 +63,7 @@ import android.os.Message;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.util.Log;
+import android.util.Range;
import android.util.Size;
import android.view.Display;
import android.view.KeyEvent;
@@ -270,6 +272,10 @@ public class CaptureModule implements CameraModule, PhotoController,
private long mRecordingTotalTime;
private boolean mRecordingTimeCountsDown = false;
private ImageReader mVideoSnapshotImageReader;
+ private Range mHighSpeedFPSRange;
+ private boolean mHighSpeedCapture = false;
+ private boolean mHighSpeedCaptureSlowMode = false; //HFR
+ private int mHighSpeedCaptureRate;
private class MediaSaveNotifyThread extends Thread {
private Uri uri;
@@ -2160,35 +2166,78 @@ public class CaptureModule implements CameraModule, PhotoController,
mFrameProcessor.setOutputSurface(surface);
mFrameProcessor.setVideoOutputSurface(mMediaRecorder.getSurface());
addPreviewSurface(mPreviewBuilder, surfaces, cameraId);
- surfaces.add(mVideoSnapshotImageReader.getSurface());
+ if (!mHighSpeedCapture) surfaces.add(mVideoSnapshotImageReader.getSurface());
+ else mPreviewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mHighSpeedFPSRange);
- mCameraDevice[cameraId].createCaptureSession(surfaces, new CameraCaptureSession
- .StateCallback() {
+ if (!mHighSpeedCapture) {
+ mCameraDevice[cameraId].createCaptureSession(surfaces, new CameraCaptureSession
+ .StateCallback() {
- @Override
- public void onConfigured(CameraCaptureSession cameraCaptureSession) {
- Log.d(TAG, "StartRecordingVideo session onConfigured");
- mCurrentSession = cameraCaptureSession;
- try {
- setUpVideoCaptureRequestBuilder(mPreviewBuilder);
- mCurrentSession.setRepeatingRequest(mPreviewBuilder.build(), null, mCameraHandler);
- } catch (CameraAccessException e) {
- e.printStackTrace();
+ @Override
+ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
+ Log.d(TAG, "StartRecordingVideo session onConfigured");
+ mCurrentSession = cameraCaptureSession;
+ try {
+ setUpVideoCaptureRequestBuilder(mPreviewBuilder);
+ mCurrentSession.setRepeatingRequest(mPreviewBuilder.build(), null, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ mMediaRecorder.start();
+ mUI.clearFocus();
+ mUI.resetPauseButton();
+ mRecordingTotalTime = 0L;
+ mRecordingStartTime = SystemClock.uptimeMillis();
+ mUI.showRecordingUI(true);
+ updateRecordingTime();
}
- mMediaRecorder.start();
- mUI.clearFocus();
- mUI.resetPauseButton();
- mRecordingTotalTime = 0L;
- mRecordingStartTime = SystemClock.uptimeMillis();
- mUI.showRecordingUI(true);
- updateRecordingTime();
- }
- @Override
- public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
- Toast.makeText(mActivity, "Video Failed", Toast.LENGTH_SHORT).show();
- }
- }, null);
+ @Override
+ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ Toast.makeText(mActivity, "Video Failed", Toast.LENGTH_SHORT).show();
+ }
+ }, null);
+ } else {
+ mCameraDevice[cameraId].createConstrainedHighSpeedCaptureSession(surfaces, new
+ CameraConstrainedHighSpeedCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(CameraCaptureSession cameraCaptureSession) {
+ mCurrentSession = cameraCaptureSession;
+ CameraConstrainedHighSpeedCaptureSession session =
+ (CameraConstrainedHighSpeedCaptureSession) mCurrentSession;
+ try {
+ List list = session
+ .createHighSpeedRequestList(mPreviewBuilder.build());
+ session.setRepeatingBurst(list, null, mCameraHandler);
+ } catch (CameraAccessException e) {
+ Log.e(TAG, "Failed to start high speed video recording "
+ + e.getMessage());
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Failed to start high speed video recording "
+ + e.getMessage());
+ e.printStackTrace();
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Failed to start high speed video recording "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ mMediaRecorder.start();
+ mUI.clearFocus();
+ mUI.resetPauseButton();
+ mRecordingTotalTime = 0L;
+ mRecordingStartTime = SystemClock.uptimeMillis();
+ mUI.showRecordingUI(true);
+ updateRecordingTime();
+ }
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
+ Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
+ }
+ }, null);
+ }
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -2206,6 +2255,19 @@ public class CaptureModule implements CameraModule, PhotoController,
mUI.showTimeLapseUI(mCaptureTimeLapse);
}
+ private void updateHFRSetting() {
+ String value = mSettingsManager.getValue(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE);
+ if (value == null) return;
+ if (value.equals("off")) {
+ mHighSpeedCapture = false;
+ } else {
+ mHighSpeedCapture = true;
+ String mode = value.substring(0, 3);
+ mHighSpeedCaptureSlowMode = mode.equals("hsr");
+ mHighSpeedCaptureRate = Integer.parseInt(value.substring(3));
+ }
+ }
+
private void setUpVideoCaptureRequestBuilder(CaptureRequest.Builder builder) {
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest
@@ -2429,8 +2491,11 @@ public class CaptureModule implements CameraModule, PhotoController,
Log.d(TAG, "setUpMediaRecorder");
String videoSize = mSettingsManager.getValue(SettingsManager.KEY_VIDEO_QUALITY);
int size = CameraSettings.VIDEO_QUALITY_TABLE.get(videoSize);
- if (mCaptureTimeLapse)
+ if (mCaptureTimeLapse) {
size = CameraSettings.getTimeLapseQualityFor(size);
+ }
+ updateHFRSetting();
+ boolean hfr = mHighSpeedCapture && !mHighSpeedCaptureSlowMode;
mProfile = CamcorderProfile.get(cameraId, size);
int videoEncoder = SettingTranslation
@@ -2440,7 +2505,7 @@ public class CaptureModule implements CameraModule, PhotoController,
int outputFormat = MediaRecorder.OutputFormat.MPEG_4;
- if (!mCaptureTimeLapse) {
+ if (!mCaptureTimeLapse && !hfr) {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
}
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
@@ -2457,7 +2522,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
}
mMediaRecorder.setVideoEncoder(videoEncoder);
- if (!mCaptureTimeLapse) {
+ if (!mCaptureTimeLapse && !hfr) {
mMediaRecorder.setAudioEncodingBitRate(mProfile.audioBitRate);
mMediaRecorder.setAudioChannels(mProfile.audioChannels);
mMediaRecorder.setAudioSamplingRate(mProfile.audioSampleRate);
@@ -2467,7 +2532,21 @@ public class CaptureModule implements CameraModule, PhotoController,
if (mCaptureTimeLapse) {
double fps = 1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs;
mMediaRecorder.setCaptureRate(fps);
+ } else if (mHighSpeedCapture) {
+ mHighSpeedFPSRange = new Range(mHighSpeedCaptureRate, mHighSpeedCaptureRate);
+ int fps = (int) mHighSpeedFPSRange.getUpper();
+ mMediaRecorder.setCaptureRate(fps);
+ if (mHighSpeedCaptureSlowMode) {
+ mMediaRecorder.setVideoFrameRate(30);
+ } else {
+ mMediaRecorder.setVideoFrameRate(fps);
+ }
+
+ int scaledBitrate = mProfile.videoBitRate * fps / mProfile.videoFrameRate;
+ Log.i(TAG, "Scaled Video bitrate : " + scaledBitrate);
+ mMediaRecorder.setVideoEncodingBitRate(scaledBitrate);
}
+
Location loc = mLocationManager.getCurrentLocation();
if (loc != null) {
mMediaRecorder.setLocation((float) loc.getLatitude(),
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index dadbb3144..47a1a857c 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -111,6 +111,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
SettingsManager.KEY_WHITE_BALANCE,
SettingsManager.KEY_CAMERA2,
SettingsManager.KEY_FACE_DETECTION,
+ SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE,
SettingsManager.KEY_VIDEO_FLASH_MODE,
SettingsManager.KEY_VIDEO_DURATION,
SettingsManager.KEY_VIDEO_QUALITY,
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index ae46b9587..a3778b444 100644
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -115,6 +115,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
"pref_camera2_video_time_lapse_frame_interval_key";
public static final String KEY_FACE_DETECTION = "pref_camera2_facedetection_key";
public static final String KEY_AUTO_VIDEOSNAP_SIZE = "pref_camera2_videosnap_key";
+ public static final String KEY_VIDEO_HIGH_FRAME_RATE = "pref_camera2_hfr_key";
private static final String TAG = "SnapCam_SettingsManager";
private static SettingsManager sInstance;
@@ -128,6 +129,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
private boolean mIsMonoCameraPresent = false;
private boolean mIsFrontCameraPresent = false;
private JSONObject mDependency;
+ private int mCameraId;
private SettingsManager(Context context) {
mListeners = new ArrayList<>();
@@ -201,6 +203,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
@Override
public void onSettingChanged(ListPreference pref) {
String key = pref.getKey();
+ if (pref.getKey().equals(KEY_VIDEO_QUALITY)) buildHFR();
List changed = checkDependencyAndUpdate(key);
if (changed == null) return;
notifyListeners(changed);
@@ -219,6 +222,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
private void setLocalIdAndInitialize(int cameraId) {
mPreferences.setLocalId(mContext, cameraId);
+ mCameraId = cameraId;
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
PreferenceInflater inflater = new PreferenceInflater(mContext);
@@ -505,6 +509,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
ListPreference faceDetection = mPreferenceGroup.findPreference(KEY_FACE_DETECTION);
ListPreference makeup = mPreferenceGroup.findPreference(KEY_MAKEUP);
ListPreference trackingfocus = mPreferenceGroup.findPreference(KEY_TRACKINGFOCUS);
+ ListPreference hfr = mPreferenceGroup.findPreference(KEY_VIDEO_HIGH_FRAME_RATE);
if (whiteBalance != null) {
CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
@@ -591,6 +596,10 @@ public class SettingsManager implements ListMenu.SettingsListener {
if (!TrackingFocusFrameListener.isSupportedStatic())
removePreference(mPreferenceGroup, KEY_TRACKINGFOCUS);
}
+
+ if (hfr != null) {
+ buildHFR();
+ }
}
private void buildExposureCompensation(int cameraId) {
@@ -653,6 +662,86 @@ public class SettingsManager implements ListMenu.SettingsListener {
cameraIdPref.setEntries(entries);
}
+ private void buildHFR() {
+ ListPreference hfrPref = mPreferenceGroup.findPreference(KEY_VIDEO_HIGH_FRAME_RATE);
+
+
+ Size[] highSpeedVideoSize = getSupportedHighSpeedVideoSize(mCameraId);
+ if (highSpeedVideoSize.length == 0) {
+ CharSequence[] entryValues = new CharSequence[1];
+ CharSequence[] entries = new CharSequence[1];
+ entryValues[0] = "off";
+ entries[0] = "off";
+ hfrPref.setEntryValues(entryValues);
+ hfrPref.setEntries(entries);
+ hfrPref.setValueIndex(0);
+ return;
+ }
+
+ ListPreference videoQuality = mPreferenceGroup.findPreference(KEY_VIDEO_QUALITY);
+ String video = videoQuality.getValue();
+ int x = video.indexOf('x');
+ Size videoSize = new Size(Integer.parseInt(video.substring(0, x)),
+ Integer.parseInt(video.substring(x + 1)));
+
+ boolean found = false;
+ for (Size s : highSpeedVideoSize) {
+ if (videoSize.equals(s)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ CharSequence[] entryValues = new CharSequence[1];
+ CharSequence[] entries = new CharSequence[1];
+ entryValues[0] = "off";
+ entries[0] = "Off";
+ hfrPref.setEntryValues(entryValues);
+ hfrPref.setEntries(entries);
+ hfrPref.setValueIndex(0);
+ return;
+ }
+
+ Range[] range = getSupportedHighSpeedVideoFPSRange(mCameraId, highSpeedVideoSize[0]);
+ ArrayList<Range> list = new ArrayList<>();
+ for (Range r : range) {
+ if (r.getLower() == r.getUpper()) {
+ list.add(r);
+ }
+ }
+
+ if (list.size() == 0) {
+ CharSequence[] entryValues = new CharSequence[1];
+ CharSequence[] entries = new CharSequence[1];
+ entryValues[0] = "off";
+ entries[0] = "Off";
+ hfrPref.setEntryValues(entryValues);
+ hfrPref.setEntries(entries);
+ hfrPref.setValueIndex(0);
+ return;
+ }
+
+ CharSequence[] entryValues = new CharSequence[list.size() * 2 + 1];
+ CharSequence[] entries = new CharSequence[list.size() * 2 + 1];
+ entryValues[0] = "off";
+ entries[0] = "Off";
+ int i = 1;
+ for (Range r : list) {
+ entries[i] = "HFR " + r.getLower();
+ entryValues[i] = "hfr" + r.getLower();
+ i++;
+ }
+ for (Range r : list) {
+ entries[i] = "HSR " + r.getLower();
+ entryValues[i] = "hsr" + r.getLower();
+ i++;
+ }
+
+ hfrPref.setEntryValues(entryValues);
+ hfrPref.setEntries(entries);
+ }
+
private boolean removePreference(PreferenceGroup group, String key) {
for (int i = 0, n = group.size(); i < n; i++) {
CameraPreference child = group.get(i);
@@ -816,6 +905,18 @@ public class SettingsManager implements ListMenu.SettingsListener {
return res;
}
+ public Size[] getSupportedHighSpeedVideoSize(int cameraId) {
+ StreamConfigurationMap map = mCharacteristics.get(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ return map.getHighSpeedVideoSizes();
+ }
+
+ public Range[] getSupportedHighSpeedVideoFPSRange(int cameraId, Size videoSize) {
+ StreamConfigurationMap map = mCharacteristics.get(cameraId).get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ return map.getHighSpeedVideoFpsRangesFor(videoSize);
+ }
+
private List<String> getSupportedRedeyeReduction(int cameraId) {
int[] flashModes = mCharacteristics.get(cameraId).get(CameraCharacteristics
.CONTROL_AE_AVAILABLE_MODES);
@@ -983,6 +1084,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
JSONObject dependencyMap = getDependencyMapForKey(key);
if (dependencyMap == null) return null;
if (!dependencyMap.has(value)) value = "default";
+ if (!dependencyMap.has(value)) return null;
value = getDependencyKey(dependencyMap, value);
try {
return dependencyMap.getJSONObject(value);