Android: Getting Camera preview as tilted - android

I have made a custom Camera application. And i am getting a Tilted camera view. So i want to know the solution for a correct and a normal preview. I have used setDisplayOrientation() Method. But got no result. Searching for a answer that works.
The Compiling API is 2.3 GingerBread!
Thanks in advance.`
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
String TAG = "MyMsg";
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 {
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
Log.d(TAG, "Surface Creation started");
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("MyMsg", "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("MyMsg", "Error starting camera preview: " + e.getMessage());
}
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
`

Related

Front camera brightness get very low when start recording in custom camera

I'm working in a custom video recorder which contain both front and back camera. When i start recording in back camera no problem, when i start recording in front camera brightness of the camera reduced.
i have camera switch button to change front and back camera
int currentCameraId;
reverseCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCamera.stopPreview();
mCamera.release();
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
mCamera = Camera.open(currentCameraId);
setCameraDisplayOrientation(UnlVideoActivity.this, currentCameraId, mCamera);
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
mCamera.startPreview();
}
});
public void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
params.setRotation(rotation);
switch (rotation) {
case Surface.ROTATION_0:
Toast.makeText(UnlVideoActivity.this, "LAND", Toast.LENGTH_SHORT).show();
degrees = 0;
break;
case Surface.ROTATION_90:
Toast.makeText(UnlVideoActivity.this, "PORT", Toast.LENGTH_SHORT).show();
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
camera.startPreview();
}
by this way i switch the front camera when i start recoring the brightness came to low.
code for recording
private boolean prepareMediaRecorder() {
mCamera = getCameraInstance();
mediaRecorder = new MediaRecorder();
mediaRecorder.setOrientationHint(orientationHint);
mCamera.unlock();
mediaRecorder.setPreviewDisplay(mHolder.getSurface());
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
mediaRecorder.setPreviewDisplay(mCameraSurfaceView.getHolder().getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
You should try manipulating camera iso settings. As it will let camera capture more light and you might solve your issue.
Camera camera = Camera.open();
Camera.Parameters params =
camera.getParameters();
params.set("iso", "400");
camera.setParameters(params);
There can be more iso settings as 100,200,1000,auto etc
If you want to isolate this setting only for front cam then just manipulate it if the cam in action is front cam.
Do let me know if this changed anything for you.

Camera lags when orientation is changed

I am trying to create a camera preview using SurfaceView and it mostly works fine. I initialize the camera on onSurfaceCreated method and destroy it on onSurfaceDestroyed. Why are the above methods being called when the orientation of the device changes. Following is the surface view code.
#Override
public void surfaceCreated(SurfaceHolder holder) {
// Initialize the camera
initCamera();
Log.d("tags", "Camera Started!");
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.stopPreview();
camera.release();
}
Log.d("tags", "Camera destroyed!");
}
public void initCamera() {
if (camera == null) {
camera = Camera.open(); // Get's the first camera
}
try {
camera.setPreviewDisplay(sfHolder);
} catch (IOException err) {
err.printStackTrace();
}
// Set camera orientation
Activity activity = (Activity)this.getContext();
this.setCameraDisplayOrientation(activity);
camera.startPreview();
}
private void setCameraDisplayOrientation(Activity activity) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
Log.d("tag", "Result -- " + result);
boolean camNull = camera == null;
Log.d("tag", String.valueOf(camNull));
camera.setDisplayOrientation(result);
When I launch the application on my device, the preview starts as expected but when I change the orientation from portrait to landscape and vice versa, the preview hangs for a few seconds and the new preview is shown with the changed orientation.
According to the logs surface is being destroyed and created again when orientation changes and hence the camera is being re-initialized everytime orientation changes. How can I overcome this ? Am I doing anything wrong here ?

Custom Android Camera Application, Camera Preview Issue

the camera preview is showing a distorted image, which is elongated while in portrait mode and flattened while in landscape. I have already resized preview with a million techniques. Then I read somewhere it must be something with resizing the SurfaceView. But so far I have not found anything suitable.
This is my activity.java file:
public class CameraActivity extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
private FrameLayout preview;
private static final String TAG = "CameraActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
if (checkCameraHardware(getBaseContext())){
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera, CameraActivity.this);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
Log.d(TAG, "Camera Available");
return true;
} else {
Log.d(TAG, "No Camera Found");
return false;
}
}
/** A safe way to get an instance of the Camera object. */
public Camera getCameraInstance(){
Camera c = null;
try {
int i = Camera.getNumberOfCameras();
releaseCamera(); //in case camera is being accessed by any other app.
Log.d(TAG, "Number of Cameras "+i +"\n");
c = Camera.open(); // attempt to get a Camera instance
Log.d(TAG, "Camera Opened");
}
catch (Exception e){
Log.d(TAG, "Camera Can't Be Accessed");
}
return c; // returns null if camera is unavailable
}
#Override
protected void onPause() {
super.onPause();
releaseCamera(); // release the camera immediately on pause event
}
private void releaseCamera(){
if (mCamera != null){
//mCamera.setPreviewCallback(null);
mPreview.getHolder().removeCallback(mPreview);
mCamera.release(); // release the camera for other applications
}
}
This is my camera preview class:
#SuppressLint("ViewConstructor")
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private Size mPreviewSize;
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera, Activity activity) {
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
Camera.Parameters parameters = mCamera.getParameters();
List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
mPreviewSize = localSizes.get(0);
Log.d(TAG, "Width " + mPreviewSize.width);
Log.d(TAG, "Height " + mPreviewSize.height);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height );
requestLayout();
mCamera.setParameters(parameters);
//start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = -90; break;
case Surface.ROTATION_180: degrees = 0; break;
case Surface.ROTATION_270: degrees = -90; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
}
And this is my activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:baselineAligned="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraActivity" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight = "1"
/>
</LinearLayout>
Your SurfaceView (or TextureView) must have the same aspect ratio as your preview images, otherwise you will get the distortion that you describe.
FWIW, you may find it useful to work with my CWAC-Camera library, which offers a CameraFragment that handles a lot of this low-level stuff for you. It's still a work in progress, though.
You can find the camera preview width & height as soon as the camera instance is created, in onCreate. Then, choose layout_width and layout_height so that they fit into the preview FrameLayout and preserve the aspect ratio of the camera. You can use FrameLayout.addView(View, LayoutParams).
Not sure if anyone still reads this but I had the same problem and this answer fixed it.
I copy the code here just in case (I also editted it to match this example):
mCamera.Parameters parameters1 = mCamera.getParameters();
parameters1.setPreviewSize(getWidth(), getHeight());
mCamera.setParameters(parameters1);
add these lines just before this:
mCamera.startPreview();

Android Camera setDisplayOrientation does not work

i am working camera project in android.my problem is camera setDisplayOrientation method is not working and my camera preview on surface always landscape.i want to expected portrait camera preview on SurfaceView. I am using Samsung galaxy y (Android 2.3.5) and my activity code shown below:
import java.io.IOException;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
public class AndroidCamera extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;;
String stringPath = "/sdcard/samplevideo.3gp";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStartCameraPreview = (Button)findViewById(R.id.startcamerapreview);
Button buttonStopCameraPreview = (Button)findViewById(R.id.stopcamerapreview);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
buttonStartCameraPreview.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!previewing){
camera = Camera.open();
if (camera != null){
try {
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}});
buttonStopCameraPreview.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(camera != null && previewing){
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
}});
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
my problem shown blow figure:
Any one can help with any code or tutorial links and thanks for spending valuable your time
Finally i got solution and find camera preview surface view following code:
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private static boolean DEBUGGING = true;
private static final String LOG_TAG = "CameraPreviewSample";
private static final String CAMERA_PARAM_ORIENTATION = "orientation";
private static final String CAMERA_PARAM_LANDSCAPE = "landscape";
private static final String CAMERA_PARAM_PORTRAIT = "portrait";
protected Activity mActivity;
protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;
protected Camera.Size mPreviewSize;
protected Camera.Size mPictureSize;
public CameraPreview(Context context, Camera camera) {
super(context);
mActivity=(Activity)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("CameraView", "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 {
Camera.Parameters cameraParams = mCamera.getParameters();
boolean portrait = isPortrait();
configureCameraParameters(cameraParams, portrait);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("CameraView", "Error starting camera preview: " + e.getMessage());
}
}
public void onPause() {
mCamera.release();
mCamera = null;
}
protected void configureCameraParameters(Camera.Parameters cameraParams, boolean portrait) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { // for 2.1 and before
if (portrait) {
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_PORTRAIT);
} else {
cameraParams.set(CAMERA_PARAM_ORIENTATION, CAMERA_PARAM_LANDSCAPE);
}
} else { // for 2.2 and later
int angle;
Display display = mActivity.getWindowManager().getDefaultDisplay();
switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v(LOG_TAG, "angle: " + angle);
mCamera.setDisplayOrientation(angle);
}
cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
if (DEBUGGING) {
Log.v(LOG_TAG, "Preview Actual Size - w: " + mPreviewSize.width + ", h: " + mPreviewSize.height);
Log.v(LOG_TAG, "Picture Actual Size - w: " + mPictureSize.width + ", h: " + mPictureSize.height);
}
mCamera.setParameters(cameraParams);
}
public boolean isPortrait() {
return (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
}
}
It's need minimum sdk 2.3 or higher
if you want to rotate the preview output, try this:
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (isPreviewRunning)
{
mCamera.stopPreview();
}
Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
parameters.setPreviewSize(width, height);
}
if(display.getRotation() == Surface.ROTATION_180)
{
parameters.setPreviewSize(height, width);
}
if(display.getRotation() == Surface.ROTATION_270)
{
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
previewCamera();
}
For lower API levels you could use:
private void setCameraDisplayOrientationAPI8(){
//Sets the camera right Orientation.
//Special void for API 8 build.
//This void should be called before calling camera.setParameters(cameraParameters).
if (activeActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
{
camera.setDisplayOrientation(90);
}
if (activeActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
camera.setDisplayOrientation(180);
}
}
and just call setCameraDisplayOrientationAPI8(); on your surfaceChanged func.
plus:
private void setCameraDisplayOrientation() {
//Sets the camera right Orientation.
//IMPORTANT!! This code is available only for API Level 9 build or greater.
if (mApiLvl<9){
Log.d(TAG, "setCameraDisplayOrientation ERROR: This code is available only for API Level 9 build or greater.");
return;
}
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraIndex, info);
int rotation = activeActivity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
hope this helps.
Also, check if the "Auto-rotate Screen" option is checked in the phone Settings (Settings > Dislay or Screen - depends on the android version).
It took me quite a while till a figured it out. If it's not checked, the orientation of the camera in the app may be ignored.

MediaRecorder video capturing in portrait mode

I'm try to make custom video app. Iwork using settings in manifest 2.2 only (API 8).
All goes well but I don't understand why portrait mode video does not differ from lanscape one.
To make detection of device changed orientation I use this code within surfaceChanged()
if (mCamera != null) {
Camera.Parameters p = mCamera.getParameters();
try {
mCamera.stopPreview();
} catch (Exception e) {
// TODO: handle exception
}
int previewWidth = 0;
int previewHeight = 0;
if (mPreviewSize != null) {
Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
switch (rotation) {
case Surface.ROTATION_0:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(0);
break;
case Surface.ROTATION_180:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(270);
break;
case Surface.ROTATION_270:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
p.setPreviewSize(previewWidth, previewHeight);
mCamera.setParameters(p);
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Cannot start preview.", e);
}
}
Works like a charm. If I rotate device surface change orientation, calling surfaceChanged, where camera is set to appropriate DisplayRotation.
The question is how to determine later if the video captured either in lanscape mode or in portrait one. As I got all the videos are captured in landscape orientation. It does not depend of setDisplayOrientation which affect only preview process.
Also exploring the problem I noticed that if to use standard Camera app it writes special tag to video file (seen in MediaInfo): Rotation : 90 for the portrait captured videos.
But MediaRecorder class does not.
Seems that is the problem. Anybody got to solve this?
Found it !
Indeed, you can change the preview, you can tag the video, but there's no way to actually change the video... (maybe a speed issue or something)
camera.setDisplayOrientation(90);
To rotate the preview, then
recorder.setOrientationHint(90);
To tag the video as having a 90° rotation, then the phone will automatically rotate it when reading.
So all you have to do is
camera = Camera.open();
//Set preview with a 90° ortientation
camera.setDisplayOrientation(90);
camera.unlock();
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
recorder = new MediaRecorder();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
recorder.setOutputFile(getVideoFolder()+rnd.nextString()+".mp4");
recorder.setPreviewDisplay(holder.getSurface());
//Tags the video with a 90° angle in order to tell the phone how to display it
recorder.setOrientationHint(90);
if (recorder != null) {
try {
recorder.prepare();
} catch (IllegalStateException e) {
Log.e("IllegalStateException", e.toString());
} catch (IOException e) {
Log.e("IOException", e.toString());
}
}
recorder.start();
Hope it helps ;-)
camera.setDisplayOrientation(90) does not work in all devices. Following solution work perfectly in different devices and also handling marshmallow runtime permission.
See setCameraRotation method
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public static int rotate;
private Context mContext;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mContext = context;
}
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera preview
if (mCamera != null) {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
stopPreview();
// set preview size and make any resize, rotate or
// reformatting changes here
setCamera(camera);
// start preview with new settings
startPreview();
}
public void stopPreview(){
try {
if(mCamera != null)
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
e.printStackTrace();
}
}
public void startPreview(){
try {
if(mCamera != null) {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}else{
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " );
}
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
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.
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
/**
* add camera orientation and display rotation according to screen landscape or portrait
*/
setCameraRotation();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if(mCamera != null){
mCamera.release();
}
}
public void setCameraRotation() {
try {
Camera.CameraInfo camInfo = new Camera.CameraInfo();
if (VideoCaptureActivity.cameraId == 0)
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);
else
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, camInfo);
int cameraRotationOffset = camInfo.orientation;
// ...
Camera.Parameters parameters = mCamera.getParameters();
int rotation = ((Activity)mContext).getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break; // Natural orientation
case Surface.ROTATION_90:
degrees = 90;
break; // Landscape left
case Surface.ROTATION_180:
degrees = 180;
break;// Upside down
case Surface.ROTATION_270:
degrees = 270;
break;// Landscape right
}
int displayRotation;
if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
displayRotation = (cameraRotationOffset + degrees) % 360;
displayRotation = (360 - displayRotation) % 360; // compensate
// the
// mirror
} else { // back-facing
displayRotation = (cameraRotationOffset - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(displayRotation);
if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
rotate = (360 + cameraRotationOffset + degrees) % 360;
} else {
rotate = (360 + cameraRotationOffset - degrees) % 360;
}
parameters.set("orientation", "portrait");
parameters.setRotation(rotate);
mCamera.setParameters(parameters);
} catch (Exception e) {
}
}
}
Now prepare media recorder with correct rotation so that recorded video play in right orientation.
mediaRecorder.setOrientationHint(CameraPreview.rotate);
private boolean prepareMediaRecorder() {
mediaRecorder = new MediaRecorder();
mCamera.unlock();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOrientationHint(CameraPreview.rotate);
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
mediaRecorder.setOutputFile(filePath);
mediaRecorder.setMaxDuration(15000); // Set max duration 15 sec.
mediaRecorder.setMaxFileSize(10000000); // Set max file size 1M
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
releaseMediaRecorder();
return false;
} catch (IOException e) {
releaseMediaRecorder();
return false;
}
return true;
}
You can download complete sample https://github.com/umesh-kushwaha/Android_Video_Recording_portrait

Categories

Resources