package com.pili.pldroid.playerdemo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.pili.pldroid.player.AVOptions;
import com.pili.pldroid.player.PLMediaPlayer;
import com.pili.pldroid.player.widget.PLVideoView;
import com.pili.pldroid.playerdemo.utils.Utils;
import com.pili.pldroid.playerdemo.widget.MediaController;
/**
* This is a demo activity of PLVideoView
*/
public class PLVideoViewActivity extends VideoPlayerBaseActivity {
private static final String TAG = PLVideoViewActivity.class.getSimpleName();
private static final int MESSAGE_ID_RECONNECTING = 0x01;
private MediaController mMediaController;
private PLVideoView mVideoView;
private Toast mToast = null;
private String mVideoPath = null;
private int mDisplayAspectRatio = PLVideoView.ASPECT_RATIO_FIT_PARENT;
private boolean mIsActivityPaused = true;
private View mLoadingView;
private View mCoverView = null;
private int mIsLiveStreaming = 1;
private void setOptions(int codecType) {
AVOptions options = new AVOptions();
// the unit of timeout is ms
options.setInteger(AVOptions.KEY_PREPARE_TIMEOUT, 10 * 1000);
options.setInteger(AVOptions.KEY_GET_AV_FRAME_TIMEOUT, 10 * 1000);
options.setInteger(AVOptions.KEY_PROBESIZE, 128 * 1024);
// Some optimization with buffering mechanism when be set to 1
options.setInteger(AVOptions.KEY_LIVE_STREAMING, mIsLiveStreaming);
if (mIsLiveStreaming == 1) {
options.setInteger(AVOptions.KEY_DELAY_OPTIMIZATION, 1);
}
// 1 -> hw codec enable, 0 -> disable [recommended]
options.setInteger(AVOptions.KEY_MEDIACODEC, codecType);
// whether start play automatically after prepared, default value is 1
options.setInteger(AVOptions.KEY_START_ON_PREPARED, 0);
mVideoView.setAVOptions(options);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pl_video_view);
mVideoView = (PLVideoView) findViewById(R.id.VideoView);
mCoverView = (ImageView) findViewById(R.id.CoverView);
mVideoView.setCoverView(mCoverView);
mLoadingView = findViewById(R.id.LoadingView);
mVideoView.setBufferingIndicator(mLoadingView);
mLoadingView.setVisibility(View.VISIBLE);
mVideoPath = getIntent().getStringExtra("videoPath");
mIsLiveStreaming = getIntent().getIntExtra("liveStreaming", 1);
// 1 -> hw codec enable, 0 -> disable [recommended]
int codec = getIntent().getIntExtra("mediaCodec", AVOptions.MEDIA_CODEC_SW_DECODE);
setOptions(codec);
// Set some listeners
mVideoView.setOnInfoListener(mOnInfoListener);
mVideoView.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
mVideoView.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
mVideoView.setOnCompletionListener(mOnCompletionListener);
mVideoView.setOnSeekCompleteListener(mOnSeekCompleteListener);
mVideoView.setOnErrorListener(mOnErrorListener);
mVideoView.setVideoPath(mVideoPath);
// You can also use a custom `MediaController` widget
mMediaController = new MediaController(this, false, mIsLiveStreaming == 1);
mVideoView.setMediaController(mMediaController);
}
@Override
protected void onResume() {
super.onResume();
mIsActivityPaused = false;
mVideoView.start();
}
@Override
protected void onPause() {
super.onPause();
mToast = null;
mIsActivityPaused = true;
mVideoView.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mVideoView.stopPlayback();
}
public void onClickSwitchScreen(View v) {
mDisplayAspectRatio = (mDisplayAspectRatio + 1) % 5;
mVideoView.setDisplayAspectRatio(mDisplayAspectRatio);
switch (mVideoView.getDisplayAspectRatio()) {
case PLVideoView.ASPECT_RATIO_ORIGIN:
showToastTips("Origin mode");
break;
case PLVideoView.ASPECT_RATIO_FIT_PARENT:
showToastTips("Fit parent !");
break;
case PLVideoView.ASPECT_RATIO_PAVED_PARENT:
showToastTips("Paved parent !");
break;
case PLVideoView.ASPECT_RATIO_16_9:
showToastTips("16 : 9 !");
break;
case PLVideoView.ASPECT_RATIO_4_3:
showToastTips("4 : 3 !");
break;
default:
break;
}
}
private PLMediaPlayer.OnInfoListener mOnInfoListener = new PLMediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(PLMediaPlayer plMediaPlayer, int what, int extra) {
Log.d(TAG, "onInfo: " + what + ", " + extra);
return false;
}
};
private PLMediaPlayer.OnErrorListener mOnErrorListener = new PLMediaPlayer.OnErrorListener() {
@Override
public boolean onError(PLMediaPlayer plMediaPlayer, int errorCode) {
boolean isNeedReconnect = false;
Log.e(TAG, "Error happened, errorCode = " + errorCode);
switch (errorCode) {
case PLMediaPlayer.ERROR_CODE_INVALID_URI:
showToastTips("Invalid URL !");
break;
case PLMediaPlayer.ERROR_CODE_404_NOT_FOUND:
showToastTips("404 resource not found !");
break;
case PLMediaPlayer.ERROR_CODE_CONNECTION_REFUSED:
showToastTips("Connection refused !");
break;
case PLMediaPlayer.ERROR_CODE_CONNECTION_TIMEOUT:
showToastTips("Connection timeout !");
isNeedReconnect = true;
break;
case PLMediaPlayer.ERROR_CODE_EMPTY_PLAYLIST:
showToastTips("Empty playlist !");
break;
case PLMediaPlayer.ERROR_CODE_STREAM_DISCONNECTED:
showToastTips("Stream disconnected !");
isNeedReconnect = true;
break;
case PLMediaPlayer.ERROR_CODE_IO_ERROR:
showToastTips("Network IO Error !");
isNeedReconnect = true;
break;
case PLMediaPlayer.ERROR_CODE_UNAUTHORIZED:
showToastTips("Unauthorized Error !");
break;
case PLMediaPlayer.ERROR_CODE_PREPARE_TIMEOUT:
showToastTips("Prepare timeout !");
isNeedReconnect = true;
break;
case PLMediaPlayer.ERROR_CODE_READ_FRAME_TIMEOUT:
showToastTips("Read frame timeout !");
isNeedReconnect = true;
break;
case PLMediaPlayer.ERROR_CODE_HW_DECODE_FAILURE:
setOptions(AVOptions.MEDIA_CODEC_SW_DECODE);
isNeedReconnect = true;
break;
case PLMediaPlayer.MEDIA_ERROR_UNKNOWN:
break;
default:
showToastTips("unknown error !");
break;
}
// Todo pls handle the error status here, reconnect or call finish()
if (isNeedReconnect) {
sendReconnectMessage();
} else {
finish();
}
// Return true means the error has been handled
// If return false, then `onCompletion` will be called
return true;
}
};
private PLMediaPlayer.OnCompletionListener mOnCompletionListener = new PLMediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(PLMediaPlayer plMediaPlayer) {
Log.d(TAG, "Play Completed !");
showToastTips("Play Completed !");
finish();
}
};
private PLMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = new PLMediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(PLMediaPlayer plMediaPlayer, int precent) {
Log.d(TAG, "onBufferingUpdate: " + precent);
}
};
private PLMediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new PLMediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(PLMediaPlayer plMediaPlayer) {
Log.d(TAG, "onSeekComplete !");
}
};
private PLMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = new PLMediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(PLMediaPlayer plMediaPlayer, int width, int height, int videoSar, int videoDen) {
Log.d(TAG, "onVideoSizeChanged: width = " + width + ", height = " + height + ", sar = " + videoSar + ", den = " + videoDen);
}
};
private void showToastTips(final String tips) {
if (mIsActivityPaused) {
return;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(PLVideoViewActivity.this, tips, Toast.LENGTH_SHORT);
mToast.show();
}
});
}
protected Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what != MESSAGE_ID_RECONNECTING) {
return;
}
if (mIsActivityPaused || !Utils.isLiveStreamingAvailable()) {
finish();
return;
}
if (!Utils.isNetworkAvailable(PLVideoViewActivity.this)) {
sendReconnectMessage();
return;
}
mVideoView.setVideoPath(mVideoPath);
mVideoView.start();
}
};
private void sendReconnectMessage() {
showToastTips("正在重连...");
mLoadingView.setVisibility(View.VISIBLE);
mHandler.removeCallbacksAndMessages(null);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ID_RECONNECTING), 500);
}
}