Video Cropping Example

Today we will create an application which will display a video from the assets folder using TextureView and When a user touches the screen, TextureView will resize itself and video will be cropped to match the new size.

TextureView is used to display the content stream and it gives you ability to easily play and crop video. It is very similar to ImageView#setScaleType.

Follow the steps below and you will be able to display and crop the video by the end of this tutorial.

Step1: Create a new Android project in your android environment. Make sure to set your minSDKVersion to 14. (This code sample won’t give output as aimed below 14)

Step2: Get a .mp4 video and copy it to assets folder. (If using android studio to create assets folder into app/src/main)

Step3: Write the following into activity_main.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootView">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Actual Video Size"
android:textSize="18pt"
android:background="@android:color/darker_gray"/>

<TextureView
android:id="@+id/textureView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>

 

Step4: Write the following into your activity:

 

package com.example.videocroppingexample;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.FrameLayout;

import java.io.IOException;

public class MainActivity extends Activity implements TextureView.SurfaceTextureListener {

private static final String TAG = MainActivity.class.getName();

private static final String FILE_NAME = "kidssong.mp4";

private MediaPlayer mMediaPlayer;
private TextureView mTextureView;
private float mVideoWidth;
private float mVideoHeight;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

calculateVideoSize();
initView();
}

private void calculateVideoSize() {
try {
AssetFileDescriptor afd = getAssets().openFd(FILE_NAME);
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(
afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
String height = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
mVideoHeight = Float.parseFloat(height);
mVideoWidth = Float.parseFloat(width);

} catch (IOException e) {
Log.d(TAG, e.getMessage());
} catch (NumberFormatException e) {
Log.d(TAG, e.getMessage());
}
}
private void initView() {
mTextureView = (TextureView) findViewById(R.id.textureView);
mTextureView.setSurfaceTextureListener(this);

FrameLayout rootView = (FrameLayout) findViewById(R.id.rootView);
rootView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_UP:
updateTextureViewSize((int) motionEvent.getX(), (int) motionEvent.getY());
break;
}
return true;
}
});
}

private void updateTextureViewSize(int viewWidth, int viewHeight) {
float scaleX = 1.0f;
float scaleY = 1.0f;

if (mVideoWidth > viewWidth && mVideoHeight > viewHeight) {
scaleX = mVideoWidth / viewWidth;
scaleY = mVideoHeight / viewHeight;
} else if (mVideoWidth < viewWidth && mVideoHeight < viewHeight) {
scaleY = viewWidth / mVideoWidth;
scaleX = viewHeight / mVideoHeight;
} else if (viewWidth > mVideoWidth) {
scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight);
} else if (viewHeight > mVideoHeight) {
scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth);
}

int pivotPointX = viewWidth / 2;
int pivotPointY = viewHeight / 2;

Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY);

mTextureView.setTransform(matrix);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(viewWidth, viewHeight));
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
Surface surface = new Surface(surfaceTexture);

try {
AssetFileDescriptor afd = getAssets().openFd(FILE_NAME);
mMediaPlayer = new MediaPlayer();
mMediaPlayer
.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mMediaPlayer.setSurface(surface);
mMediaPlayer.setLooping(true);

mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});

} catch (IllegalArgumentException e) {
Log.d(TAG, e.getMessage());
} catch (SecurityException e) {
Log.d(TAG, e.getMessage());
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return true;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
}

 

Here we have written initView() and updateTextureViewSize() methods to handle resizing and cropping.

Step5: On running the app you will be able to do 2 actions I described at the start of this tutorial. Check the output below:

cropping1

On cropping it will look like below:

cropping2

Check my previous post on Android Wear 

Leave a Comment: