I want to capture image while recording video using camera2 API.
Two separate demos are available. 1. To capture image and 2. To record video
I tried to combine them into one app. But confused in many things. Like
- CameraDevice is single which representation of a single camera connected to an Android device.
- Different template needed in request. For image :
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
and for videomCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
- In createCaptureSession method surface of ImageReader is needed and for video MediaRecorder is needed.
CameraCaptureSession.StateCallback is needed in createCaptureSession method for both image and video.
And camera2 APIs are new. So no more examples available on Google.
Anyone has any idea about this? like how to capture photo while recording in android?
For camera2 API, and video snapshots, you'll need to improve the camera2video sample somewhat.
- 3 capture target Surfaces: Preview (a TextureView or SurfaceView), JPEG (an ImageReader), and recording (MediaRecorder or MediaCodec).
- Pass surfaces from all three to createCaptureSession
- When not recording video, set the repeating request to just target the preview
- When recording video, set the repeating request to target both preview and the recording Surface, and start the mediarecorder (as camera2video does); when stopping recording switch back to just targeting preview in the repeating request.
- When you want to take a picture, issue a single capture() call with a request that targets the JPEG surface, the preview surface, and if recording is active, the recording surface.
- Get the JPEG from the ImageReader when its onImageAvailable callback fires.
There is the full work example:
public class Camera2VideoImageActivity extends AppCompatActivity {
private static final String TAG = "Camera2VideoActivity";
private static final int STATE_PREVIEW = 0;
private static final int STATE_WAIT_LOCK = 1;
private int mCaptureState = STATE_PREVIEW;
private TextureView mTextureView;
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
connectCamera();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
mMediaRecorder = new MediaRecorder();
if(mIsRecording) {
try {
createVideoFileName();
} catch (IOException e) {
e.printStackTrace();
}
startRecord();
mMediaRecorder.start();
runOnUiThread(new Runnable() {
@Override
public void run() {
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
});
} else {
startPreview();
}
// Toast.makeText(getApplicationContext(),
// "Camera connection made!", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisconnected(CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
private HandlerThread mBackgroundHandlerThread;
private Handler mBackgroundHandler;
private String mCameraId;
private Size mPreviewSize;
private Size mVideoSize;
private Size mImageSize;
private ImageReader mImageReader;
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new
ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage()));
}
};
private class ImageSaver implements Runnable {
private final Image mImage;
public ImageSaver(Image image) {
mImage = image;
}
@Override
public void run() {
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mImageFileName)));
sendBroadcast(mediaStoreUpdateIntent);
if(fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private MediaRecorder mMediaRecorder;
private Chronometer mChronometer;
private int mTotalRotation;
private CameraCaptureSession mPreviewCaptureSession;
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new
CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult captureResult) {
switch (mCaptureState) {
case STATE_PREVIEW:
// Do nothing
break;
case STATE_WAIT_LOCK:
mCaptureState = STATE_PREVIEW;
Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
startStillCaptureRequest();
}
break;
}
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
process(result);
}
};
private CameraCaptureSession mRecordCaptureSession;
private CameraCaptureSession.CaptureCallback mRecordCaptureCallback = new
CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult captureResult) {
switch (mCaptureState) {
case STATE_PREVIEW:
// Do nothing
break;
case STATE_WAIT_LOCK:
mCaptureState = STATE_PREVIEW;
Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
startStillCaptureRequest();
}
break;
}
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
process(result);
}
};
private CaptureRequest.Builder mCaptureRequestBuilder;
private ImageButton mRecordImageButton;
private ImageButton mStillImageButton;
private boolean mIsRecording = false;
private boolean mIsTimelapse = false;
private File mVideoFolder;
private String mVideoFileName;
private File mImageFolder;
private String mImageFileName;
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private static class CompareSizeByArea implements Comparator<Size> {
@Override
public int compare(Size lhs, Size rhs) {
return Long.signum( (long)(lhs.getWidth() * lhs.getHeight()) -
(long)(rhs.getWidth() * rhs.getHeight()));
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera2_video_image);
createVideoFolder();
createImageFolder();
mChronometer = (Chronometer) findViewById(R.id.chronometer);
mTextureView = (TextureView) findViewById(R.id.textureView);
mStillImageButton = (ImageButton) findViewById(R.id.cameraImageButton2);
mStillImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!(mIsTimelapse || mIsRecording)) {
checkWriteStoragePermission();
}
lockFocus();
}
});
mRecordImageButton = (ImageButton) findViewById(R.id.videoOnlineImageButton);
mRecordImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mIsRecording || mIsTimelapse) {
mChronometer.stop();
mChronometer.setVisibility(View.INVISIBLE);
mIsRecording = false;
mIsTimelapse = false;
mRecordImageButton.setImageResource(R.mipmap.btn_video_online);
// Starting the preview prior to stopping recording which should hopefully
// resolve issues being seen in Samsung devices.
startPreview();
mMediaRecorder.stop();
mMediaRecorder.reset();
Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mVideoFileName)));
sendBroadcast(mediaStoreUpdateIntent);
} else {
mIsRecording = true;
mRecordImageButton.setImageResource(R.mipmap.btn_video_busy);
checkWriteStoragePermission();
}
}
});
mRecordImageButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mIsTimelapse =true;
mRecordImageButton.setImageResource(R.mipmap.btn_timelapse);
checkWriteStoragePermission();
return true;
}
});
}
@Override
protected void onResume() {
super.onResume();
startBackgroundThread();
if(mTextureView.isAvailable()) {
setupCamera(mTextureView.getWidth(), mTextureView.getHeight());
connectCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) {
if(grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(),
"Application will not run without camera services", Toast.LENGTH_SHORT).show();
}
if(grantResults[1] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(),
"Application will not have audio on record", Toast.LENGTH_SHORT).show();
}
}
if(requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if(mIsRecording || mIsTimelapse) {
mIsRecording = true;
mRecordImageButton.setImageResource(R.mipmap.btn_video_busy);
}
Toast.makeText(this,
"Permission successfully granted!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,
"App needs to save video to run", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
@Override
public void onWindowFocusChanged(boolean hasFocas) {
super.onWindowFocusChanged(hasFocas);
View decorView = getWindow().getDecorView();
if(hasFocas) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
private void setupCamera(int width, int height) {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for(String cameraId : cameraManager.getCameraIdList()){
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
CameraCharacteristics.LENS_FACING_FRONT){
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation();
mTotalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270;
int rotatedWidth = width;
int rotatedHeight = height;
if(swapRotation) {
rotatedWidth = height;
rotatedHeight = width;
}
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
mVideoSize = chooseOptimalSize(map.getOutputSizes(MediaRecorder.class), rotatedWidth, rotatedHeight);
mImageSize = chooseOptimalSize(map.getOutputSizes(ImageFormat.JPEG), rotatedWidth, rotatedHeight);
mImageReader = ImageReader.newInstance(mImageSize.getWidth(), mImageSize.getHeight(), ImageFormat.JPEG, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void connectCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
}
private void startRecord() {
try {
if(mIsRecording) {
setupMediaRecorder();
} else if(mIsTimelapse) {
setupTimelapse();
}
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
Surface recordSurface = mMediaRecorder.getSurface();
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
mCaptureRequestBuilder.addTarget(previewSurface);
mCaptureRequestBuilder.addTarget(recordSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mRecordCaptureSession = session;
try {
mRecordCaptureSession.setRepeatingRequest(
mCaptureRequestBuilder.build(), null, null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "onConfigureFailed: startRecord");
}
}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void startPreview() {
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
Log.d(TAG, "onConfigured: startPreview");
mPreviewCaptureSession = session;
try {
mPreviewCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(),
null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.d(TAG, "onConfigureFailed: startPreview");
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void startStillCaptureRequest() {
try {
if(mIsRecording) {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
} else {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
}
mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mTotalRotation);
CameraCaptureSession.CaptureCallback stillCaptureCallback = new
CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
try {
createImageFileName();
} catch (IOException e) {
e.printStackTrace();
}
}
};
if(mIsRecording) {
mRecordCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null);
} else {
mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void closeCamera() {
if(mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
if(mMediaRecorder != null) {
mMediaRecorder.release();
mMediaRecorder = null;
}
}
private void startBackgroundThread() {
mBackgroundHandlerThread = new HandlerThread("Camera2VideoImage");
mBackgroundHandlerThread.start();
mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
}
private void stopBackgroundThread() {
mBackgroundHandlerThread.quitSafely();
try {
mBackgroundHandlerThread.join();
mBackgroundHandlerThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) {
int sensorOrienatation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return (sensorOrienatation + deviceOrientation + 360) % 360;
}
private static Size chooseOptimalSize(Size[] choices, int width, int height) {
List<Size> bigEnough = new ArrayList<Size>();
for(Size option : choices) {
if(option.getHeight() == option.getWidth() * height / width &&
option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
if(bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizeByArea());
} else {
return choices[0];
}
}
private void createVideoFolder() {
File movieFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
mVideoFolder = new File(movieFile, "camera2VideoImage");
if(!mVideoFolder.exists()) {
mVideoFolder.mkdirs();
}
}
private File createVideoFileName() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "VIDEO_" + timestamp + "_";
File videoFile = File.createTempFile(prepend, ".mp4", mVideoFolder);
mVideoFileName = videoFile.getAbsolutePath();
return videoFile;
}
private void createImageFolder() {
File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
mImageFolder = new File(imageFile, "camera2VideoImage");
if(!mImageFolder.exists()) {
mImageFolder.mkdirs();
}
}
private File createImageFileName() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "IMAGE_" + timestamp + "_";
File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder);
mImageFileName = imageFile.getAbsolutePath();
return imageFile;
}
private void checkWriteStoragePermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
try {
createVideoFileName();
} catch (IOException e) {
e.printStackTrace();
}
if(mIsTimelapse || mIsRecording) {
startRecord();
mMediaRecorder.start();
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(this, "app needs to be able to save videos", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT);
}
} else {
try {
createVideoFileName();
} catch (IOException e) {
e.printStackTrace();
}
if(mIsRecording || mIsTimelapse) {
startRecord();
mMediaRecorder.start();
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.setVisibility(View.VISIBLE);
mChronometer.start();
}
}
}
private void setupMediaRecorder() throws IOException {
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(mVideoFileName);
mMediaRecorder.setVideoEncodingBitRate(1000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setOrientationHint(mTotalRotation);
mMediaRecorder.prepare();
}
private void setupTimelapse() throws IOException {
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
mMediaRecorder.setOutputFile(mVideoFileName);
mMediaRecorder.setCaptureRate(2);
mMediaRecorder.setOrientationHint(mTotalRotation);
mMediaRecorder.prepare();
}
private void lockFocus() {
mCaptureState = STATE_WAIT_LOCK;
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
try {
if(mIsRecording) {
mRecordCaptureSession.capture(mCaptureRequestBuilder.build(), mRecordCaptureCallback, mBackgroundHandler);
} else {
mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), mPreviewCaptureCallback, mBackgroundHandler);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
Create a video thumbnail for a video. May return null if the video is corrupt or the format is not supported.
private void makeVideoPreview() {
Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoAbsolutePath, MediaStore.Images.Thumbnails.MINI_KIND);
saveImage(thumbnail);
}
public void onClick(View v) {
// TODO Auto-generated method stub
// if(v == myButton)
// {
if (recording) {
// stop recording and release camera
// type.setVisibility(View.GONE);1
type.setText("");
myChronometer.stop();
myChronometer.setBase(SystemClock.elapsedRealtime());
// mediaRecorder.stop(); // stop the recording
releaseMediaRecorder(); // release the MediaRecorder object
//
myCamera.lock();
recording = false;
// "/sdcard/fivo_flim/" + "fivo_flim_"+video_no
// + ".mp4";
System.out.println("11111111111 "+SessionManager.getVideoCount(prefs1));
new UploadPicture(VideoScreen.this, mApi, "/", new File(
"/sdcard/record/" + "record"
+ SessionManager.getVideoCount(prefs1) + ".mp4"))
.execute();
SessionManager.saveVideoCount(prefs1,
SessionManager.getVideoCount(prefs1) + 1);
mWakeLock.release();
System.out.println("uuuuuuuuuuuuuuuuuu");
} else {
// Release Camera before MediaRecorder start
releaseCamera();
mWakeLock.acquire();
if (!prepareMediaRecorder()) {
Toast.makeText(
VideoScreen.this,
"Fail in PrepareCamera()!\n \n Please Insert SD Card or\n Restart your phone ",
Toast.LENGTH_LONG).show();
finish();
}
System.out.println("prepare media recorder");
try {
mediaRecorder.prepare();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Starting Media Recorder");
try {
mediaRecorder.start();
} catch (Exception e) {
// TODO: handle exception
System.out.println("exception is " + e);
}
type.setText("Recording...");
myChronometer.setBase(SystemClock.elapsedRealtime());
myChronometer.start();
recording = true;
myButton.setClickable(false);
try {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
myButton.setClickable(true);
}
}, 3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@SuppressLint({ "NewApi", "SdCardPath" })
private boolean prepareMediaRecorder() {
myCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
myCamera.setDisplayOrientation(90);
myCamera.unlock();
mediaRecorder.setCamera(myCamera);
mediaRecorder.setOrientationHint(90);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH));
File mediaStorageDir = new File("/sdcard/record/");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Logger.Debug("failed to create directory");
}
}
video_no=SessionManager.getVideoCount(prefs1);
mFiles.add("/sdcard/record/" + "record" + video_no
+ ".mp4");
mediaRecorder.setOutputFile("/sdcard/record/" + "record"
+ video_no + ".mp4");
video_no++;
mediaRecorder.setPreviewDisplay(myCameraSurfaceView.getHolder()
.getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
@SuppressLint("SdCardPath")
private void releaseMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
myCamera.lock();
}
}
private void releaseCamera() {
if (myCamera != null) {
myCamera.release();
myCamera = null;
}
}
}
To extend Eddy Talvala's answer (which I agree witch):
If you want to capture a single photo WHILE recording a video, you simply issue a single CaptureRequest only targeting the surface of an ImageReader.The repeating request of the video recording won't be stopped. With that you can take snapshots from a video being recorded.
I hope this helps, if you need some code samples I will post them when im home.
Try this mate:
public void takeSnapshot(CameraCaptureSession.CaptureCallback captureCallback) {
try {
//In case that we are in legacy
if (null == mCameraActivity || CameraSettings.isLegacyHardwareLevel())
return;
int captureTemplate = CameraDevice.TEMPLATE_VIDEO_SNAPSHOT;
final CaptureRequest.Builder captureBuilder;
captureBuilder = YourCameraDevice.createCaptureRequest(captureTemplate);
captureBuilder.addTarget(YourImageReader.getSurface());
//To get the right orientation we must to get it in base of the sensor position.
SensorOrientation = CameraManager.getCameraCharacteristics(mCameraId).get(
CameraCharacteristics.SENSOR_ORIENTATION);
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, SensorOrientation);
mCaptureSession.capture(captureBuilder.build(), captureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
来源:https://stackoverflow.com/questions/36174807/how-to-programmatically-take-photos-while-recording-video-using-camera2-api-in-a