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.
Related
I am trying to develop an Android application that will take pictures in a service. Before implementing a service I am trying to implement the functionality on a button click. I've used code available on following locations
how to capture an image in background without using the camera application
However I am getting an excecption while executing Camera.takePicture() call. The LogCat shows following
12-10 14:46:56.135 589-18809/? E/QCameraStateMachine: int32_t qcamera::QCameraStateMachine::procEvtPreviewReadyState(qcamera_sm_evt_enum_t, void *): Error!! cannot handle evt(24) in state(1)
12-10 14:46:56.135 589-4574/? I/QCamera2HWI: [KPI Perf] static int qcamera::QCamera2HardwareInterface::pre_take_picture(struct camera_device *): X
12-10 14:46:56.135 589-4574/? E/QCamera2HWI: static int qcamera::QCamera2HardwareInterface::take_picture(struct camera_device *): pre_take_picture failed with ret = -38
12-10 14:46:56.135 589-4574/? I/QCameraHalWatchdog: Stopped Watchdog Thread (0ms)[take_picture]
I could not find any information on "cannot handle evt(24) in state(1)". Neither on "qcamera::QCamera2HardwareInterface::pre_take_picture(struct camera_device *): X"
I have not copied the code here since the code is already presnet in the link I've provided earlier
My min compile version is KitKat and I am using Motorola Lenovo.
Your help is highly appreciated.
Edit****
Here is the code
Camera.PictureCallback mCall = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "------ In onPictureTaken");
// decode the data obtained by the camera into a Bitmap
// display.setImageBitmap(photo);
Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0,
data.length);
}
};
...
Camera c = null;
try {
c = Camera.open();
SurfaceView sv = new SurfaceView(this);
SurfaceHolder holder = sv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
c.setPreviewDisplay(holder);
Camera.Parameters params = c.getParameters();
params.setJpegQuality(100);
c.setParameters(params);
c.startPreview();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
c.setPreviewDisplay(holder);
c.takePicture(null, null, mCall);
} catch (Exception e) {
Log.e(TAG, "---- problems with camera operation " + e.getMessage(), e);
e.printStackTrace();
Log.d(TAG, "------ 333333 ");
} finally {
if (c != null) {
c.stopPreview();
c.release();
}
}
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();
}
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());
}
}
I'm developing an image recognition app and would like the camera to focus automatically all the time. The folks at ZXing have solved this problem by calling autofocus() every few seconds, but on some cameras this doesn't focus smoothly, but zips to one end and refocuses. On my Alcatel 995, gingerbread 2.3.3 API level 10 phone, it actually makes an alarming click every time this happens.
This phone doesn't support FOCUS_MODE_CONTINUOUS_PICTURE. I tried using FOCUS_MODE_CONTINUOUS_VIDEO, which is supported, and it didn't work. I wrote a test app that captured every preview frame of the camera normally with a callback, but it didn't focus. I added a video recorder feature to the app, and when video is being recorded, the camera does autofocus all the time. But video recording takes away the ability to get a callback on each frame, I think. It's been discussed at
https://stackoverflow.com/questions/9477042/extract-video-frames-while-recording-the-video-on-android?rq=1
and
How to show real time filtered camera preview while recording videos?
Here is some of that test code:
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
Camera.Parameters parameters = mCamera.getParameters();
mCamera.setDisplayOrientation(90); // just get it right for testing
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
Log.d(TAG, String.format("Frame %d", mFrameNumber++)); // see the frames in the logcat
}
});
} catch (IOException exception) {
mCamera.release();
mCamera = null;
Log.d(TAG, "exception setting parameters");
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
Camera.Parameters parameters = mCamera.getParameters();
List<Size> previewSizes = parameters.getSupportedPreviewSizes();
Size previewSize = getOptimalPreviewSize(previewSizes, w, h);
parameters.setPreviewSize(previewSize.width, previewSize.height);
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
mCamera.setParameters(parameters);
mCamera.startPreview();
if (mRecordingVideo)
startVideo(mCamera, holder);
}
// derived from http://developer.android.com/guide/topics/media/camera.html#capture-video
private void startVideo(Camera camera, SurfaceHolder holder) {
camera.stopPreview(); // not specified in documentation but seems to be needed
camera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(camera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // No audio is recorded
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setOutputFile("/dev/null");
try {
mMediaRecorder.setPreviewDisplay(holder.getSurface());
mMediaRecorder.prepare();
} catch (IOException e) {
camera.release();
Log.d(TAG, "startVideo: Failed.");
e.printStackTrace();
}
mMediaRecorder.start();
}
If I set mRecordingVideo in the above code to start the video recorder, I gain autofocus but lose the per-preview-frame callbacks.
The Camera.Parameters class definition says that FOCUS_MODE_CONTINUOUS_VIDEO is "intended for video recording" but doesn't make plain that it doesn't work otherwise.
Is there anything else I can do to persuade continuous autofocus to work in a gingerbread phone without recording video? Have I missed something out?
Is this phone-specific? Do other phones continuous autofocus in this mode without recording video? I posted the source of a complete test app to Github if anyone would like to try it on their phone.
Someone kindly helped me out by testing this on another phone on another continent. Thanks very much, Colin!
It appears that the code above is correct and should cause the camera to focus properly.
This behaviour is phone-specific. The Alcatel 995 running 2.3.6 definitely does not focus in this mode without the video recorder running. A Samsung Galaxy Nexus (not sure which OS) running the same code does focus without the video recorder running.
try "setRecordingHint(true)" to the camera parameters
I'm developing on android, i want to do somethings with camera (process pixels's values), but just in background, is it possible to do it without surface view? just use a buffer to read pixels's values and do processing.
thanks for every one can help me
As of API-Level 11 the SurfaceTexture was added. With it a SurfaceView is no longer needed. I tested the following code with my Samsung Galaxy S3 Neo.
mCamera = Camera.open();
try {
mCamera.setPreviewTexture(new SurfaceTexture(10));
} catch (IOException e1) {
Log.e(Version.APP_ID, e1.getMessage());
}
Parameters params = mCamera.getParameters();
params.setPreviewSize(640, 480);
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
params.setPictureFormat(ImageFormat.JPEG);
mCamera.setParameters(params);
mCamera.startPreview();
mCamera.takePicture(null, null, null, new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(Version.APP_ID, "picture-taken");
}
});
I've been looking for an answer to this for a while. I found it there, copied here for convenience.
http://handycodeworks.com/?p=19
Basically, let's just create a dummy SurfaceView (it works even inside a Service), and use it for Camera functions.
SurfaceView view = new SurfaceView(this);
c.setPreviewDisplay(view.getHolder());
c.startPreview();
c.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);