I am working on Panning and cropping the landscape video using Texture View.I am in a half way that I can pan the landscape video from left to right vice versa by using this example
https://github.com/crust87/Android-VideoCropView.
FFMPEG can crop the particular portion of the video by using this command
ffmpeg -i /sdcard/videokit/in.mp4 -filter:v crop=720:1088:0:0 -c:a
copy /sdcard/videokit/out.mp4
How can I crop only the video which is visible in Texture View and save it local storage in Android.
crop=720:1088:0:0 is a hard coded width and height of the video and it is cropping fine.But how can I get the width and height of the visible video in Texture View to crop the visible video and Save it to the local storage in android.
public class MainActivity extends Activity {
// Layout Components
private FrameLayout top_frame;
// Attributes
private String originalPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.check);
top_frame = (FrameLayout)findViewById(R.id.top_frame);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1000 && resultCode == RESULT_OK) {
final VideoCropView mVideoCropView = new VideoCropView(this);
mVideoCropView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mVideoCropView.start();
}
});
top_frame.addView(mVideoCropView);
Uri selectedVideoUri = data.getData();
originalPath = getRealPathFromURI(selectedVideoUri);
mVideoCropView.setVideoURI(selectedVideoUri);
mVideoCropView.seekTo(1);
}
}
public void onButtonLoadClick(View v) {
top_frame.removeAllViews();
Intent lIntent = new Intent(Intent.ACTION_PICK);
lIntent.setType("video/*");
lIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(lIntent, 1000);
}
public String getRealPathFromURI(Uri contentUri) { // getting image path from gallery.
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = getApplicationContext().getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
CropVideoView
public class VideoCropView extends TextureView implements MediaPlayerControl {
// Constants
private static final String LOG_TAG = "VideoCropView";
private static final int STATE_ERROR = -1;
private static final int STATE_IDLE = 0;
private static final int STATE_PREPARING = 1;
private static final int STATE_PREPARED = 2;
private static final int STATE_PLAYING = 3;
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
// MediaPlayer Components
protected Context mContext;
private MediaPlayer mMediaPlayer;
private Surface mSurface;
private OnInfoListener mOnInfoListener;
private OnCompletionListener mOCompletionListener;
private OnErrorListener mOnErrorListener;
private OnPreparedListener mOnPreparedListener;
private OnTranslatePositionListener mOnTranslatePositionListener;
// CropView Components
private Matrix mMatrix;
// MediaPlayer Attributes
protected Uri mUri;
private int mCurrentBufferPercentage;
private int mSeekWhenPrepared;
protected int mVideoWidth;
protected int mVideoHeight;
// CropView Attributes
private float mRatioWidth;
private float mRatioHeight;
private float mPositionX;
private float mPositionY;
private float mBoundX;
private float mBoundY;
private int mRotate;
private float mScaleX;
private float mScaleY;
private float mScale;
// Working Variables
private int mCurrentState = STATE_IDLE;
private int mTargetState = STATE_IDLE;
// Touch Event
// past position x, y and move point
float mPastX;
float mPastY;
float mTouchDistance;
private Context context;
// Constructors
public VideoCropView(final Context context) {
super(context);
mContext = context;
initAttributes();
initVideoView();
}
public VideoCropView(final Context context, final AttributeSet attrs) {
super(context, attrs);
mContext = context;
initAttributes(context, attrs, 0);
initVideoView();
}
public VideoCropView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initAttributes(context, attrs, defStyleAttr);
initVideoView();
}
private void initAttributes() {
mRatioWidth = 1;
mRatioHeight = 1;
}
private void initAttributes(Context context, AttributeSet attrs, int defStyleAttr) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VideoCropView, defStyleAttr, 0);
mRatioWidth = typedArray.getInteger(R.styleable.VideoCropView_ratio_width, 3);
mRatioHeight = typedArray.getInteger(R.styleable.VideoCropView_ratio_height, 4);
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
int heightLayout;
int widthLayout;
widthLayout = MeasureSpec.getSize(widthMeasureSpec);
heightLayout = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthLayout, heightLayout);
/*if(widthMeasureSpec < heightMeasureSpec){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) ((width / mRatioWidth) * mRatioHeight);
setMeasuredDimension(width, height);
}else{
int width = MeasureSpec.getSize(widthMeasureSpec);
int height =MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
*/
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mCurrentState == STATE_ERROR || mCurrentState == STATE_IDLE || mCurrentState == STATE_PREPARING) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPastX = event.getX();
mPastY = event.getY();
mTouchDistance = 0;
case MotionEvent.ACTION_MOVE:
if(mBoundX!=0 || mBoundY!=0) {
float dx = event.getX() - mPastX;
float dy = event.getY() - mPastY;
updateViewPosition(dx, dy);
mPastX = event.getX();
mPastY = event.getY();
mTouchDistance += (Math.abs(dx) + Math.abs(dy));
}
break;
case MotionEvent.ACTION_UP:
if (mTouchDistance < 25) {
if (isPlaying()) {
pause();
} else {
start();
}
}
mTouchDistance = 0;
break;
}
return true;
}
#Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(VideoView.class.getName());
}
#Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(VideoView.class.getName());
}
public int resolveAdjustedSize(int desiredSize, int measureSpec) {
Log.d(LOG_TAG, "Resolve called.");
int result = desiredSize;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/*
* Parent says we can be as big as we want. Just don't be larger
* than max size imposed on ourselves.
*/
result = desiredSize;
break;
case MeasureSpec.AT_MOST:
/*
* Parent says we can be as big as we want, up to specSize. Don't be
* larger than specSize, and don't be larger than the max size
* imposed on ourselves.
*/
result = Math.min(desiredSize, specSize);
break;
case MeasureSpec.EXACTLY:
// No choice. Do what we are told.
result = specSize;
break;
}
return result;
}
public void initVideoView() {
mVideoHeight = 0;
mVideoWidth = 0;
setFocusable(false);
setSurfaceTextureListener(mSurfaceTextureListener);
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
}
public void setVideoPath(String path) {
if (path != null) {
setVideoURI(Uri.parse(path));
}
}
public void setVideoURI(Uri pVideoURI) {
mUri = pVideoURI;
mSeekWhenPrepared = 0;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(mContext, pVideoURI);
// create thumbnail bitmap
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
String rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
try {
mRotate = Integer.parseInt(rotation);
} catch(NumberFormatException e) {
mRotate = 0;
}
}
retriever.release();
openVideo();
requestLayout();
invalidate();
}
public void stopPlayback() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
}
}
public void openVideo() {
if ((mUri == null) || (mSurface == null)) {
// not ready for playback just yet, will try again later
return;
}
// Tell the music playback service to pause
// TODO: these constants need to be published somewhere in the
// framework.
Intent intent = new Intent("com.android.music.musicservicecommand");
intent.putExtra("command", "pause");
mContext.sendBroadcast(intent);
// we shouldn't clear the target state, because somebody might have
// called start() previously
release(false);
try {
mMediaPlayer = new MediaPlayer();
// TODO: create SubtitleController in MediaPlayer, but we need
// a context for the subtitle renderers
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri);
mMediaPlayer.setSurface(mSurface);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
mMediaPlayer.setLooping(true);
mCurrentState = STATE_PREPARING;
} catch (IllegalStateException e) {
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
e.printStackTrace();
} catch (IOException e) {
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
e.printStackTrace();
}
}
private OnVideoSizeChangedListener mSizeChangedListener = new OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(final MediaPlayer mp, final int width,
final int height) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
requestLayout();
if(mVideoWidth >= mVideoHeight)
initVideo();
}
}
};
private OnPreparedListener mPreparedListener = new OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
mCurrentState = STATE_PREPARED;
if (mOnPreparedListener != null) {
mOnPreparedListener.onPrepared(mp);
}
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be
// changed after seekTo()
if (seekToPosition != 0) {
seekTo(seekToPosition);
}
if ((mVideoWidth != 0) && (mVideoHeight != 0)) {
if(mVideoWidth >= mVideoHeight) initVideo();
if (mTargetState == STATE_PLAYING) {
start();
}
} else {
// We don't know the video size yet, but should start anyway.
// The video size might be reported to us later.
if (mTargetState == STATE_PLAYING) {
start();
}
}
}
};
private OnCompletionListener mCompletionListener = new OnCompletionListener() {
#Override
public void onCompletion(final MediaPlayer mp) {
mCurrentState = STATE_PLAYBACK_COMPLETED;
mTargetState = STATE_PLAYBACK_COMPLETED;
if (mOCompletionListener != null) {
mOCompletionListener.onCompletion(mMediaPlayer);
}
}
};
private OnInfoListener mInfoListener = new OnInfoListener() {
public boolean onInfo(MediaPlayer mp, int arg1, int arg2) {
if (mOnInfoListener != null) {
mOnInfoListener.onInfo(mp, arg1, arg2);
}
return true;
}
};
private OnErrorListener mErrorListener = new OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
Log.d(LOG_TAG, "Error: " + framework_err + "," + impl_err);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
/* If an error handler has been supplied, use it and finish. */
if (mOnErrorListener != null) {
if (mOnErrorListener.onError(mMediaPlayer, framework_err,
impl_err)) {
return true;
}
}
return true;
}
};
private OnBufferingUpdateListener mBufferingUpdateListener = new OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
mCurrentBufferPercentage = percent;
}
};
public void setOnPreparedListener(OnPreparedListener listener) {
mOnPreparedListener = listener;
}
public void setOnCompletionListener(OnCompletionListener listener) {
mOCompletionListener = listener;
}
public void setOnErrorListener(OnErrorListener listener) {
mOnErrorListener = listener;
}
public void setOnInfoListener(OnInfoListener listener) {
mOnInfoListener = listener;
}
private void release(boolean cleartargetstate) {
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
mCurrentState = STATE_IDLE;
if (cleartargetstate) {
mTargetState = STATE_IDLE;
}
}
}
#Override
public void start() {
if (isInPlaybackState()) {
mMediaPlayer.start();
mCurrentState = STATE_PLAYING;
}
mTargetState = STATE_PLAYING;
}
#Override
public void pause() {
if (isInPlaybackState()) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mCurrentState = STATE_PAUSED;
}
}
mTargetState = STATE_PAUSED;
}
#Override
public int getDuration() {
if (isInPlaybackState()) {
return mMediaPlayer.getDuration();
}
return -1;
}
#Override
public int getCurrentPosition() {
if (isInPlaybackState()) {
return mMediaPlayer.getCurrentPosition();
}
return 0;
}
#Override
public void seekTo(int msec) {
if (isInPlaybackState()) {
mMediaPlayer.seekTo(msec);
mSeekWhenPrepared = 0;
} else {
mSeekWhenPrepared = msec;
}
}
#Override
public boolean isPlaying() {
return isInPlaybackState() && mMediaPlayer.isPlaying();
}
#Override
public int getBufferPercentage() {
if (mMediaPlayer != null) {
return mCurrentBufferPercentage;
}
return 0;
}
private boolean isInPlaybackState() {
return (mMediaPlayer != null && mCurrentState != STATE_ERROR
&& mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING);
}
#Override
public boolean canPause() {
return false;
}
#Override
public boolean canSeekBackward() {
return false;
}
#Override
public boolean canSeekForward() {
return false;
}
#Override
public int getAudioSessionId() {
return -1;
}
SurfaceTextureListener mSurfaceTextureListener = new SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = new Surface(surface);
openVideo();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
boolean isValidState = (mTargetState == STATE_PLAYING);
boolean hasValidSize = (mVideoWidth == width && mVideoHeight == height);
if (mMediaPlayer != null && isValidState && hasValidSize) {
start();
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
return true;
}
#Override
public void onSurfaceTextureUpdated(final SurfaceTexture surface) {
}
};
#Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (visibility == View.INVISIBLE || visibility == View.GONE) {
if (isPlaying()) {
stopPlayback();
}
}
}
public float getScale() {
return mScale;
}
private void initVideo() {
try {
int width = getWidth();
int height = getHeight();
mScaleX = 1.0f;
mScaleY = 1.0f;
mPositionX = 0;
mPositionY = 0;
mBoundX = 0;
mBoundY = 0;
mMatrix = new Matrix();
mScaleX = (float) mVideoWidth / width;
mScaleY = (float) mVideoHeight / height;
mBoundX = width - mVideoWidth / mScaleY;
mBoundY = height - mVideoHeight / mScaleX;
if (mScaleX < mScaleY) {
mScale = mScaleX;
mScaleY = mScaleY * (1.0f / mScaleX);
mScaleX = 1.0f;
mBoundX = 0;
} else {
mScale = mScaleY;
mScaleX = mScaleX * (1.0f / mScaleY);
mScaleY = 1.0f;
mBoundY = 0;
}
mMatrix = new Matrix();
mMatrix.setScale(mScaleX, mScaleY);
setTransform(mMatrix);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
public void updateViewPosition(float x, float y) {
float nextX = mPositionX + x;
float nextY = mPositionY + y;
if(mScaleX == 1.0f) {
x = 0;
} else {
if(nextX > 0) {
x = -mPositionX;
mPositionX = mPositionX + x;
} else if(nextX < mBoundX) {
x = mBoundX - mPositionX;
mPositionX = mPositionX + x;
} else {
mPositionX = nextX;
}
}
if(mScaleY == 1.0f) {
y = 0;
} else {
if(nextY > 0) {
y = -mPositionY;
mPositionY = mPositionY + y;
} else if(nextY < mBoundY) {
y = mBoundY - mPositionY;
mPositionY = mPositionY + y;
} else {
mPositionY = nextY;
}
}
if(mOnTranslatePositionListener != null) {
mOnTranslatePositionListener.onTranslatePosition(mPositionX, mPositionY, mPositionX * -mScale, mPositionY * -mScale);
}
mMatrix.postTranslate(x, y);
setTransform(mMatrix);
invalidate();
}
// public void setOriginalRatio() {
// if(mVideoWidth != 0 && mVideoHeight != 0) {
// int gcd = gcd(mVideoWidth, mVideoHeight);
// setRatio(mVideoWidth / gcd, mVideoHeight / gcd);
// }
// }
public int gcd(int n, int m) {
while (m != 0) {
int t = n % m;
n = m;
m = t;
}
return Math.abs(n);
}
// public void setRatio(float ratioWidth, float ratioHeight) {
// mRatioWidth = ratioWidth;
// mRatioHeight = ratioHeight;
//
// int seek = getCurrentPosition();
//
// requestLayout();
// invalidate();
// openVideo();
//
// seekTo(seek);
// }
public float getRatioWidth() {
return mRatioWidth;
}
public float getRatioHeight() {
return mRatioHeight;
}
public float getRealPositionX() {
return mPositionX * -mScale;
}
public float getRealPositionY() {
return mPositionY * -mScale;
}
public int getVideoWidth() {
return mVideoWidth;
}
public int getVideoHeight() {
return mVideoHeight;
}
public int getRotate() {
return mRotate;
}
public void setOnTranslatePositionListener(OnTranslatePositionListener pOnTranslatePositionListener) {
mOnTranslatePositionListener = pOnTranslatePositionListener;
}
public void setContext(Context context) {
this.context = context;
}
public interface OnTranslatePositionListener {
public abstract void onTranslatePosition(float x, float y, float rx, float ry);
}
}
FFMPEG for cropping particular portion
ffmpeg -i /sdcard/videokit/in.mp4 -filter:v crop=720:1088:0:0 -c:a copy /sdcard/videokit/out.mp4
public class SimpleExample extends Activity {
String workFolder = null;
String demoVideoFolder = null;
String demoVideoPath = null;
String vkLogPath = null;
private boolean commandValidationFailedFlag = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ffmpeg_demo_client_1);
demoVideoFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videokit/";
demoVideoPath = demoVideoFolder + "in.mp4";
Log.i(Prefs.TAG, getString(R.string.app_name) + " version: " + GeneralUtils.getVersionName(getApplicationContext()) );
workFolder = getApplicationContext().getFilesDir().getAbsolutePath() + "/";
//Log.i(Prefs.TAG, "workFolder: " + workFolder);
vkLogPath = workFolder + "vk.log";
GeneralUtils.copyLicenseFromAssetsToSDIfNeeded(this, workFolder);
GeneralUtils.copyDemoVideoFromAssetsToSDIfNeeded(this, demoVideoFolder);
Button invoke = (Button)findViewById(R.id.invokeButton);
invoke.setOnClickListener(new OnClickListener() {
public void onClick(View v){
Log.i(Prefs.TAG, "run clicked.");
if (GeneralUtils.checkIfFileExistAndNotEmpty(demoVideoPath)) {
new TranscdingBackground(SimpleExample.this).execute();
}
else {
Toast.makeText(getApplicationContext(), demoVideoPath + " not found", Toast.LENGTH_LONG).show();
}
}
});
int rc = GeneralUtils.isLicenseValid(getApplicationContext(), workFolder);
Log.i(Prefs.TAG, "License check RC: " + rc);
}
public class TranscdingBackground extends AsyncTask<String, Integer, Integer>
{
ProgressDialog progressDialog;
Activity _act;
String commandStr;
public TranscdingBackground (Activity act) {
_act = act;
}
#Override
protected void onPreExecute() {
EditText commandText = (EditText)findViewById(R.id.CommandText);
commandStr = commandText.getText().toString();
progressDialog = new ProgressDialog(_act);
progressDialog.setMessage("FFmpeg4Android Transcoding in progress...");
progressDialog.show();
}
protected Integer doInBackground(String... paths) {
Log.i(Prefs.TAG, "doInBackground started...");
// delete previous log
boolean isDeleted = GeneralUtils.deleteFileUtil(workFolder + "/vk.log");
Log.i(Prefs.TAG, "vk deleted: " + isDeleted);
PowerManager powerManager = (PowerManager)_act.getSystemService(Activity.POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
Log.d(Prefs.TAG, "Acquire wake lock");
wakeLock.acquire();
///////////// Set Command using code (overriding the UI EditText) /////
//commandStr = "ffmpeg -y -i /sdcard/videokit/in.mp4 -strict experimental -s 320x240 -r 30 -aspect 3:4 -ab 48000 -ac 2 -ar 22050 -vcodec mpeg4 -b 2097152 /sdcard/videokit/out.mp4";
//String[] complexCommand = {"ffmpeg", "-y" ,"-i", "/sdcard/videokit/in.mp4","-strict","experimental","-s", "160x120","-r","25", "-vcodec", "mpeg4", "-b", "150k", "-ab","48000", "-ac", "2", "-ar", "22050", "/sdcard/videokit/out.mp4"};
///////////////////////////////////////////////////////////////////////
LoadJNI vk = new LoadJNI();
try {
vk.run(GeneralUtils.utilConvertToComplex(commandStr), workFolder, getApplicationContext());
GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder);
} catch (Throwable e) {
Log.e(Prefs.TAG, "vk run exeption.", e);
}
finally {
if (wakeLock.isHeld())
wakeLock.release();
else{
Log.i(Prefs.TAG, "Wake lock is already released, doing nothing");
}
}
Log.i(Prefs.TAG, "doInBackground finished");
return Integer.valueOf(0);
}
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onCancelled() {
Log.i(Prefs.TAG, "onCancelled");
//progressDialog.dismiss();
super.onCancelled();
}
#Override
protected void onPostExecute(Integer result) {
Log.i(Prefs.TAG, "onPostExecute");
progressDialog.dismiss();
super.onPostExecute(result);
// finished Toast
String rc = null;
if (commandValidationFailedFlag) {
rc = "Command Vaidation Failed";
}
else {
rc = GeneralUtils.getReturnCodeFromLog(vkLogPath);
}
final String status = rc;
SimpleExample.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(SimpleExample.this, status, Toast.LENGTH_LONG).show();
if (status.equals("Transcoding Status: Failed")) {
Toast.makeText(SimpleExample.this, "Check: " + vkLogPath + " for more information.", Toast.LENGTH_LONG).show();
}
}
});
}
}
}
try to use getBitmap: TextureView.getBitmap for VideoCropView
it returns bitmap wanted resolution.
Then you can crop using Bitmap.createBitmap
like this
resizedbitmap=Bitmap.createBitmap(bmp, 0,0,yourwidth, yourheight);
Use this library to crop video with visible portion
Video Trimmer Library
Related
I need to tilt my SurfaceView by certain angle. SurfaceView renders a frame from WebRTC. But the render is always vertical. I need to rotate it by certain angle, say 30 degrees. I tried setting up setWillNotDraw(false); and adding this to my onDraw(Canvas canvas) method.
#Override
protected void onDraw(Canvas canvas) {
canvas.rotate(30, 220, 290);
super.onDraw(canvas);
}
This does not seem to work at all.
Here is my SurfaceView class:
public class SurfaceViewRenderer extends SurfaceView implements Callback, Callbacks {
private static final String TAG = "SurfaceViewRenderer";
private final String resourceName = this.getResourceName();
private final VideoLayoutMeasure videoLayoutMeasure = new VideoLayoutMeasure();
private final EglRenderer eglRenderer;
private RendererEvents rendererEvents;
private final Object layoutLock = new Object();
private boolean isFirstFrameRendered;
private int rotatedFrameWidth;
private int rotatedFrameHeight;
private int frameRotation;
private boolean enableFixedSize;
private int surfaceWidth;
private int surfaceHeight;
public SurfaceViewRenderer(Context context) {
super(context);
this.eglRenderer = new EglRenderer(this.resourceName);
this.getHolder().addCallback(this);
}
public SurfaceViewRenderer(Context context, AttributeSet attrs) {
super(context, attrs);
this.eglRenderer = new EglRenderer(this.resourceName);
this.getHolder().addCallback(this);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setWillNotDraw(false);
}
public void init(org.webrtc.EglBase.Context sharedContext, RendererEvents rendererEvents) {
this.init(sharedContext, rendererEvents, EglBase.CONFIG_PLAIN, new GlRectDrawer());
}
public void init(org.webrtc.EglBase.Context sharedContext, RendererEvents rendererEvents, int[] configAttributes, GlDrawer drawer) {
ThreadUtils.checkIsOnMainThread();
this.rendererEvents = rendererEvents;
Object var5 = this.layoutLock;
synchronized(this.layoutLock) {
this.rotatedFrameWidth = 0;
this.rotatedFrameHeight = 0;
this.frameRotation = 0;
}
this.eglRenderer.init(sharedContext, configAttributes, drawer);
}
public void release() {
this.eglRenderer.release();
}
public void addFrameListener(FrameListener listener, float scale, GlDrawer drawer) {
this.eglRenderer.addFrameListener(listener, scale, drawer);
}
public void addFrameListener(FrameListener listener, float scale) {
this.eglRenderer.addFrameListener(listener, scale);
}
public void removeFrameListener(FrameListener listener) {
this.eglRenderer.removeFrameListener(listener);
}
public void setEnableHardwareScaler(boolean enabled) {
ThreadUtils.checkIsOnMainThread();
this.enableFixedSize = enabled;
this.updateSurfaceSize();
}
public void setMirror(boolean mirror) {
this.eglRenderer.setMirror(mirror);
}
public void setScalingType(ScalingType scalingType) {
ThreadUtils.checkIsOnMainThread();
this.videoLayoutMeasure.setScalingType(scalingType);
}
public void setScalingType(ScalingType scalingTypeMatchOrientation, ScalingType scalingTypeMismatchOrientation) {
ThreadUtils.checkIsOnMainThread();
this.videoLayoutMeasure.setScalingType(scalingTypeMatchOrientation, scalingTypeMismatchOrientation);
}
public void setFpsReduction(float fps) {
this.eglRenderer.setFpsReduction(fps);
}
public void disableFpsReduction() {
this.eglRenderer.disableFpsReduction();
}
public void pauseVideo() {
this.eglRenderer.pauseVideo();
}
public void renderFrame(I420Frame frame) {
this.updateFrameDimensionsAndReportEvents(frame);
this.eglRenderer.renderFrame(frame);
}
protected void onMeasure(int widthSpec, int heightSpec) {
ThreadUtils.checkIsOnMainThread();
Object var4 = this.layoutLock;
Point size;
synchronized(this.layoutLock) {
size = this.videoLayoutMeasure.measure(widthSpec, heightSpec, this.rotatedFrameWidth, this.rotatedFrameHeight);
}
this.setMeasuredDimension(size.x, size.y);
this.logD("onMeasure(). New size: " + size.x + "x" + size.y);
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
ThreadUtils.checkIsOnMainThread();
this.eglRenderer.setLayoutAspectRatio((float)(right - left) / (float)(bottom - top));
this.updateSurfaceSize();
}
private void updateSurfaceSize() {
ThreadUtils.checkIsOnMainThread();
Object var1 = this.layoutLock;
synchronized(this.layoutLock) {
if(this.enableFixedSize && this.rotatedFrameWidth != 0 && this.rotatedFrameHeight != 0 && this.getWidth() != 0 && this.getHeight() != 0) {
float layoutAspectRatio = (float)this.getWidth() / (float)this.getHeight();
float frameAspectRatio = (float)this.rotatedFrameWidth / (float)this.rotatedFrameHeight;
int drawnFrameWidth;
int drawnFrameHeight;
if(frameAspectRatio > layoutAspectRatio) {
drawnFrameWidth = (int)((float)this.rotatedFrameHeight * layoutAspectRatio);
drawnFrameHeight = this.rotatedFrameHeight;
} else {
drawnFrameWidth = this.rotatedFrameWidth;
drawnFrameHeight = (int)((float)this.rotatedFrameWidth / layoutAspectRatio);
}
int width = Math.min(this.getWidth(), drawnFrameWidth);
int height = Math.min(this.getHeight(), drawnFrameHeight);
this.logD("updateSurfaceSize. Layout size: " + this.getWidth() + "x" + this.getHeight() + ", frame size: " + this.rotatedFrameWidth + "x" + this.rotatedFrameHeight + ", requested surface size: " + width + "x" + height + ", old surface size: " + this.surfaceWidth + "x" + this.surfaceHeight);
if(width != this.surfaceWidth || height != this.surfaceHeight) {
this.surfaceWidth = width;
this.surfaceHeight = height;
this.getHolder().setFixedSize(width, height);
}
} else {
this.surfaceWidth = this.surfaceHeight = 0;
this.getHolder().setSizeFromLayout();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
ThreadUtils.checkIsOnMainThread();
this.eglRenderer.createEglSurface(holder.getSurface());
this.surfaceWidth = this.surfaceHeight = 0;
this.updateSurfaceSize();
}
public void surfaceDestroyed(SurfaceHolder holder) {
ThreadUtils.checkIsOnMainThread();
final CountDownLatch completionLatch = new CountDownLatch(1);
this.eglRenderer.releaseEglSurface(new Runnable() {
public void run() {
completionLatch.countDown();
}
});
ThreadUtils.awaitUninterruptibly(completionLatch);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
ThreadUtils.checkIsOnMainThread();
this.logD("surfaceChanged: format: " + format + " size: " + width + "x" + height);
}
private String getResourceName() {
try {
return this.getResources().getResourceEntryName(this.getId()) + ": ";
} catch (NotFoundException var2) {
return "";
}
}
private void updateFrameDimensionsAndReportEvents(I420Frame frame) {
Object var2 = this.layoutLock;
synchronized(this.layoutLock) {
if(!this.isFirstFrameRendered) {
this.isFirstFrameRendered = true;
this.logD("Reporting first rendered frame.");
if(this.rendererEvents != null) {
this.rendererEvents.onFirstFrameRendered();
}
}
if(this.rotatedFrameWidth != frame.rotatedWidth() || this.rotatedFrameHeight != frame.rotatedHeight() || this.frameRotation != frame.rotationDegree) {
this.logD("Reporting frame resolution changed to " + frame.width + "x" + frame.height + " with rotation " + frame.rotationDegree);
if(this.rendererEvents != null) {
this.rendererEvents.onFrameResolutionChanged(frame.width, frame.height, frame.rotationDegree);
}
this.rotatedFrameWidth = frame.rotatedWidth();
this.rotatedFrameHeight = frame.rotatedHeight();
this.frameRotation = frame.rotationDegree;
this.post(new Runnable() {
public void run() {
SurfaceViewRenderer.this.updateSurfaceSize();
SurfaceViewRenderer.this.requestLayout();
}
});
}
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.rotate(180, 220, 290);
super.onDraw(canvas);
}
private void logD(String string) {
Logging.d("SurfaceViewRenderer", this.resourceName + string);
}
}
You could use TextureView instead.
From the documentation:
Unlike SurfaceView, TextureView does not create a separate window but behaves as a regular View. This key difference allows a TextureView to be moved, transformed, animated, etc.
I am creating a camera application using android camera api by this example: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/
I made some changes according to my needs and you can see the code below. The problem is, camera preview for back camera works quite fine on my LG G3 device but on LG G4 it gets too slow. It also works fine with front camera on both devices.
What can cause this problem ?
CameraPreview:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback{
private static String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Size> mSupportedPreviewSizes;
private Size mPreviewSize;
public CameraPreview(Context context, Camera camera){
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try{
Log.d(TAG, "Surface Created..");
if(mCamera == null){
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
} catch (IOException e) {
Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void refreshCamera(Camera camera) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
setCamera(camera);
try {
Log.d(TAG,"RefreshCamera..");
if(mCamera == null){
Log.d(TAG,"Camera null");
}
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewDisplay(mHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d(TAG, "Surface Changed..");
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mCamera.release();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG,"onMeasure..");
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mSupportedPreviewSizes==null){
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}else{
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
Log.d(TAG, "mPreviewSize set.. Width: " + mPreviewSize.width+" Height: " + mPreviewSize.height);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
I can share the Activity class if its needed..
Thanks..
I had the same problem using surface view .use the below preview class.its working for me for all the device screen.
public class SquareCameraPreview extends SurfaceView {
public static final String TAG = SquareCameraPreview.class.getSimpleName();
private static final int INVALID_POINTER_ID = -1;
private static final int ZOOM_OUT = 0;
private static final int ZOOM_IN = 1;
private static final int ZOOM_DELTA = 1;
private static final int FOCUS_SQR_SIZE = 100;
private static final int FOCUS_MAX_BOUND = 1000;
private static final int FOCUS_MIN_BOUND = -FOCUS_MAX_BOUND;
private static final double ASPECT_RATIO = 3.0 / 4.0;
private Camera mCamera;
private float mLastTouchX;
private float mLastTouchY;
// For scaling
private int mMaxZoom;
private boolean mIsZoomSupported;
private int mActivePointerId = INVALID_POINTER_ID;
private int mScaleFactor = 1;
private ScaleGestureDetector mScaleDetector;
// For focus
private boolean mIsFocus;
private boolean mIsFocusReady;
private Camera.Area mFocusArea;
private ArrayList<Camera.Area> mFocusAreas;
public SquareCameraPreview(Context context) {
super(context);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SquareCameraPreview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mFocusArea = new Camera.Area(new Rect(), 1000);
mFocusAreas = new ArrayList<Camera.Area>();
mFocusAreas.add(mFocusArea);
}
/**
* Measure the view and its content to determine the measured width and the
* measured height
*/
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
final boolean isPortrait =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (isPortrait) {
if (width > height * ASPECT_RATIO) {
width = (int) (height * ASPECT_RATIO + 0.5);
} else {
height = (int) (width / ASPECT_RATIO + 0.5);
}
} else {
if (height > width * ASPECT_RATIO) {
height = (int) (width * ASPECT_RATIO + 0.5);
} else {
width = (int) (height / ASPECT_RATIO + 0.5);
}
}
setMeasuredDimension(width, height);
}
public int getViewWidth() {
return getWidth();
}
public int getViewHeight() {
return getHeight();
}
public void setCamera(Camera camera) {
mCamera = camera;
if (camera != null) {
Camera.Parameters params = camera.getParameters();
mIsZoomSupported = params.isZoomSupported();
if (mIsZoomSupported) {
mMaxZoom = params.getMaxZoom();
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mIsFocus = true;
mLastTouchX = event.getX();
mLastTouchY = event.getY();
mActivePointerId = event.getPointerId(0);
break;
}
case MotionEvent.ACTION_UP: {
if (mIsFocus && mIsFocusReady) {
handleFocus(mCamera.getParameters());
}
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
mCamera.cancelAutoFocus();
mIsFocus = false;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
return true;
}
private void handleZoom(Camera.Parameters params) {
int zoom = params.getZoom();
if (mScaleFactor == ZOOM_IN) {
if (zoom < mMaxZoom) zoom += ZOOM_DELTA;
} else if (mScaleFactor == ZOOM_OUT) {
if (zoom > 0) zoom -= ZOOM_DELTA;
}
params.setZoom(zoom);
mCamera.setParameters(params);
}
private void handleFocus(Camera.Parameters params) {
float x = mLastTouchX;
float y = mLastTouchY;
if (!setFocusBound(x, y)) return;
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null
&& supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
Log.d(TAG, mFocusAreas.size() + "");
params.setFocusAreas(mFocusAreas);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(params);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
// Callback when the auto focus completes
}
});
}
}
public void setIsFocusReady(final boolean isFocusReady) {
mIsFocusReady = isFocusReady;
}
private boolean setFocusBound(float x, float y) {
int left = (int) (x - FOCUS_SQR_SIZE / 2);
int right = (int) (x + FOCUS_SQR_SIZE / 2);
int top = (int) (y - FOCUS_SQR_SIZE / 2);
int bottom = (int) (y + FOCUS_SQR_SIZE / 2);
if (FOCUS_MIN_BOUND > left || left > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > right || right > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > top || top > FOCUS_MAX_BOUND) return false;
if (FOCUS_MIN_BOUND > bottom || bottom > FOCUS_MAX_BOUND) return false;
mFocusArea.rect.set(left, top, right, bottom);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor = (int) detector.getScaleFactor();
handleZoom(mCamera.getParameters());
return true;
}
}
}
public class CameraFragment extends Fragment implements SurfaceHolder.Callback, Camera.PictureCallback {
public static int HIGH_RESOLUTION_WIDTH=1000;
public static int HIGH_RESOLUTION_HIGHT=1500;
public static String clorie_count;
private long startTime = 0L;
public static final String TAG = CameraFragment.class.getSimpleName();
public static final String CAMERA_ID_KEY = "camera_id";
public static final String CAMERA_FLASH_KEY = "flash_mode";
public static final String IMAGE_INFO = "image_info";
private static final int PICTURE_SIZE_MAX_WIDTH = 1280;
private static final int PREVIEW_SIZE_MAX_WIDTH = 640;
private int mCameraID;
private String mFlashMode;
private Camera mCamera;
private SquareCameraPreview mPreviewView;
private SurfaceHolder mSurfaceHolder;
private boolean mIsSafeToTakePhoto = false;
private ImageParameters mImageParameters;
private CameraOrientationListener mOrientationListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
mOrientationListener = new CameraOrientationListener(context);
}
View view;
Dialog listDialog;
#SuppressLint("NewApi")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.camera_fragment, container, false);
if (savedInstanceState == null) {
mCameraID = getBackCameraID();
mFlashMode = CameraSettingPreferences.getCameraFlashMode(getActivity());
mImageParameters = new ImageParameters();
} else {
mCameraID = savedInstanceState.getInt(CAMERA_ID_KEY);
mFlashMode = savedInstanceState.getString(CAMERA_FLASH_KEY);
mImageParameters = savedInstanceState.getParcelable(IMAGE_INFO);
}
mPreviewView = (SquareCameraPreview) view.findViewById(R.id.camerapreview);
mPreviewView.getHolder().addCallback(CameraFragment.this);
mImageParameters.mIsPortrait =getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
capture_icon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
takePicture();
}
});
return view;
}
private void takePicture() {
if (mIsSafeToTakePhoto) {
setSafeToTakePhoto(false);
mOrientationListener.rememberOrientation();
// Shutter callback occurs after the image is captured. This can
// be used to trigger a sound to let the user know that image is taken
Camera.ShutterCallback shutterCallback = null;
// Raw callback occurs when the raw image data is available
Camera.PictureCallback raw = null;
// postView callback occurs when a scaled, fully processed
// postView image is available.
Camera.PictureCallback postView = null;
// jpeg callback occurs when the compressed image is available
mCamera.takePicture(shutterCallback, raw, postView, this);
}
}
private void setSafeToTakePhoto(final boolean isSafeToTakePhoto) {
mIsSafeToTakePhoto = isSafeToTakePhoto;
}
private void setCameraFocusReady(final boolean isFocusReady) {
if (this.mPreviewView != null) {
mPreviewView.setIsFocusReady(isFocusReady);
}
}
/**
* Determine the current display orientation and rotate the camera preview
* accordingly
*/
private void determineDisplayOrientation() {
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(mCameraID, cameraInfo);
// Clockwise rotation needed to align the window display to the natural position
int rotation = getActivity().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 displayOrientation;
// CameraInfo.Orientation is the angle relative to the natural position of the device
// in clockwise rotation (angle that is rotated clockwise from the natural position)
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
// Orientation is angle of rotation when facing the camera for
// the camera image to match the natural orientation of the device
displayOrientation = (cameraInfo.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360;
} else {
displayOrientation = (cameraInfo.orientation - degrees + 360) % 360;
}
mImageParameters.mDisplayOrientation = displayOrientation;
mImageParameters.mLayoutOrientation = degrees;
mCamera.setDisplayOrientation(mImageParameters.mDisplayOrientation);
}
private void setupCamera() {
// Never keep a global parameters
Camera.Parameters parameters = mCamera.getParameters();
Size bestPreviewSize = determineBestPreviewSize(parameters);
Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
// Set continuous picture focus, if it's supported
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
final View changeCameraFlashModeBtn = getView().findViewById(R.id.flash);
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes != null && flashModes.contains(mFlashMode)) {
parameters.setFlashMode(mFlashMode);
changeCameraFlashModeBtn.setVisibility(View.VISIBLE);
} else {
changeCameraFlashModeBtn.setVisibility(View.INVISIBLE);
}
// Lock in the changes
mCamera.setParameters(parameters);
}
private Size determineBestPreviewSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPreviewSizes(), PREVIEW_SIZE_MAX_WIDTH);
}
private Size determineBestPictureSize(Camera.Parameters parameters) {
return determineBestSize(parameters.getSupportedPictureSizes(), PICTURE_SIZE_MAX_WIDTH);
}
private Size determineBestSize(List<Size> sizes, int widthThreshold) {
Size bestSize = null;
Size size;
int numOfSizes = sizes.size();
for (int i = 0; i < numOfSizes; i++) {
size = sizes.get(i);
boolean isDesireRatio = (size.width / 4) == (size.height / 3);
boolean isBetterSize = (bestSize == null) || size.width > bestSize.width;
if (isDesireRatio && isBetterSize) {
bestSize = size;
}
}
if (bestSize == null) {
Log.d(TAG, "cannot find the best camera size");
return sizes.get(sizes.size() - 1);
}
return bestSize;
}
/**
* Start the camera preview
*/
private void startCameraPreview() {
determineDisplayOrientation();
setupCamera();
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
setSafeToTakePhoto(true);
setCameraFocusReady(true);
} catch (IOException e) {
Log.d(TAG, "Can't start camera preview due to IOException " + e);
e.printStackTrace();
}
}
private void getCamera(int cameraID) {
try {
mCamera = Camera.open(cameraID);
mPreviewView.setCamera(mCamera);
} catch (Exception e) {
Log.d(TAG, "Can't open camera with id " + cameraID);
e.printStackTrace();
}
}
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
HERE YOU GET THE PHOTO BYTE[] arg0
CONVERT IT TO BITMAP OR STROE INTO A FILE
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mSurfaceHolder = holder;
getCamera(mCameraID);
startCameraPreview();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
private static class CameraOrientationListener extends OrientationEventListener {
private int mCurrentNormalizedOrientation;
private int mRememberedNormalOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onOrientationChanged(int orientation) {
if (orientation != ORIENTATION_UNKNOWN) {
mCurrentNormalizedOrientation = normalize(orientation);
}
}
/**
* #param degrees Amount of clockwise rotation from the device's natural position
* #return Normalized degrees to just 0, 90, 180, 270
*/
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
mRememberedNormalOrientation = mCurrentNormalizedOrientation;
}
public int getRememberedNormalOrientation() {
rememberOrientation();
return mRememberedNormalOrientation;
}
}
/*#Override
public void onResume() {
super.onResume();
if (mCamera == null) {
restartPreview();
}
}*/
#Override
public void onStop() {
mOrientationListener.disable();
// stop the preview
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
if (getKillStatus()) {
android.os.Process.killProcess(android.os.Process.myPid());
}
// CameraSettingPreferences.saveCameraFlashMode(getActivity(), mFlashMode);
super.onStop();
}
#Override
public void onResume() {
super.onResume();
/*if (camera != null) {
camera.stopPreview();
preview.setupCamera(null,isResolutionHigh);
camera.release();
camera = null;
}
int numCams = Camera.getNumberOfCameras();
if (numCams > 0) {
try {
camera = Camera.open(0);
camera.startPreview();
preview.setupCamera(camera,isResolutionHigh);
} catch (RuntimeException ex) {
// Toast.makeText(ctx, getString(R.string.camera_not_found),
// Toast.LENGTH_LONG).show();
}
}*/
if (mCamera == null) {
restartPreview();
}
}
private void restartPreview() {
if (mCamera != null) {
stopCameraPreview();
mCamera.release();
mCamera = null;
}
getCamera(mCameraID);
startCameraPreview();
}
/**
* Stop the camera preview
*/
private void stopCameraPreview() {
setSafeToTakePhoto(false);
setCameraFocusReady(false);
// Nulls out callbacks, stops face detection
mCamera.stopPreview();
mPreviewView.setCamera(null);
}
private int getBackCameraID() {
return CameraInfo.CAMERA_FACING_BACK;
}
}
AND YOUR XML FILE
<com.demo.camera.SquareCameraPreview
android:id="#+id/camerapreview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
ImageParameter Class
public class ImageParameters implements Parcelable {
public boolean mIsPortrait;
public int mDisplayOrientation;
public int mLayoutOrientation;
public int mCoverHeight, mCoverWidth;
public int mPreviewHeight, mPreviewWidth;
public ImageParameters(Parcel in) {
mIsPortrait = (in.readByte() == 1);
mDisplayOrientation = in.readInt();
mLayoutOrientation = in.readInt();
mCoverHeight = in.readInt();
mCoverWidth = in.readInt();
mPreviewHeight = in.readInt();
mPreviewWidth = in.readInt();
}
public ImageParameters() {}
public int calculateCoverWidthHeight() {
return Math.abs(mPreviewHeight - mPreviewWidth) / 2;
}
public int getAnimationParameter() {
return mIsPortrait ? mCoverHeight : mCoverWidth;
}
public boolean isPortrait() {
return mIsPortrait;
}
public ImageParameters createCopy() {
ImageParameters imageParameters = new ImageParameters();
imageParameters.mIsPortrait = mIsPortrait;
imageParameters.mDisplayOrientation = mDisplayOrientation;
imageParameters.mLayoutOrientation = mLayoutOrientation;
imageParameters.mCoverHeight = mCoverHeight;
imageParameters.mCoverWidth = mCoverWidth;
imageParameters.mPreviewHeight = mPreviewHeight;
imageParameters.mPreviewWidth = mPreviewWidth;
return imageParameters;
}
public String getStringValues() {
return "is Portrait: " + mIsPortrait + "," +
"\ncover height: " + mCoverHeight + " width: " + mCoverWidth
+ "\npreview height: " + mPreviewHeight + " width: " + mPreviewWidth;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (mIsPortrait ? 1 : 0));
dest.writeInt(mDisplayOrientation);
dest.writeInt(mLayoutOrientation);
dest.writeInt(mCoverHeight);
dest.writeInt(mCoverWidth);
dest.writeInt(mPreviewHeight);
dest.writeInt(mPreviewWidth);
}
public static final Creator<ImageParameters> CREATOR = new Parcelable.Creator<ImageParameters>() {
#Override
public ImageParameters createFromParcel(Parcel source) {
return new ImageParameters(source);
}
#Override
public ImageParameters[] newArray(int size) {
return new ImageParameters[size];
}
};
}
Another class you need camera setting preference
public class CameraSettingPreferences {
private static final String FLASH_MODE = "squarecamera__flash_mode";
private static SharedPreferences getCameraSettingPreferences(#NonNull final Context context) {
return context.getSharedPreferences("com.desmond.squarecamera", Context.MODE_PRIVATE);
}
protected static void saveCameraFlashMode(#NonNull final Context context, #NonNull final String cameraFlashMode) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
final SharedPreferences.Editor editor = preferences.edit();
editor.putString(FLASH_MODE, cameraFlashMode);
editor.apply();
}
}
public static String getCameraFlashMode(#NonNull final Context context) {
final SharedPreferences preferences = getCameraSettingPreferences(context);
if (preferences != null) {
return preferences.getString(FLASH_MODE, Camera.Parameters.FLASH_MODE_AUTO);
}
return Camera.Parameters.FLASH_MODE_AUTO;
}
}
Let me know if you have any doubts.
Does anyone have an idea what would cause the below error?
queueBuffer: error queuing buffer to SurfaceTexture, -32
I'm using SurfaceTexture in my app. The above error occurs when I try to set as
a livewallpaper
Below is the code:
public class ClockWallpaperService extends WallpaperService {
private WallpaperEngine myEngine;
public void onCreate() {
super.onCreate();
}
#Override
public Engine onCreateEngine() {
System.out.println("Service: onCreateEngine");
this.myEngine = new WallpaperEngine();
return myEngine;
}
public void onDestroy() {
this.myEngine = null;
super.onDestroy();
}
private class WallpaperEngine extends Engine implements OnGestureListener,
OnSharedPreferenceChangeListener {
public Bitmap image1, backgroundImage;
private ArrayList<Leaf> leafList;
private Bitmap bitmap1;
private Bitmap bitmap2;
private Bitmap bitmap3;
private Bitmap currentBackgroundBitmap;
private Paint paint;
private int count;
private int heightOfCanvas;
private int widthOfCanvas;
private float touchX;
private float touchY;
private int interval;
private int amount;
private boolean fallingDown;
private float bgX = 0;
private String colorFlag;
private String backgroundFlag;
private Random rand;
private GestureDetector detector;
private static final int DRAW_MSG = 0;
private static final int MAX_SIZE = 101;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DRAW_MSG:
drawPaper();
break;
}
}
};
/** hands colors for hour, min, sec */
private int[] colors = { 0xFFFF0000, 0xFF0000FF, 0xFFA2BC13 };
// private int bgColor;
private int width;
private int height;
private boolean visible = true;
private boolean displayHandSec;
private AnalogClock clock;
private SharedPreferences prefs;
WallpaperEngine() {
// get the fish and background image references
backgroundImage = BitmapFactory.decodeResource(getResources(),
R.drawable.bg1);
SharedPreferences sp = getSharedPreferences("back_position",
Activity.MODE_PRIVATE);
int position = sp.getInt("back_position", 1);
Global.backgroundDial = BitmapFactory.decodeResource(
getResources(), Global.BackgroundId[position]);
prefs = PreferenceManager
.getDefaultSharedPreferences(ClockWallpaperService.this);
prefs.registerOnSharedPreferenceChangeListener(this);
displayHandSec = prefs.getBoolean(
SettingsActivity.DISPLAY_HAND_SEC_KEY, true);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
// bgColor = Color.parseColor("#C0C0C0");
clock = new AnalogClock(getApplicationContext());
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
// TODO Auto-generated method stub
super.onCreate(surfaceHolder);
System.out.println("Engine: onCreate");
this.leafList = new ArrayList<Leaf>();
this.bitmap1 = BitmapFactory.decodeResource(getResources(),
R.drawable.flower1);
this.bitmap2 = BitmapFactory.decodeResource(getResources(),
R.drawable.flower2);
this.bitmap3 = BitmapFactory.decodeResource(getResources(),
R.drawable.flower3);
this.paint = new Paint();
this.paint.setAntiAlias(true);
this.count = -1;
this.rand = new Random();
this.detector = new GestureDetector(this);
this.touchX = -1.0f;
this.touchY = -1.0f;
SharedPreferences pref = PreferenceManager
.getDefaultSharedPreferences(ClockWallpaperService.this);
pref.registerOnSharedPreferenceChangeListener(this);
String speedStr = pref.getString("leaf_falling_speed", "20");
String amountStr = pref.getString("leaf_number", "50");
this.interval = Integer.parseInt(speedStr);
this.amount = Integer.parseInt(amountStr);
this.colorFlag = pref.getString("leaf_color", "0");
this.backgroundFlag = pref.getString("paper_background", "0");
String directionFlag = pref.getString("leaf_moving_direction", "0");
if (directionFlag.equals("0")) {
this.fallingDown = true;
} else {
this.fallingDown = false;
}
this.setTouchEventsEnabled(true);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
System.out.println("Engine: onDestroy");
this.mHandler.removeMessages(DRAW_MSG);
PreferenceManager.getDefaultSharedPreferences(
ClockWallpaperService.this)
.unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
this.width = width;
this.height = height;
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
super.onSurfaceCreated(holder);
System.out.println("Engine: onSurfaceCreate");
Canvas canvas = holder.lockCanvas();
this.heightOfCanvas = canvas.getHeight();
this.widthOfCanvas = canvas.getWidth();
System.out.println("Width = " + widthOfCanvas + ", Height = "
+ heightOfCanvas);
holder.unlockCanvasAndPost(canvas);
this.mHandler.sendEmptyMessage(DRAW_MSG);
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
System.out.println("Engine: onSurfaceDestroyed");
this.mHandler.removeMessages(DRAW_MSG);
if (this.currentBackgroundBitmap != null) {
this.currentBackgroundBitmap.recycle();
this.currentBackgroundBitmap = null;
}
if (this.bitmap1 != null) {
this.bitmap1.recycle();
this.bitmap1 = null;
}
if (this.bitmap2 != null) {
this.bitmap2.recycle();
this.bitmap2 = null;
}
if (this.bitmap3 != null) {
this.bitmap3.recycle();
this.bitmap3 = null;
}
super.onSurfaceDestroyed(holder);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
System.out.println("xPixelOffset: " + xPixelOffset
+ ", yPixelOffset: " + yPixelOffset);
this.bgX = xPixelOffset;
}
private void drawPaper() {
count++;
if (count >= 10000) {
count = 0;
}
if (count % 10 == 0) {
if (this.leafList.size() < MAX_SIZE) {
Leaf l = null;
Bitmap temp = bitmap1;
if (colorFlag.equals("0")) {
int index = rand.nextInt(3) + 1;
switch (index) {
case 1:
temp = bitmap1;
break;
case 2:
temp = bitmap2;
break;
case 3:
temp = bitmap3;
break;
default:
temp = bitmap1;
break;
}
} else if (colorFlag.equals("1")) {
temp = bitmap1;
} else if (colorFlag.equals("2")) {
temp = bitmap2;
} else if (colorFlag.equals("3")) {
temp = bitmap3;
}
l = new Leaf(temp, this.heightOfCanvas, this.widthOfCanvas);
this.leafList.add(l);
}
}
SurfaceHolder holder = this.getSurfaceHolder();
Canvas canvas = holder.lockCanvas();
drawBackground(canvas);
int size = Math.min(this.amount, this.leafList.size());
for (int i = 0; i < size; i++) {
Leaf l = this.leafList.get(i);
if (l.isTouched()) {
l.handleTouched(touchX, touchY);
} else {
l.handleFalling(this.fallingDown);
}
l.drawLeaf(canvas, paint);
}
holder.unlockCanvasAndPost(canvas);
this.mHandler.sendEmptyMessageDelayed(DRAW_MSG, this.interval);
}
private void drawBackground(Canvas c) {
c.drawBitmap(backgroundImage, 0, 0, null);
clock.config(width / 2, height / 2, (int) (width * 0.6f),
new Date(), paint, colors, displayHandSec);
clock.draw(c);
}
#Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
this.detector.onTouchEvent(event);
}
public boolean onDown(MotionEvent e) {
touchX = e.getX();
touchY = e.getY();
int size = Math.min(this.amount, this.leafList.size());
for (int i = 0; i < size; i++) {
Leaf l = this.leafList.get(i);
float centerX = l.getX() + l.getBitmap().getWidth() / 2.0f;
float centerY = l.getY() + l.getBitmap().getHeight() / 2.0f;
if (!l.isTouched()) {
if (Math.abs(centerX - touchX) <= 80
&& Math.abs(centerY - touchY) <= 80
&& centerX != touchX) {
l.setTouched(true);
}
}
}
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
public void onLongPress(MotionEvent e) {
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
if (key.equals("leaf_falling_speed")) {
String speedStr = sharedPreferences.getString(key, "20");
this.interval = Integer.parseInt(speedStr);
} else if (key.equals("leaf_number")) {
String amountStr = sharedPreferences.getString(key, "50");
this.amount = Integer.parseInt(amountStr);
} else if (key.equals("leaf_moving_direction")) {
String directionFlag = sharedPreferences.getString(key, "0");
if (directionFlag.equals("0")) {
this.fallingDown = true;
} else {
this.fallingDown = false;
}
} else if (key.equals("leaf_color")) {
this.colorFlag = sharedPreferences.getString(key, "0");
this.leafList.removeAll(leafList);
}
}
}
}
I am using the mediaplayer.xml to play the video file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/MainView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#4d4d4d"
android:gravity="center"
android:keepScreenOn="true"
android:orientation="vertical" >
<SurfaceView
android:id="#+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
The following MediaPlayerActivity class using SurfaceView and MediaPlayer
While playing video in portrait mode it seems that the video stretched one. I want to play the video vertically center and should not occupy the full screen and then in landscape mode should play in full screen mode.
public class MediaPlayerActivity extends Activity implements OnCompletionListener,
OnErrorListener, OnInfoListener, OnBufferingUpdateListener,
OnPreparedListener, OnSeekCompleteListener, SurfaceHolder.Callback,
MediaController.MediaPlayerControl {
private MediaController controller;
Display currentDisplay;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer;
int videoWidth = 0;
int videoHeight = 0;
boolean readyToPlay = false;
private String streamingVideoUrl;
private ProgressDialog dialog;
public final String TAG = "VIDEO_PLAYER";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"Media player activity called ");
setContentView(R.layout.mediaplayer);
if(getIntent() != null ){
streamingVideoUrl = getIntent().getStringExtra("stream_url");
}
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setOnClickListener(surViewClickListener);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
/*setVideoSize();*/
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//Log.d(TAG,"Returned by getDatasource :"+getDataSource(streamingVideoUrl));
mediaPlayer.setDataSource(streamingVideoUrl);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
currentDisplay = getWindowManager().getDefaultDisplay();
controller = new MediaController(this);
dialog = new ProgressDialog(this);
//dialog.setMessage("Preparing File to Streaming");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setCanceledOnTouchOutside(false);
if(this!= null && !this.isFinishing()){
dialog.show();
}
handler.postDelayed(r, 100);
}
/*private void setVideoSize() {
try {
// // Get the dimensions of the video
int videoWidth = mediaPlayer.getVideoWidth();
int videoHeight = mediaPlayer.getVideoHeight();
float videoProportion = (float) videoWidth / (float) videoHeight;
// Get the width of the screen
int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
float screenProportion = (float) screenWidth / (float) screenHeight;
// Get the SurfaceView layout parameters
android.view.ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
if (videoProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) ((float) screenWidth / videoProportion);
} else {
lp.width = (int) (videoProportion * (float) screenHeight);
lp.height = screenHeight;
}
// Commit the layout parameters
surfaceView.setLayoutParams(lp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
/*//coded by Karthikeyan V
//converting url to byte
private String getDataSource(String path) throws IOException {
Log.d(TAG,"getDataSource called");
if (!URLUtil.isNetworkUrl(path)) {
return path;
} else {
URL url = new URL(path);
URLConnection cn = url.openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null)
throw new RuntimeException("stream is null");
File temp = File.createTempFile("mediaplayertmp", "dat");
temp.deleteOnExit();
String tempPath = temp.getAbsolutePath();
FileOutputStream out = new FileOutputStream(temp);
byte buf[] = new byte[128];
do {
int numread = stream.read(buf);
if (numread <= 0)
break;
out.write(buf, 0, numread);
} while (true);
try {
stream.close();
} catch (IOException ex) {
Log.e(TAG, "error: " + ex.getMessage(), ex);
}
Log.d(TAG,"temp path :"+tempPath);
return tempPath;
}
}*/
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public int getCurrentPosition() {
if(mediaPlayer !=null)
return mediaPlayer.getCurrentPosition();
else
return 0;
}
#Override
public int getDuration() {
return mediaPlayer.getDuration();
}
#Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
#Override
public void pause() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
}
#Override
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
#Override
public void start() {
mediaPlayer.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceChanged Called");
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceCreated Called");
mediaPlayer.setDisplay(holder);
try {
mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow IllegalStateException " + e.getMessage());
finish();
}
if(Constants.DEBUG)
Log.d(TAG, "Media Flow MediaPlayer Preparing");
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow surfaceDestroyed Called");
}
#Override
public void onSeekComplete(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onSeekComplete Called");
}
#Override
public void onPrepared(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onPrepared Called");
// dismissProgressLoading();
controller.setMediaPlayer(this);
controller.setAnchorView(this.findViewById(R.id.MainView));
controller.setEnabled(true);
controller.show();
mp.start();
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow MediaPlayer Buffering: " + percent + "%");
dismissProgressLoading();
}
#Override
public boolean onInfo(MediaPlayer mp, int whatInfo, int extra) {
//
dismissProgressLoading();
if(Constants.DEBUG)
{
if (whatInfo == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow Media Info, Media Info Bad Interleaving " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow Media Info, Media Info Not Seekable " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_UNKNOWN) {
Log.v(TAG, "Media Flow Media Info, Media Info Unknown " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Log.v(TAG, "Media Flow MediaInfo, Media Info Video Track Lagging " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
Log.v(TAG, "Media Flow MediaInfo, Media Info Metadata Update " + extra);
}
}
return false;
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
dismissProgressLoading();
StringBuilder sb = new StringBuilder();
sb.append("Media Player Error: ");
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
sb.append("Not Valid for Progressive Playback");
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
sb.append("Server Died");
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
sb.append("Media Error Unknown");
break;
default:
sb.append(" Non standard (");
sb.append(what);
sb.append(")");
}
//sb.append(" (" + what + ") ");
sb.append(extra);
showErrorDialog("Cannot play video", sb.toString());
return true;
}
void dismissProgressLoading() {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
#Override
public void onCompletion(MediaPlayer mp) {
if(Constants.DEBUG)
Log.v(TAG, "Media Flow onCompletion Called");
dismissProgressLoading();
onBackPressed();
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
final Runnable r = new Runnable() {
public void run() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()
&& mediaPlayer.getCurrentPosition() > 0) {
if(Constants.DEBUG)
Log.d(TAG, "isPlaying : " + mediaPlayer.isPlaying());
if(Constants.DEBUG)
Log.d(TAG,
"currentPosition : "
+ mediaPlayer.getCurrentPosition());
handler.sendEmptyMessage(0);
} else {
handler.postDelayed(this, 100);
}
}
}
};
Handler handler = new Handler() {
public void handleMessage(Message msg) {
dismissProgressLoading();
}
};
#Override
protected void onResume() {
if(Constants.SHOULD_FINISH_APPLICATION)
finish();
super.onResume();
}
#Override
protected void onRestart() {
super.onRestart();
}
protected void onPause() {
super.onPause();
pause();
}
#Override
protected void onDestroy() {
super.onDestroy();
dismissProgressLoading();
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
if(controller !=null)
{
controller.hide();
}
}
OnClickListener surViewClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (controller != null) {
if (controller.isShowing()) {
controller.hide();
} else {
controller.show();
}
}
}
};
#SuppressWarnings("deprecation")
void showErrorDialog(String title, String message) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
// Setting Dialog Title
alertDialog.setTitle(title);
// Setting Dialog Message
alertDialog.setMessage(message);
// Setting Icon to Dialog
alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
// Setting OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Write your code here to execute after dialog closed
dialog.dismiss();
finish();
}
});
// Showing Alert Message
if(this!= null && !this.isFinishing()){
alertDialog.show();
}
}
}
handleAspectRatio() {
int surfaceView_Width = surfaceView.getWidth();
int surfaceView_Height = surfaceView.getHeight();
float video_Width = mediaPlayer.getVideoWidth();
float video_Height = mediaPlayer.getVideoHeight();
float ratio_width = surfaceView_Width/video_Width;
float ratio_height = surfaceView_Height/video_Height;
float aspectratio = video_Width/video_Height;
LayoutParams layoutParams = surfaceView.getLayoutParams();
if (ratio_width > ratio_height){
layoutParams.width = (int) (surfaceView_Height * aspectratio);
layoutParams.height = surfaceView_Height;
}else{
layoutParams.width = surfaceView_Width;
layoutParams.height = (int) (surfaceView_Width / aspectratio);
}
surfaceView.setLayoutParams(layoutParams);
}
call above function before calling
mediaPlayer.start();
I met the same problem,after i look into VideoView source code in API 23,i found the good method,here is my solution,we can create a custom SurfaceView and override onMeasure(),then here you go,use VideoSurfaceView to play the video.
public class VideoSurfaceView extends SurfaceView implements MediaPlayer.OnVideoSizeChangedListener {
private int mVideoWidth;
private int mVideoHeight;
public VideoSurfaceView(Context context) {
super(context);
}
public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Set video size.
*
* #see MediaPlayer#getVideoWidth()
* #see MediaPlayer#getVideoHeight()
*/
public void setVideoSize(int videoWidth, int videoHeight) {
mVideoWidth = videoWidth;
mVideoHeight = videoHeight;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.i("####", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//Log.i("###", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//Log.i("###", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
setMeasuredDimension(width, height);
}
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
getHolder().setFixedSize(mVideoWidth, mVideoHeight);
requestLayout();
}
}
}
i have a shake listener as follows
public class ShakeListener implements SensorEventListener {
private String TAG = ShakeListener.class.getSimpleName();
private static final int FORCE_THRESHOLD = 800;
private static final int TIME_THRESHOLD = 100;
private static final int SHAKE_TIMEOUT = 500;
private static final int SHAKE_DURATION = 1000;
private static final int SHAKE_COUNT = 5;
private SensorManager mSensorMgr;
private float mLastX = -1.0f, mLastY = -1.0f, mLastZ = -1.0f;
private long mLastTime;
private OnShakeListener mShakeListener;
private Context mContext;
private int mShakeCount = 0;
private long mLastShake;
private long mLastForce;
public interface OnShakeListener {
public void onShake();
}
public ShakeListener(Context context) {
Log.d(TAG,"ShakeListener invoked---->");
mContext = context;
resume();
}
public void setOnShakeListener(OnShakeListener listener) {
mShakeListener = listener;
}
public void resume() {
mSensorMgr = (SensorManager) mContext
.getSystemService(Context.SENSOR_SERVICE);
if (mSensorMgr == null) {
throw new UnsupportedOperationException("Sensors not supported");
}
boolean supported = false;
try {
supported = mSensorMgr.registerListener(this,
mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
} catch (Exception e) {
Toast.makeText(mContext, "Shaking not supported", Toast.LENGTH_LONG)
.show();
}
if ((!supported) && (mSensorMgr != null))
mSensorMgr.unregisterListener(this);
}
public void pause() {
if (mSensorMgr != null) {
mSensorMgr.unregisterListener(this);
mSensorMgr = null;
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
long now = System.currentTimeMillis();
if ((now - mLastForce) > SHAKE_TIMEOUT) {
mShakeCount = 0;
}
if ((now - mLastTime) > TIME_THRESHOLD) {
long diff = now - mLastTime;
float speed = Math.abs(event.values[SensorManager.DATA_X]
+ event.values[SensorManager.DATA_Y]
+ event.values[SensorManager.DATA_Z] - mLastX - mLastY
- mLastZ)
/ diff * 10000;
if (speed > FORCE_THRESHOLD) {
if ((++mShakeCount >= SHAKE_COUNT)
&& (now - mLastShake > SHAKE_DURATION)) {
mLastShake = now;
mShakeCount = 0;
Log.d(TAG,"ShakeListener mShakeListener---->"+mShakeListener);
if (mShakeListener != null) {
mShakeListener.onShake();
}
}
mLastForce = now;
}
mLastTime = now;
mLastX = event.values[SensorManager.DATA_X];
mLastY = event.values[SensorManager.DATA_Y];
mLastZ = event.values[SensorManager.DATA_Z];
}}}
iam using this listener in one of my activity as ffollows
mShaker = new ShakeListener(this);
mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () {
public void onShake()
{
Intent myIntent = new Intent(myActivity.this, loginActivity.class);
startActivity(myIntent);
}
});
this shake should trigger only when iam on that particular activity..but it s triggering in all activities ,worse part is even when i close the app if i shake, the event is triggering and making the app open..Any help is appreciated.
add this method in your activity:
#Override
protected void finalize() throws Throwable {
try {
stop();
} catch (Exception e){
e.printStackTrace();
}
super.finalize();
}
public void stop(){
try {
sensorMgr.unregisterListener(this, mAccelerometer);
} catch (Exception e){
e.printStackTrace();
}
}