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
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am recording a 40 sec video using custom Camera, but I want to get video's thumbnail at every 10 sec while recording it.
I also used the PreviewCallback but it will not work while recording due to unlock the camera.
I also tried with TextureView which is not working while switching camera. At the time of switching ,I called again surfaceCreated
surfaceCreated(SurfaceHolder holder) method as below:-
public void surfaceCreated(SurfaceHolder holder) {
CustomCameraUtils.releaseCamera(camera);
camera = Camera.open(currentCameraId);
try {
CustomCameraUtils.setUpCamera(camera, getWindowManager().getDefaultDisplay().getRotation(), currentCameraId);
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(preview);
camera.startPreview();
previewRunning = true;
} catch (Exception e) {
e.printStackTrace();
CustomCameraUtils.releaseCamera(camera);
camera = null;
}
}
CustomCameraUtils.setUpCamera(camera, getWindowManager().getDefaultDisplay().getRotation(), currentCameraId);
public static void setUpCamera(Camera c, int rotation, int currentCameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(currentCameraId, info);
int degree = 0;
switch (rotation) {
case Surface.ROTATION_0:
degree = 0;
break;
case Surface.ROTATION_90:
degree = 90;
break;
case Surface.ROTATION_180:
degree = 180;
break;
case Surface.ROTATION_270:
degree = 270;
break;
default:
break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// frontFacing
rotation = (info.orientation + degree) % 330;
rotation = (360 - rotation) % 360;
} else {
// Back-facing
rotation = (info.orientation - degree + 360) % 360;
}
c.setDisplayOrientation(rotation);
Camera.Parameters params = c.getParameters();
List<String> focusModes = params.getSupportedFlashModes();
if (focusModes != null) {
if (focusModes
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
}
params.setRotation(rotation);
}
CustomCameraUtils.releaseCamera(camera)
public static void releaseCamera(Camera camera) {
try {
if (camera != null) {
camera.setPreviewCallback(null);
camera.setErrorCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
} catch (Exception e) {
e.printStackTrace();
camera = null;
}
}
Try the following example:
https://github.com/googlesamples/android-Camera2Video
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
private void openCamera(int width, int height) {
if (!hasPermissionsGranted(VIDEO_PERMISSIONS)) {
requestVideoPermissions();
return;
}
final Activity activity = getActivity();
if (null == activity || activity.isFinishing()) {
return;
}
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
Log.d(TAG, "tryAcquire");
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
String cameraId = manager.getCameraIdList()[0];
// Choose the sizes for camera preview and video recording
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
if (map == null) {
throw new RuntimeException("Cannot get available preview/video sizes");
}
mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
width, height, mVideoSize);
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
configureTransform(width, height);
mMediaRecorder = new MediaRecorder();
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
activity.finish();
} catch (NullPointerException e) {
// Currently an NPE is thrown when the Camera2API is used but not supported on the
// device this code runs.
ErrorDialog.newInstance(getString(R.string.camera_error))
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera opening.");
}
}
So you can get the bitmap from mTextureView using mTextureView.getBitmap()
Retrieving the Bitmap from TextureView.
https://developer.android.com/reference/android/view/TextureView.html#getBitmap()
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.
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
}
}
`
I have a video recorder on my android app which works well. Most important piece of code is here:
protected void startRecording() throws IOException
{
mCamera.stopPreview();
mCamera.unlock();
mrec = new MediaRecorder();
mrec.setCamera(mCamera);
mrec.setAudioSource(MediaRecorder.AudioSource.MIC);
mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mrec.setOutputFile(Videopath);
mrec.setPreviewDisplay(surfaceHolder.getSurface());
mrec.prepare();
isRecording=true;
mrec.start();
}
//-------------------------------------------------------------
protected void stopRecording()
{
releaseOnExit();
mCamera = Camera.open();
mCamera.lock();
surfaceView = (SurfaceView) findViewById(R.id.surface_camera);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Parameters params = mCamera.getParameters();
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
try {
mCamera .setPreviewDisplay(surfaceHolder);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera .startPreview();
btnlistToggle.setEnabled(true);
}
//-------------------------------------------------------------
#Override
public void surfaceCreated(SurfaceHolder holder)
{
if (mCamera != null)
{
Parameters params = mCamera.getParameters();
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
try {
mCamera .setPreviewDisplay(holder);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera .startPreview();
}
else
{
Toast.makeText(getApplicationContext(), "Camera not available!", Toast.LENGTH_LONG).show();
VideoRecorderActivity.this.finish();
}
}
I have a video player on my app ,too. But when I play my recorded videos , video 90 degree rotates which isn't good for showing. I play my recorded video by KMplayer on windows But video has 90 degree rotation at there . And I must tell that I use SurfaceView for player. How can I resolve it?
It is necessary for me or for other users read this post.
Preview orientation depends on the orientation of the device and camera orientation.
Basically what you need is to calculate the orientation of the camera preview based on those conditions.
We need two help methods:
1 - Calculate the device orientation:
public int getDeviceOrientation(Context context) {
int degrees = 0;
WindowManager windowManager =
(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
int rotation = windowManager.getDefaultDisplay().getRotation();
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;
}
return degrees;
}
2 - Calculate Camera preview rotation:
public static int getPreviewOrientation(Context context, int cameraId) {
int temp = 0;
int previewOrientation = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
int deviceOrientation = getDeviceOrientation(context);
temp = cameraInfo.orientation - deviceOrientation + 360;
previewOrientation = temp % 360;
return previewOrientation;
}
At your code, before mediaRecorder.prepare();
int rotation = getPreviewOrientation(context, cameraId);
mediaRecorder.setOrientationHint(rotation);
To use those methods is required a context and the camera Id in use.
Get the camera Id for back camera:
public int getCamaraBackId(){
numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return i;
}
}
return -1 // Device do not have back camera !!!!???
}
Open camera with Camera.open(getCamaraBackId());
For more information see Android documentation
I know your issue,
Video use Media Recorder from Camera, so you need rotate Media Recorder. use below codes should be fixed your issue.
/**
*
* #param mMediaRecorder
* #return
*/
public static MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {
/**
* Define Orientation of video in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
switch (CustomCamera.current_orientation) {
case 0:
mMediaRecorder.setOrientationHint(90);
break;
case 90:
mMediaRecorder.setOrientationHint(180);
break;
case 180:
mMediaRecorder.setOrientationHint(270);
break;
case 270:
mMediaRecorder.setOrientationHint(0);
break;
}
return mMediaRecorder;
}
Should add before prepare() method :
// Step 5: Set the preview output
/**
* Define Orientation of image in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
CustomCamera.mMediaRecorder = Utils.rotateBackVideo(CustomCamera.mMediaRecorder);
CustomCamera.mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
Thank you
Use this for your MediaRecorder.
mrec.setOrientationHint(90);
Take a look at the documentation
mrec.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mrec.setOutputFile(Videopath);
mrec.setPreviewDisplay(surfaceHolder.getSurface());
mrec.setOrientationHint(90);
mrec.prepare();
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();