The Problem: Certain Android devices (listed at the bottom of the question) exhibit unexpected behavior when utilizing the setOrientationHint(int degrees) function for videos taken with the front facing camera. The expected behavior is for the video to be rotated clockwise, but these devices rotate the video counterclockwise.
My Goal: To identify a variable within either the camera settings or hardware orientations that allows me to predictably know when this will occur. Specifically, I would like to avoid special casing these phones in my code!
Further Explanation: I am recording video using the standard MediaRecorder object, and in preparing for recording, I set the orientation of the video using setOrientationHint(). In the documentation for setOrientationHint(), the following is specified for the degrees parameter:
degrees –– the angle to be rotated clockwise in degrees. The supported angles are
0, 90, 180, and 270.
The function is intended to add a composition matrix containing the rotation angle so that a video player can display the video as intended. So, what I do is that I get the camera hardware's orientation using the CameraInfo class and use that as the degrees parameter in the setOrientationHint fn. (I have tried variation on this code using the AOSP as a guide, but I had the exact same result.)
A Real Example: The Samsung Galaxy S3 front-facing camera (and most others, in fact) will have a hardware orientation of 270, so I use this when recording, and the resulting video is displayed correctly. An HTC Vivid will similarly return a hardware orientation of 270 for the same camera, but will only be displayed correctly if I use 90 as the degrees parameter in the setOrientationHint fn. If I use the 270 of the hardware orientation like any other phone, the video will be upside down.
NB: The setOrientationHint() function includes a warning:
Note that some video players may choose to ignore the compostion
matrix in a video during playback.
However, this is not what is happening, because I can easily fix this issue on these phones if I fake it and put in 90 instead of 270.
Phones that I have seen specifically exhibit this issue: HTC Vivid (PH39100) running Android 4.0.3, HTC EVO 4G (PG86100) running Android 4.0.3, HTC Thunderbolt (ADR6400L) running Android 2.3.4. Notice that they are all HTC phones. Perhaps someone at HTC mistook clockwise for counterclockwise.
Yes, the HTC phones rotate in the wrong direction for the front facing cameras. Instead of trying to guess, I ended up adding a settings screen that would take two pictures with the second one rotating 90 degrees. Then the user could keep hitting next as I cycled through the different rotation direction and angle combinations until both pictures appeared oriented the same way.
Related
Shooting video with MediaRecorder class is good, shooting results in the phone, it was also ok, but uploaded to the computer to see the video,but it is rotated by 90 degrees. How to solve?
Usually, some vendor like samsung or sony... make their devices to record video in landscape mode. Maybe you record video in vertical orientation and review video after that on the laptop should be rotated by 90 degrees. I faced this issue in my project and the way to solve that is: detect the orientation by use the phone's sensor, after that use setOrientationHint(int degrees) method in MediaRecorder class to have a suitable orientation .
I have two devices, a Nexus 7 (Android 5) and a Galaxy S3 (4.3). On both devices I recorded a video in portrait mode and saved it with rotation hint 90 degrees. This is the correct orientation hint cause when played using the default media player the orientation is fine on both devices. I can even copy the video from the Nexus to the Galaxy and the orientation is still fine when I play the video file.
However, when I decode the video using the MediaCodec api I get some problems with the video rotation. When I display the video data I get from the MediaCodec the video on the Nexus is correct but on the Galaxy S3 the video is rotated by 90 degrees. My problem is that I have no clue what parameters on both devices differ so that I can decide why I have to rotate the video on the Galaxy but not on the Nexus!
On both devices the display rotation is 0 and the orientation is portrait:
int rotation = windowManager.getDefaultDisplay().getRotation();
int orientation = context.getResources().getConfiguration().orientation;
Is there another parameter I have to take into account?
Was there some api changes between 4.3 and 5 that affects the rotation of the decoded video? For example, is that video rotated automatically now?
I use opengl to display the video in case it matters...
Update: Solution
The problem was in the OpenGL transformation matrix that I get back from the MediaCodec. MediaCodec renders onto a SurfaceTexture and in case of the Nexus the transformation matrix of the SurfaceTexture is updated correctly, the Galaxy does not do that. When rendering the final output texture I used this matrix. To solve this I ignore the transformation matrix and rotate the video manually according to the recording hint.
I am trying to build a receipt scanning Android app and the way that I am handling really long receipts is to take multiple pictures and compile them into one long image. I tried doing image stitching with opencv but I ran into too many memory issues on older devices.
I am now running into the issue that with certain devices, specifically the Samsung Galaxy Player and Samsung Galaxy Tab 2, the preview and image capture orientation are not correct. The receipt needs to be scanned in portrait mode.
I have tried using this code to rotate the preview: http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation%28int%29
I added a line of code that rotates the camera by the same value that it rotates the preview.
On the Galaxy Player, this makes the preview display as still rotated but now flipped. The pictures that it returns are still rotated as if the camera was not rotated.
On the Galaxy Tab the preview displays correctly but the image that it creates is upside down.
Is there a way to detect the top and bottom of the image without saving it to file and getting the EXIF? Would that even make a difference on these devices or is there a deeper issue with those devices?
Thanks!
When using setOrientationHint for recording videos, Samsung and Motorola phones simply write this value into the Rotation Metadata.
However, it appears HTC phones do not write this value into the metadata and actually attempt to rotate the video after recording. The phones I have tried on Android 4.0.3 and lower actually rotate it 90 degrees no matter the value and the 4.0.4 phones rotate it as per the value.
Has anyone else noticed this behavior and what is the best way to fix this?
In my experience, there's nothing you can do to unify all devices. Some devices add metadata, some rotate the byte array, and some dismiss it altogether.
Another problem you have with metadata is that just as the recording devices differ, so do the playback devices, in Windows for example you might have noticed that jpeg metadata (EXIF) is ignored and all images are displayed landscape.
I would have hoped by now that the hardware manufacturers would have had certain hoops to jump through with regards to camera hardware but it seems that this is still a problem.
I have a server component that processes video uploads for a web/iOS/Android application.
However I am running into a problem handling the video orientation. Is there a good way to solve this? I have a tool MediaInfo that rips the meta data out of the device but this is what i am encountering
iOS
the portrait is correct 90 or 270
the landscape is crazy. if you hold the device with the button to the left, it reports 0 for the front camera and 180 for the back
Android
here the situation is reversed the landscape is correct both front and back camera
the portrait is 90 or 270 depending on if you are using the front or back camera
furthermore some devices like Motorola Droids and Evo4G dont record the meta data at all
has anyone seen a clean solution for this?
There is no clean solution for android devices that do not report the orientation.
For all the other orientations, I had overly complicated it in my mind. The flip between front and back means the angles are correct if rotated clockwise