I'm working with camera2 and I'm showing a preview of my photo/video after longclick in my thumbnail. Also, I'm rotating it depending of which orientation the camera had when the picture was taken. For example, if I did a picture in 90º, my preview will be also rotated 90º.
Everything is working fine, I'm using a customContainer and there I'm using onLayout and OnMeasure to create my preview depending of the size of the screen, aspect ratio and orientation. It works fine with photos. My problem appear when I try to do the same with videos, they only work in 0º.
I tried to rotate the TextureView which contain my MediaPlayer but after this my onLayout become crazy and Itś impossible find a (l,t,r,b) combination to measure it correctly.
Here is my XML:
<?xml version="1.0" encoding="utf-8"?>
<com.android.camera.ui.common.ThumbnailContainer xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preview_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/rounded_rectangle_thumbnail_preview"
android:visibility="invisible">
<TextureView
android:id="@+id/show_video_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
<ImageView
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:visibility="invisible"
/>
</com.android.camera.ui.common.ThumbnailContainer>
Here is my Surface code:
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Log.i(TAG, "InicializoSurface. Width: " + width + " HEIGHT:" + height);
Log.i(TAG, "InicializoSurface. Width: " + mVideoView.getMeasuredWidth() + " HEIGHT:" + mVideoView.getMeasuredHeight());
Log.i(TAG, "View transform. Width: " + mVideoView.getWidth() + " HEIGHT:" + mVideoView.getHeight());
mMediaSurface = new Surface(mVideoView.getSurfaceTexture());
initializeMediaPlayer();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (mMediaPlayer != null) {
// Make sure we stop video and release resources when activity is destroyed.
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
//////////
private void initializeMediaPlayer(){
mMediaPlayer = new CustomMediaPlayer();
Uri uri = Uri.parse(mCameraDataAdapter.getList().get(0).getPath());
try {
mMediaPlayer.setDataSource(mActivity, uri);
mMediaPlayer.setSurface(mMediaSurface);
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(mMediaPlayer);
mMediaPlayer.setOnCompletionListener(mMediaPlayer);
} catch (IOException e) {
e.printStackTrace();
}
}
///////////
mVideoView.setVisibility(View.VISIBLE);
// mVideoView.setTranslationX(-200);
// mVideoView.setTranslationY(-200);
Log.i(TAG, "X: " + mVideoView.getX() + "Y: " + mVideoView.getY());
if (mVideoView.isAvailable()) {
onSurfaceTextureAvailable(mVideoView.getSurfaceTexture(), mVideoView.getWidth(), mVideoView.getHeight());
}
if (mMediaPlayer == null) {
initializeMediaPlayer();
}
// mMediaPlayer.mVideoHolder = mVideoView.getHolder();
// mMediaPlayer.setDisplay(mMediaPlayer.mVideoHolder);
if (mMediaPrepared) {
Log.i(TAG,"Comienzo Video");
mMediaPlayer.start();
}
Finally here is my onMeasure/OnLayout from my CustomView
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width;
int height;
int wantedWidth = 0;
int wantedHeight = 0;
if(mWidth == 0 && mHeight == 0 ){
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight =MeasureSpec.getSize(heightMeasureSpec);
}
width = mWidth;
height = mHeight;
if (mOrientation == 0 || mOrientation == 180) {
wantedWidth = width - (int)(mMargin * 2);
mVideo.measure(MeasureSpec.makeMeasureSpec(wantedWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (wantedWidth * mVideoAspectRatio), MeasureSpec.EXACTLY));
wantedHeight = (mViewTop.getLayoutParams().height) * 2 + (int) (wantedWidth * mAspectRatio);
} else {
Log.e(TAG, "Real Width = " + width + " real Height = " + height);
wantedHeight = width - 2 * mViewTop.getLayoutParams().height - (int)(mMargin * 2);
mVideo.measure(MeasureSpec.makeMeasureSpec(wantedHeight, MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec((int) (wantedHeight * mAspectRatio), MeasureSpec.EXACTLY));
//
wantedWidth =(int) (wantedHeight * mAspectRatio) ;
wantedHeight = width - (int)(mMargin * 2);
}
Log.e(TAG, "onMeasure: " + wantedWidth + "x" + wantedHeight);
setMeasuredDimension(MeasureSpec.makeMeasureSpec(wantedWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(wantedHeight, MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int w = getMeasuredWidth();
int h = getMeasuredHeight();
int viewHeight = mViewBottom.getMeasuredHeight();
int imageViewHeight = mImage.getMeasuredHeight();
int wantedHeight = 0;
// w = w - (int) (2 * mMargin);
if (mOrientation == 0 || mOrientation == 180) {
mVideo.layout(0,wantedHeight,w,wantedHeight + imageViewHeight);
}else{
mVideo.layout(viewHeight,0,r-viewHeight - (int) mMargin,w);
}
}
I have been looking in other post as Android MediaRecorder making rotated video and I saw that it's not possible to rotate the textureView, but I can't believe that I can rotate a image so easily and have to fight during this to rotate 90 degrees a video.