简体   繁体   中英

Playing video on TextureView taken from front camera

I record a video from Samsung Galaxy S4 (1080wx1920h) from FRONT CAMERA. The resulting video is rotated 90° and upside down. (See the picture)

视频结果

Then I take the video (final resolution 320wx240h) and I display it to TextureView with:

textureView.setRotation(90.0f);
textureView.setScaleX(-1);

and I set the layout parameters of the textureView to:

ViewGroup.LayoutParams params = textureView.getLayoutParams();
params.height = 1440;
params.width = 1080;
textureView.setLayoutParams(params);

The result looks like:

1080wx1440h

After several retries I figgured that if I set layout to:

params.height = 810;
params.width = 1080;

The dimensions ration remains correct:

810yx1080h

Finally I would like to display the video as it was recorded in RecordingActivity (1080wx1440h):

RecordingResolution

Any thoughts on how to accomplish this?

Or is there a way how to record the video from front camera in correct rotation?

Full activity code:

import android.app.Activity;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Surface;
import android.view.TextureView;
import android.view.ViewGroup;

public class ReplayActivity extends Activity  implements TextureView.SurfaceTextureListener {
    private String pathToVideo;
    private TextureView textureView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_replay);
        textureView = (TextureView)findViewById(R.id.texture_view);
        textureView.setSurfaceTextureListener(this);
        textureView.setRotation(90.0f);
        textureView.setScaleX(-1);
        pathToVideo = getIntent().getStringExtra("path");
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        MediaPlayer mediaPlayer = new MediaPlayer();
        mediaPlayer.setSurface(new Surface(surface));

        try {
            mediaPlayer.setDataSource(pathToVideo);

            mediaPlayer.prepare();

            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);//x = 1080, y = 1920

            Point videoDimensions = new Point(mediaPlayer.getVideoWidth(),mediaPlayer.getVideoHeight());//x = 320, y = 240
            Point resultParams = VideoHelpers.getScaledDimension(new Point(videoDimensions.y * 1000, videoDimensions.x * 1000), size);//x = 1080, y = 1440
            ViewGroup.LayoutParams params = textureView.getLayoutParams();
            params.height = resultParams.y;//1440
            params.width = resultParams.x;//1080
            textureView.setLayoutParams(params);
            mediaPlayer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {return false;}
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {}
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}
}

XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF0000">
    <TextureView
        android:id="@+id/texture_view"
        android:layout_width="wrap_content"
        android:background="#000000"
        android:layout_height="wrap_content" />
</RelativeLayout>

Playing with the camera, the previews, the textures, adn the matrix can be tricky.

Have in mind that the natural orientation of the camera is landscape, so if you dont do anything else, the resulting video will be in that orientation. Also, the preview frames will be landscape.

when you do textureView.setRotation(90.0f); and textureView.setScaleX(-1); you are only modifying the internal transformation matrix of the texture, this is, when something is drawed inside, a transformation occurs, and what you see is different of the actual content. This is fine, but actually the camera dont know anything about this rotation and neither the mediarecorder.

If you are using Mediarecorder You should take a look at

MediaRecorder.html#setOrientationHint(int)

Sets the orientation hint for output video playback. This method should be called before prepare(). 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. Note that some video players may choose to ignore the compostion matrix in a video during playback.

Parameters

degrees the angle to be rotated clockwise in degrees. The supported angles are 0, 90, 180, and 270 degrees.

If you are using other recording approach, probably you shold take a look at

Camera.Parameters.html#setRotation(int)

or

Camera.html#setDisplayOrientation(int)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM