android video orientation change after captureing video - android

When we will trying to record the video using MediaRecorder video is recorded properly in android and in device it will display as like recording, but when we can play video in VLC or other player in Desktop that time it will rotate the video and it will not display properly.
and i can set the MediaRecorder setOrientationHint to 90 degree.
what's the problem for changing the orientation and Why?

we Can not directly apply fix orientation while capturing video. I mean to say that you used fix 90 degree orientation in MediaRecorder setOrientationHint. you need to set setOrientationHint(dynamic degree);
First of all you need to get display rotation and get angle using display rotation. after then set That Degree to setOrientationHint method. That will work for all. Here is code.
Display display = getWindowManager().getDefaultDisplay();
int mDisplayRotation = display.getRotation();
public int getDisplayOrientationAngle() {
Log.e("", "setDisplayOrientationAngle is call");
int angle;
// switch (MeasurementNativeActivity.DisplayRotation) {
switch (mDisplayRotation) {
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("", "media recorder displayRotation: " + mDisplayRotation);
Log.v("", "media recorder angle: " + angle);
return angle;
}
mMediaRecorder.setOrientationHint(getDisplayOrientationAngle());

Extracted from the Android Documentation for MediaRecorder's setOrientationHint(int degrees) function:
This method will not trigger the source video frame to rotate during video recording, but to add a composition matrix containing the rotation angle in the output video if the output format is OutputFormat.THREE_GPP or OutputFormat.MPEG_4 so that a video player can choose the proper orientation for playback.
To sum it up, setOrientationHint just adds some sort of header to the video file that "tells" video players that they should rotate the video when playing it. In my experience, VLC player ignores this header and plays the video as it was recorded.
The only workaround I can think of would be to post-process the video by rotating it to your needs, although it seems quite a bad decision resource-wise.

Related

Camera orientation can not change with display in Android?

I know there are already questions like this, but none solved it. I took some help and figured out basic code that I need to change the camera with respect to the display.
cameraInfo=new Camera.CameraInfo();
camera.getCameraInfo(camId,cameraInfo);
int angle=0;
int rotation = getActivity().getWindowManager().getDefaultDisplay()
.getRotation();
switch(rotation)
{
case Surface.ROTATION_0:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 0");
camera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 90");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_180:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 180");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_270:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 270");
camera.setDisplayOrientation(180);
break;
default:
camera.setDisplayOrientation(0);
break;
}
}
However, I am unable to get the correct display preview with respect to the rotation of the device. I have tried several different combination of angles. However, none gave me the correct output. I am attaching the images of my preview. Please explain the solution to the problem. Moreover, I want to know what position of my device corresponds to angles 0,90,180, and 270. In other words, is 0 corresponds to portrait or landscape orientation?.
Images :
The landscape is inverted in this one. I tried setting the rotation by 180 when ROTATION_180. Doing so did not work out, as the other orientation (in landscape) became inverted
The upside down orientation does not do anything. The desired result is to bring the click button down with correct preview. I don't have any idea why this is not working. I have tried several values in each rotation, but none solved this issue.
I am a beginner, so please explain in detail. Thanks.
You should check CameraInfo.orientation for the device. Note that this property gives rotation from the natural display orientation, given for the device by Display.getRotation().
If your custom camera app uses android.hardware.camera2 API, this compensation will happen automatically.
If your custom camera activity does not lock the screen orientation, then it will be subject to "reverse landscape" glitch, and needs special treatment which involves OrientationEventListener.
You can rotate the image like this before preview:
public static Bitmap rotateImage(Bitmap bitmapSrc) {
Matrix matrix = new Matrix();
matrix.postRotate(previewRotation);
return Bitmap.createBitmap(bitmapSrc, 0, 0,
bitmapSrc.getWidth(), bitmapSrc.getHeight(), matrix, true);
}
"previewRotation" can be got from:
private static void setCameraDisplayOrientation(Context mContext, android.hardware.Camera.CameraInfo info) {
int rotation = ((CameraActivity) mContext).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;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
previewRotation = (info.orientation + degrees) % 360;
previewRotation = (360 - previewRotation) % 360; // compensate the mirror
} else { // back-facing
previewRotation = (info.orientation - degrees + 360) % 360;
}
mCameraInstance.setDisplayOrientation(previewRotation);
}

How rotation video to portrait when custom camera app?

I custom a camera app:
I set camera display portrait as:
mCamera.setDisplayOrientation(90);
Camera display portrait Ok, But file result (Video) not display portrait .
I try code:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(90);
mCamera.setParameters(parameters);
But it not ok.
Why ?
How fix this problem? Thanks.
Manual for setDisplayOrientation() says:
Set the clockwise rotation of preview display in degrees
and then
This does not affect the order of byte array passed in onPreviewFrame(byte[], Camera), JPEG pictures, or recorded videos.
You cannot rotate saved video stream, only preview.
here is a demo which work with both portrait and landscape see here
source
https://github.com/pikanji/CameraPreviewSample
demo
https://play.google.com/store/apps/details?id=net.pikanji.camerapreviewsample&hl=en
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

Correctly orient raw camera data

My camera app processes raw camera frames from onPreviewFrame() with OpenCV and then displays them on the screen. However, the raw frames are oriented the way the camera is mounted on the phone, which is usually not right-side up. To fix this, I rotate them manually with OpenCV, which is time-consuming.
I've looked into using setDisplayOrientation, but the documentation states that
This does not affect the order of byte array passed in onPreviewFrame
and I need the data to actually be right-side up, not just display right-side up. How can I correctly orient the raw camera data? If this is impossible, can I efficiently rotate the byte array passed to me in onPreviewFrame(), say by using OpenGL?
No, there's no way to get the API to do this for you, but to figure out how you need to rotate the data, take a look at the sample code at Camera.Parameters.setRotation. While setRotation() only affects JPEGs, you want to apply the exact same amount of rotation to the data you get in onPreviewFrame() as you would to the JPEGs.
Reproducing the sample code here, with minor changes:
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
mCameraOrientation = rotation; // Store rotation for later use
}
...
void onPreviewFrame(byte[] data, Camera camera) {
switch(mCameraOrientation) {
case 0:
// data is correctly rotated
break;
case 90:
// rotate data by 90 degrees clockwise
case 180:
// rotate data upside down
case 270:
// rotate data by 90 degrees counterclockwise
}
}
So you need to inherit from OrientationEventListener and override onOrientationChanged as above, and then use the calculated orientation value from there to rotate the preview frames when they come in.
setDisplayOrientation only rotates the camera vs. surface you are drawing into, if I recall correctly.
I believe you want to rotate the camera interpretation, what you may could achieve with setRotation

Is the setDisplayOrientation sample code correct?

The documentation page for Camera.setDisplayOrientation contains the following code sample stating that using it will "make the camera image show in the same orientation as the display":
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);
}
However, I had problems using it, sometimes the image would appear upside down. After some trial-and-error, I found that the correct code would be (replacing the last 8 lines of the method):
int result = (360 + info.orientation - degrees) % 360;
camera.setDisplayOrientation(result);
(Which means the calculation for back-facing cameras is correct for front cameras too.) The "compensate the mirror" comment is a bit weird since mirroring cannot be undone by rotating, that operation only swaps 90° and 270° rotations which doesn't really make sense to me.
So the question is: is the sample wrong indeed or am I missing something? I tried it on multiple devices, both back and front cameras and all supported orientations, so I know that my code IS working. One little detail that might be worth mentioning: all my devices returned 90° as info.orientation.
EDIT: Here is my camera-related code, I have tested it on a Nexus One and a Samsung Galaxy S Plus. It is used in my head-tracking 3D app, the preview is shown in the lower left corner and should always have the correct orientation.
SOLUTION (sort of): It looks like the code is correct, but my testing phone (Samsung Galaxy S Plus) returns an incorrect value for the front camera's CameraInfo.orientation. There are many related discussions about the preview being shown upside down on this model (examples here and here). A way to fix is to include an option to manually rotate the image.
The snippet you've quoted, which I used and applied in my project, is no problem in my circumstances.
For all the devices (Galaxy Note, Galaxy S III, Galaxy Nexus, Galaxy Ace II, Nexus S) I used for test, info.Orientation all return 270 on front camera, and 90 on back camera.
After a few discuss with the question raiser, I found I misunderstood the questions, so I divide the answer in two parts.
For the wrong orientation in camera preview, please refer to this solution:
Solution for wrong orientation in camera preview:
First please ensure info.Orientation will return 270 on front camera, 90 on back camera.
Then please try set your camera preview activity (or similar class that handles the preview) orientation to landscape.
Thus, when you go through the code, you'll find:
degree = 90 for screen orientation, info.Orientation = 270 for the front camera. Then you'll get result = (270 - 90 + 360) % 360, result = 180, which means it will rotate clock wise 180 for your front camera view that will correct the front camera upside-down issue.
Solution for wrong orientation in camera photo results:
If this info.Orientation applies to you, then the problem may be:
For some Samsung (or other) devices (Like Galaxy Note, Galaxy SIII), the camera will only write the Orientation Tag instead of rotate the real pixels.
If you're using the front camera and using the code above, it will display the preview with correct orientation, but will show u the "upside down" picture if you take the shot.
Solution:
/**
*
* Get the orientation from EXIF
 * #param filepath
 * #return orientation
 */
public int getExifOrientation(String filepath) {
int degree = 0;
ExifInterface exif = null;
try {
exif = new ExifInterface(filepath);
} catch (IOException ex) {
Log.e("EXIF info", "cannot read exif", ex);
}
if (exif != null) {
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
if (orientation != -1) {
// We only recognize a subset of orientation tag values.
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
}
} else {
degree = 1;
}
Log.i("EXIF info", "Orientation degrees: " + degree);
return degree;
}
Then
if (isFromCamera) {
if (fromFrontCam) {
// try change here if the orientation still wrong, -90 means rotate counter-clockwise 90 degrees.
matrix.preRotate(-90);
} else {
matrix.preRotate(90);
}
} else {
// read EXIF data
getExifOrientation(path)
// don't forget to handle the situation that some devices won't write exif data
matrix.preRotate(degree);
}

Captured video on Android won't rotate to portrait

I'm attempting to stream video using MediaRecorder on Android with the screen fixed to portrait mode (android:screenOrientation="portrait"). The camera hardware is naturally aligned to landscape mode. I can rotate the preview video display 90 degrees so the local preview displays correctly in portrait mode. However the captured video is still 90 degrees out:
Camera mCamera;
MediaRecorder mMediaRecorder;
...
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
Parameters params = mCamera.getParameters();
params.setRotation(90);
mCamera.setParameters(params);
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
The params.setRotation seems to have no effect whatsoever on the captured video. My target API is Android 2.2. My test hardware is Android 3.1.
Any ideas on how to rotate the captured video? Or is it not even possible?
Try using this:
mediaRecorder.setOrientationHint(rotation); // eg rotation=270
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

Categories

Resources