Using the following very simple camera preview activity (from a google example found here), the Nexus 4 camera is noticeably slower that the device's standard camera application:
public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView);
}
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
try {
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch (IOException ioe) {
// Something bad happened
}
}
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, Camera does all the work for us
}
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
return true;
}
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
}
}
I have been having issues with my application's camera speed on the Nexus 4, but I see this problem on no other devices. I was concerned that this was a Jelly Bean 4.2 difference, but Galaxy Nexus phones running JB4.2 work as normal with no lag. I realize this example code uses a TextureView, but other phones do not experience lag with this example.
Any help would be greatly appreciated.
I have found that the preview frame rate can be increased to a normal rate by setting the recording hint to true, but this severely decreases camera performance especially in medium to low light situations with regard to color saturation and contrast (I am shocked at the quality of the front facing camera given that this is Google's latest and greatest attempt to compete with the iPhone 5 and her quality cameras... can't wait for the X Phone).
This is not a solution to the problem, but it is something of a band-aid for developers looking to avoid shocking frame rates.
If you set the picture-size to 3264x2448, this will fix it. Even if you don't ever take a picture the picture-size is important because ZSL is enabled by default. The default picture size is 640x480 and this causes the slow preview frame rate. Disabling ZSL makes the preview even faster which is why setting the recording hit to true helps, enabling HDR does the same thing.
Related
I am having an issue with while switching GLSurfaceView. I have a GLSurfaceView (connected with Camera) and I want to move it to another view , but when I am moving it it's losing its frames and showing blackScreen after switching. and when I am reconnecting it to Camera, it starts show my Camera but with delay.
Could any one please tell me solution to move it to another parent without losing its frames (because when I am reconnecting it its showing frames with 2-3 seconds delay).
Please find code written below :
(Here VideoPanel (extends GLSurfaceView) is Frame provided by oovooSDK to show video)
final VideoPanel movingVideoView = parent1.getChildAt(0);
movingView.onPause();
parent1.removeView(movingView);
parent2.addView(movingView);
movingView.onResume();
movingView.requestRender();
for reconnecting :
application.unbindVideoPanel(videoView.userId, videoView.videoRender);
application.unbindVideoPanel(videoView.userId, videoView.videoRender);
// this methods shows delay of 2-3 seconds for binding view again
I tried following methods also
((VideoPanel) videoView.videoRender).setPreserveEGLContextOnPause(true);
// to save context when paused
((VideoPanel)videoView.videoRender).setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // to render frame again when requestRender is called
Camera is not proper release when your activity going to end.
If you are using a Surface view than release your camera in onSurfaceDestroy
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
Also recommend a release your camera if it's not ever going to use.
protected void onDestroy(){
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
I have a SurfaceView that holds a Camera Preview. I have set the camera focus mode to: Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO
and added an AutoFocus callback. When i run the app, i can see the camera adjusting its' focus in real time, but the autoFocusCallback only ever gets fired once, and when it does, it always returns the same value. (2.95) regardless of how close or far i am from an in focus object.
Wondering what i am doing wrong.. is it even possible to get real time info on what the actual focal length is?
my SurfaceView, onSurfaceChanged code:
SurfaceHolder.Callback surfaceHolderListener = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
camera=Camera.open();
try {
camera.setPreviewDisplay(previewHolder);
camera.setDisplayOrientation(90);
}
catch (Throwable e){ }
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Parameters params = camera.getParameters();
Rect centralFocusArea = new Rect();
centralFocusArea.set(holder.getSurfaceFrame().width()/2-10, holder.getSurfaceFrame().height()/2-10, holder.getSurfaceFrame().width()/2+10, holder.getSurfaceFrame().height()/2+10);
ArrayList<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
focusAreas.add(new Camera.Area(centralFocusArea, 1000));
//params.setPreviewSize(width, height);
params.setPictureFormat(PixelFormat.JPEG);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
// params.setFocusAreas(focusAreas);
camera.setParameters(params);
camera.startPreview();
camera.autoFocus(new AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
Log.v("CAMERA", "FOCUS CHANGE:"+camera.getParameters().getFocalLength());
camera.getParameters().setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
});
}
public void surfaceDestroyed(SurfaceHolder arg0)
{
camera.stopPreview();
camera.release();
}
};
Maybe you are confusing two different concepts: focus distance and focal length.
It seems you are interested in the focus distance, i.e. the distance for which the optical system has perfect focus; this depends on how far or close you are from in focus objects.
On the contrary, the focal length is an intrinsic property of the optical system (i.e. of the camera lenses), and it is fixed in most standard mobile devices (optical zoom capabilities are needed to have a variable focal length).
The value you get, 2.95, is the focal length (in mm) of your camera. Nexus 7 2013 tablets have such focal length.
Thus, it is perfectly normal that the function getFocalLength() always gives you the same value.
Most Android implementations do not provide a proper value for the focus distance, despite the parameter being well-defined in the Android specification. Some time ago, I checked three different cameras, and none of them provided useful information.
I have a custom Camera that works just fine,except for the implementation of flash that Iam using.I have tried using FLASH_MODE_AUTO in surfaceChanged.I have also tried using the following code using a Light Sensor:
SensorEventListener listener=new SensorEventListener(){
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//Not touching this with a ten foot pole
}
#Override
public void onSensorChanged(SensorEvent event) {
float lux=event.values[0];
Log.d(TAG, "The light sensor says: "+lux+" lux");
Camera.Parameters params=mCamera.getParameters();
cancelAutoFocus();
if(lux<50)
{
if(params.getFlashMode()!=Parameters.FLASH_MODE_ON)
params.setFlashMode(Parameters.FLASH_MODE_ON);
if(params.getExposureCompensation()!=params.getMinExposureCompensation())
params.setExposureCompensation(params.getMinExposureCompensation());
Log.d(TAG, "Exposure has been set to "+params.getMinExposureCompensation());
mCamera.setParameters(params);
}
else
{
params.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
}
}
};
Whatever I do,when I take a picture and the flash fires,my picture ends up looking like this:
However when I take a picture with the default Camera app,it looks ordinary,even a little dim.
I would like to get rid of this workaround using the Light Sensor entirely and use FLASH_MODE_AUTO.How can I get my camera to behave in low-light conditions and/or with the flash turned on?
Or is there any post-processing that I must do in order to ensure that the image is of lesser brightness.
I've searched all over on the web and I can't find out what that 1001 error is. A few seconds after that I get the camera 100 error but I can't find out what the first error is. Does anyone have any ideas?
I encountered this error as well on my S3. I believe I tracked it down to how the camera preview surface was used by the MediaRecorder. In my case the preview display was getting reset when I was attempting to start recording. I solved it by cleaning out my code and just used the calls to set, start and stop the preview display in the SurfaceView implementation below (from the Android Camera developer guide):
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
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();
} 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);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Just thought I would add a post here for future reference. This issue bothered me for a long time.
It turns out that my problem was caused by an incorrect preview size, although the resolution set was obtained from the getSupportedPictureSize method.
So for example you can get the sizes as follows:
//first entry in list is 1392x1392 for front facing camera on an S3
List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
Setting this resolution or neglecting to set a picture size alltogether will cause the dreaded error 1001.
If you encounter this on any other device I would recommend trying different picture sizes.
So there was another reason for why I got it on my Galaxy S3. I was using a TextureView to show my camera preview and got this dreaded error when pressing the home button after a successful preview and then entering the app again. In the onResume() function I started up the preview again and found that I had not released the SurfaceTexture instance variable in the onSurfaceTextureDestroyed() function.
I added the release line to this function and it now looks like this and works perfectly:
#Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mSurfaceTexture = null; //This was the offending culprit.
releaseMediaPlayer();
releaseVideoRecorder();
releaseCamera();
return false;
}
In my case, in Samsung S3, the video-size parameter was not set and this led to the 1001 error. Setting the video size on the media recorder using preview size fixed the issue. However, this change may fail on other devices since the parameter may or may not be available/set in all devices. The following code addresses most of the devices:
if(params.get("video-size") != null && params.get("video-size").isEmpty()) {
int videoWidth = params.getPreviewSize().width;
int videoHeight = params.getPreviewSize().height;
mediaRecorder.setVideoSize(videoWidth, videoHeight);
} else {
mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
}
i m trying to implement camera in my app but i found that the orientation preview is all time in landscape but my app is in portrait so i need it in to portrait mode i found some solutions about that like
mCamera.setDisplayOrientation(90);
its working good with Galaxy tab2 and htc but when i test it in sony xperia sola it display strange hear i add image screen of it
u can see that the preview of camera its display of right side of screen only
but when i take picture from this app it display ok. i don't no what is the problem
can anyone help me in this .
You can try to force the surface size (and position) - I followed this path to compensate a similar bug in 2.2 version of Samsung Galaxy S. The bug was fixed when the device upgraded to 2.3.
I solved this using the following code:
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
[...]
public void show(){
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
if (!showing) {
showing=true;
try {
mCamera = Camera.open();
aspectRatio();
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
mCamera.setDisplayOrientation(90);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), R.string.text_camera_open_error, Toast.LENGTH_SHORT).show();
}
}
}
private void aspectRatio(){
if (!aspect_radio_corrected){
aspect_radio_corrected=true;
Display default_disp=((Activity)getContext()).getWindowManager().getDefaultDisplay();
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size optimalPreviewSize=parameters.getPreviewSize();
FrameLayout.LayoutParams l_params=(FrameLayout.LayoutParams)getLayoutParams();
float ratio = (float) optimalPreviewSize.height / optimalPreviewSize.width;
l_params.width=default_disp.getWidth();
l_params.height=Math.round(l_params.width / ratio);
setLayoutParams(l_params);
requestLayout();
}
}
[...]
}
And on the layout file I have:
<com.socialcoaster.utils.CameraPreview
android:id="#+id/cameraView"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Seems that this is a bug related with the aspect ratio of the current preview size setup on camera and the surfaceView area to show it. You can see that by simply changing the values of aspectRatio() to some fixed values like 100.