-
Notifications
You must be signed in to change notification settings - Fork 437
Simple usage
使用BaseVideoView对象,可写入xml布局中,也可用代码创建。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.kk.taurus.playerbase.widget.BaseVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
添加组件设置数据
mVideoView = findViewById(R.id.videoView);
mVideoView.setOnPlayerEventListener(this);
mVideoView.setOnReceiverEventListener(this);
ReceiverGroup receiverGroup = new ReceiverGroup();
receiverGroup.addReceiver(KEY_LOADING_COVER, new LoadingCover(context));
receiverGroup.addReceiver(KEY_CONTROLLER_COVER, new ControllerCover(context));
receiverGroup.addReceiver(KEY_COMPLETE_COVER, new CompleteCover(context));
receiverGroup.addReceiver(KEY_ERROR_COVER, new ErrorCover(context));
mVideoView.setReceiverGroup(receiverGroup);
//设置一个事件处理器
mVideoView.setEventHandler(new OnVideoViewEventHandler());
//设置DataSource
mVideoView.setDataSource(new DataSource("url...."));
mVideoView.start();
如果您想直接使用AVPlayer自己进行处理播放,那么大致步骤如下:
1.初始化一个AVPlayer对象。
2.初始化一个SuperContainer对象,将ReceiverGroup设置到SuperContainer中。
3.使用SuperContainer设置一个渲染视图Render,然后自己处理RenderCallBack并关联解码器。
代码如下:
SuperContainer mSuperContainer = new SuperContainer(context);
ReceiverGroup receiverGroup = new ReceiverGroup();
receiverGroup.addReceiver(KEY_LOADING_COVER, new LoadingCover(context));
receiverGroup.addReceiver(KEY_CONTROLLER_COVER, new ControllerCover(context));
receiverGroup.addReceiver(KEY_COMPLETE_COVER, new CompleteCover(context));
receiverGroup.addReceiver(KEY_ERROR_COVER, new ErrorCover(context));
mSuperContainer.setReceiverGroup(receiverGroup);
final RenderTextureView render = new RenderTextureView(mAppContext);
render.setTakeOverSurfaceTexture(true);
//....
mPlayer.setOnPlayerEventListener(new OnPlayerEventListener() {
@Override
public void onPlayerEvent(int eventCode, Bundle bundle) {
if(eventCode==OnPlayerEventListener.PLAYER_EVENT_ON_VIDEO_SIZE_CHANGE){
mVideoWidth = bundle.getInt(EventKey.INT_ARG1);
mVideoHeight = bundle.getInt(EventKey.INT_ARG2);
mVideoSarNum = bundle.getInt(EventKey.INT_ARG3);
mVideoSarDen = bundle.getInt(EventKey.INT_ARG4);
render.updateVideoSize(mVideoWidth, mVideoHeight);
render.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
}else if(eventCode==OnPlayerEventListener.PLAYER_EVENT_ON_VIDEO_ROTATION_CHANGED){
mVideoRotation = bundle.getInt(EventKey.INT_DATA);
render.setVideoRotation(mVideoRotation);
}else if(eventCode==OnPlayerEventListener.PLAYER_EVENT_ON_PREPARED){
bindRenderHolder(mRenderHolder);
}
//将事件分发给子视图
mSuperContainer.dispatchPlayEvent(eventCode, bundle);
}
});
mPlayer.setOnErrorEventListener(new OnErrorEventListener() {
@Override
public void onErrorEvent(int eventCode, Bundle bundle) {
//将事件分发给子视图
mSuperContainer.dispatchErrorEvent(eventCode, bundle);
}
});
mSuperContainer.setOnReceiverEventListener(mInternalReceiverEventListener);
render.setRenderCallback(new IRender.IRenderCallback() {
@Override
public void onSurfaceCreated(IRender.IRenderHolder renderHolder, int width, int height) {
mRenderHolder = renderHolder;
bindRenderHolder(mRenderHolder);
}
@Override
public void onSurfaceChanged(IRender.IRenderHolder renderHolder, int format, int width, int height) {
}
@Override
public void onSurfaceDestroy(IRender.IRenderHolder renderHolder) {
mRenderHolder = null;
}
});
mSuperContainer.setRenderView(render.getRenderView());
mPlayer.setDataSource(dataSource);
mPlayer.start();
具体参见项目代码 IjkPlayer。
使用前做如下配置:
PlayerConfig.addDecoderPlan(new DecoderPlan(1, IjkPlayer.class.getName(), "IjkPlayer"));
PlayerConfig.setDefaultPlanId(1);
解码器的切换
int PLAN_ID_IJK = 1;
mVideoView.switchDecoder(PLAN_ID_IJK);
mVideoView.setDataSource(dataSource);
mVideoView.start();
demo示例代码演示接入了Loading组件、Controller组件、CompleteCover组件。
这些组件均继承自父类BaseCover(覆盖层基类)
自定义覆盖层cover组件
public class CustomCover extends BaseCover{
public CustomCover(Context context) {
super(context);
}
@Override
public void onPlayerEvent(int eventCode, Bundle bundle) {
//...
}
@Override
public void onErrorEvent(int eventCode, Bundle bundle) {
//...
}
@Override
public void onReceiverEvent(int eventCode, Bundle bundle) {
//...
}
@Override
public View onCreateCoverView(Context context) {
return View.inflate(context, R.layout.layout_custom_cover, null);
}
//......
}
自定义组件的使用。
ReceiverGroup receiverGroup = new ReceiverGroup();
receiverGroup.addReceiver("loading_cover", new CustomCover(context));
mPlayer.setReceiverGroup(receiverGroup);
类似于今日头条等应用的列表播放效果,在列表中播放时无缝续播进入详情页或者无缝进入全屏页面。
原理:解码器动态关联不同的渲染视图(RenderView),比如使用MediaPlayer动态关联SurfaceView,就如同一个电脑主机不断连接不同的显示器。
版本3.2.0之后增加了关联助手,让无缝续播的使用更加简单化。使用关联播放时,您需要提供一个播放视图的容器。比如您要把正在view1容器中播放的画面切换到view2容器中,那么您只需要把view2的容器关联到助手即可。如下示例:
public class TestActivity extends AppcompatActivity{
RelationAssist mAssist;
ViewGroup view2;
public void onCreate(Bundle saveInstance){
super.onCreate(saveInstance);
//...
mAssist = new RelationAssist(this);
mAssist.setEventAssistHandler(eventHandler);
mReceiverGroup = ReceiverGroupManager.get().getLiteReceiverGroup(this);
mAssist.setReceiverGroup(mReceiverGroup);
DataSource dataSource = new DataSource();
dataSource.setData("http://...");
dataSource.setTitle("xxx");
mAssist.setDataSource(dataSource);
mAssist.attachContainer(mVideoContainer);
mAssist.play();
//...
switchPlay(view2);
}
private void switchPlay(ViewGroup container){
mAssist.attachContainer(container);
}
}
更加详细的操作请参见项目demo。
框架提供了一个WindowVideoView,如果您并不需要对Window进行无缝切播的话,请使用这个WindowVideoView,使用很简单,如下代码示例:
public class WindowVideoViewActivity extends AppCompatActivity {
WindowVideoView mWindowVideoView;
DataSource mDataSource;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_window_video_view);
int width = 640;
int height = 360;
mWindowVideoView = new WindowVideoView(this,
new FloatWindowParams()
.setX(100)
.setY(100)
.setWidth(width)
.setHeight(height)
.setGravity(Gravity.TOP | Gravity.LEFT));
mWindowVideoView.setBackgroundColor(Color.BLACK);
//...
mWindowVideoView.setReceiverGroup(receiverGroup);
mDataSource = new DataSource();
mDataSource.setData("http://...");
mDataSource.setTitle("xxx");
}
public void activeWindowVideoView(View view){
if(mWindowVideoView.isWindowShow()){
mWindowVideoView.close();
}else{
mWindowVideoView.show();
mWindowVideoView.setDataSource(mDataSource);
mWindowVideoView.start();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mWindowVideoView.close();
mWindowVideoView.stopPlayback();
}
}
如果您需要在Window模式下使用无缝续播,那么请将FloatWindow和RelationAssist二者结合使用。 此处不做代码展示,如需要可进入项目参见WindowSwitchPlayActivity中的代码示例。
数据提供者的定义是为了更好的进行播控统一的完整性而设计的。比如Server端给你的是id,你需要用id再去请求某个接口取播放的url,这时我们可以把由id到url这个过程统一的做一个处理,就由DataProvider来完成这个对接过程。
public class MonitorDataProvider extends BaseDataProvider {
@Override
public void handleSourceData(DataSource sourceData) {
//callback start
onProviderDataStart(sourceData);
loadData();
}
private void loadData(DataSource dataSource){
//...
if(sucess){
Bundle bundle = BundlePool.obtain();
bundle.putSerializable(EventKey.SERIALIZABLE_DATA, mDataSource);
//callback success
onProviderMediaDataSuccess(bundle);
}else{
//callback error
onProviderError(IDataProvider.PROVIDER_CODE_DATA_PROVIDER_ERROR, null);
}
}
@Override
public void cancel() {
//...
}
@Override
public void destroy() {
cancel();
}
}