Consequences of deprecated Camera class - android

Changed my code from using deprecated Camera class to CameraDevice and now have the errors indicated ("<-- here"). What is the best alternative for replacing these parameters?
Looking at the documentation it seems that, at least for the orientation, a sensor is the appropriate option but that seems an overly complicated response.
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setDisplayOrientation(90); <-- here
mCamera.setPreviewDisplay(holder); <-- here
mCamera.startPreview(); <-- here
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
and
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview(); <-- here
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder); <-- here
mCamera.startPreview(); <-- here
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}

Related

MediaCodec's Persistent Input Surface unsupported by Camera2 Session?

I am writing an Android app that supports saving RAW/JPEG and records videos at the same time. I tried passing 4 surfaces when creating CameraCaptureSession: preview, 2x ImageSaver and 1x PersistentInputSurface created by MediaCodec#createPersistentInputSurface. By using persistent input surface, I intend to avoid a stoppage between 2 captures.
When creating the session it fails with:
W/CameraDevice-JV-0: Stream configuration failed due to: endConfigure:380: Camera 0: Unsupported set of inputs/outputs provided
Session 0: Failed to create capture session; configuration failed
I have tried taking out all other surfaces, leaving only the PersistentInputSurface, still fails.
#Override
public void onResume() {
super.onResume();
//Some other setups...
if (persistentRecorderSurface == null) {
persistentRecorderSurface = MediaCodec.createPersistentInputSurface();
}
startBackgroundThread();
startCamera();
if (mPreviewView.isAvailable()) {
configureTransform(mPreviewView.getWidth(), mPreviewView.getHeight());
} else {
mPreviewView.setSurfaceTextureListener(mSurfaceTextureListener);
}
if (mOrientationListener != null && mOrientationListener.canDetectOrientation()) {
mOrientationListener.enable();
}
}
private void createCameraPreviewSessionLocked() {
try {
SurfaceTexture texture = mPreviewView.getSurfaceTexture();
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface = new Surface(texture);
mPreviewRequestBuilder = mBackCameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mBackCameraDevice.createCaptureSession(Arrays.asList(
surface,
mJpegImageReader.get().getSurface(),
mRAWImageReader.get().getSurface(),
persistentRecorderSurface
), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(CameraCaptureSession session) {
synchronized (mCameraStateLock) {
if (mBackCameraDevice == null) {
return;
}
try {
setup3AControlsLocked(mPreviewRequestBuilder);
session.setRepeatingRequest(mPreviewRequestBuilder.build(),
mPreCaptureCallback, mBackgroundHandler);
mState = CameraStates.PREVIEW;
} catch (CameraAccessException | IllegalStateException e) {
e.printStackTrace();
return;
}
mSession = session;
}
}
#Override
public void onConfigureFailed(CameraCaptureSession session) {
showToast("Failed to configure camera.");
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
It'd be helpful to see the system log lines right before that error line to confirm, but most likely:
You need to actually tie the persistentRecorderSurface to a MediaRecorder or MediaCodec, and call prepare() on those, before you create the camera capture session.
Otherwise, there's nothing actually at the other end of the persistent surface, and the camera can't tell what resolution or other settings are required.
Also keep in mind that there are limits on how many concurrent outputs you can have from the camera, depending on its supported hardware level and capabilities. There is currently no requirement that a device must support your combination of outputs (preview, record, JPEG, RAW), unfortunately, so it's very likely many or all devices will still give you an error.

camera open in android studio

this is my code:
#TargetApi(9)
public void surfaceCreated(SurfaceHolder holder){
Log.e(TAG, "surfaceCreated");
mCamera = Camera.open(cameraID);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning){
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(300, 300);
mCamera.setParameters(p);
try{
mCamera.setPreviewDisplay(holder);
}catch (Exception e){
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
mCamera.takePicture(null, mPictureCallback, mPictureCallback);
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed");
//mCamera.stopPreview();
//mPreviewRunning = false;
//mCamera.release();
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
it fails in: mCamera.setParameters(p);
someone can help?
Your device does not support preview 300x300 pixels, that's why Cmaera.setParameters() fails. You can only call CameraParameters.setPreviewSize() for one of the sizes listed in CameraParameters.getSupportedPreviewSizes().
Few notes:
If your device has more than one camera, each has its own list of supported sizes; some sizes may be supported by both cameras, others are not.
In some rare cases, some devices may throw RuntimeException even if you choose one of sizes that is returned by getSupportedPreviewSizes(). These are platform bugs, you can keep a blacklist of such cases per model/platform. But in any case, don't forget to wrap setParameters() in try … catch and try to resolve the issue.
In some rare cases, some devices may not throw RuntimeException but simply ignore the preview size request (or some other parameter). Be prepared.
android.hardware.Camera class is deprecated. For devices with Android Lollipop (21) and higher, use the android.hardware.camera2 API.

CamcorderProfile.QUALITY_HIGH not working on specific device

I have the following method to start a camera preview and prepare a MediaRecorder
private boolean prepareVideoRecorder(){
// BEGIN_INCLUDE (configure_preview)
//mCamera = CameraHelper.getDefaultCameraInstance();
if(Utils.hasFrontCamera())
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
else
mCamera = Camera.open();
// We need to make sure that our preview and recording video size are supported by the
// camera. Query camera to find all the sizes and choose the optimal size given the
// dimensions of our preview surface.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes,
mSurfaceView.getWidth(), mSurfaceView.getHeight());
// Use the same size for recording profile.
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
profile.audioChannels = 2;
// profile.videoFrameWidth = optimalSize.width;
// profile.videoFrameHeight = optimalSize.height;
Log.e("Resolution ",profile.videoFrameWidth + " - "+profile.videoFrameHeight);
//profile.videoBitRate = 3000000;
//profile.videoFrameRate = 24;
// likewise for the camera object itself.
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
try {
// Requires API level 11+, For backward compatibility use {#link setPreviewDisplay}
// with {#link SurfaceView}
mCamera.setPreviewDisplay(mSurfaceView.getHolder());
if (Utils.isModeCameraLandScape(getActivity())) {
mCamera.setDisplayOrientation(ORIENTATIONS_LAND.get(Utils.getRotation(context)));
Log.e("IMAGE", "preCreateCamera land "+Utils.getRotation(context));
} else {
mCamera.setDisplayOrientation(ORIENTATIONS_PORT.get(Utils.getRotation(context)));
Log.e("IMAGE", "preCreateCamera port "+Utils.getRotation(context));
}
//mCamera.setDisplayOrientation(90);
} catch (IOException e) {
Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
return false;
}
// END_INCLUDE (configure_preview)
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC );
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
// Step 4: Set output file
String path = getVideoFile(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO).getAbsolutePath();
currentFile = path;
mMediaRecorder.setOutputFile(path);
mMediaRecorder.setOrientationHint(270);
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
i had to comment this because apparently in a specific device i had for tests ( and i assume it happens on others ) i couldnt see the video preview and i got a MediaRecorder - “start failed: -19”
// profile.videoFrameWidth = optimalSize.width;
// profile.videoFrameHeight = optimalSize.height;
My problem
When i set the
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
to
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
the camera doesnt seem to start the preview, and on the Log.e i get "E/Resolution: 1280 - 720", but from what i've seen on the specs of the device, it should only go up to 640 - 480
Do i need to set some other parameters?
Before setting the quality you have to check if the camera supports that quality.
I ran into this problem on a nexus 6p device when setting the QUALITY_HIGH on the MediaRecorder.
I found the issue to the setMaxDuration() method call caused MediaRecorder to crash with a value that was too high.

Is it necessary to call Camera.stopPreview() before MediaRecorder.start()?

I am having a basic Camera application using MediaRecorder. Application previews the video on TextureView and when button is clicked it starts recording. I works on most mobile phones, but on some specific device, underlying OMX fails:
(40b1df38) hardware/ti/omap4xxx/camera/OMXCameraAdapter/OMXCameraAdapter.cpp:2176 UseBuffersPreview - Exiting function UseBuffersPreview because of ret 0 eError=80001018
and in consequence, preview freezes and recording fails.
I found that this is most likely caused when Camera object is still previewing, while MediaRecorder object start recording. When I call mCamera.stopPreview() before starting recording, it works. Therefore, I have following questions:
1. Why is call to mCamera.stopPreview() necessary on some devices, and not on others?
2. How can the recorded video be still previewed, if stopPreview() on Camera object is called, but MediaRecorder.setPreviewDisplay() was not?
Below I present some code:
public boolean startRecording() throws IllegalStateException, IOException {
if (!mRecordingStarted) {
mMediaRecorder = new MediaRecorder();
try {
mCamera.stopPreview(); // !!! without this recording fails on some devices!
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setProfile(mCamProfile);
//mMediaRecorder.setPreviewDisplay(mSurfaceView.getHolder().getSurface());
mMediaRecorder.setOutputFile(mCaptureFile);
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStarted = true;
} catch (Exception e) {
mMediaRecorder.release();
mCamera.lock();
Log.e("ERROR", e.toString());
}
}
return mRecordingStarted;
}
private void startPreview() throws IllegalStateException, IOException {
if (mCamera == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
Camera.Parameters parameters = mCamera.getParameters();
mCamera.setDisplayOrientation(0);
mCamProfile = getConfiguredProfile();
mVideoSize = getBestPreviewSize(mCamProfile, parameters);
parameters.setPreviewSize(mVideoSize.width, mVideoSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
mCamera.setParameters(parameters);
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
mCamera.startPreview();
}

When using the Camera object, can I set it to make smaller pictures if needed?

In my app I have a SurfaceHolder and I use a camera to capture a photo:
private void initCamera() {
try {
camera = Camera.open();
if (camera == null) {
camera = openFrontFacingCamera();
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
My question is:
Can I set the camera to take smaller photos, in case I need it, instead of it taking the highest resolution possible photos?
Yes. Firstly determine supported resolutions and after that set to parameters the one you need:
Camera.Parameters p = camera.getParameters();
p.setRotation(90);
p.setJpegQuality(100);
List<Size> sizes = p.getSupportedPictureSizes();
for (int i=0;i<sizes.size();i++) {
Log.e("", "Size: " + sizes.get(i).width + " " + sizes.get(i).height);
}
//determine appropriate and set:
p.setPictureSize(sizes.get(0).width, sizes.get(0).height);

Categories

Resources