上一篇:https://www.jianshu.com/p/3f39c4652d5b
IPlayer接口中的两个渲染方法
public interface IPlayer {
void setDisplay(SurfaceHolder surfaceHolder);
void setSurface(Surface surface);
}
两个渲染方法分别使用了SurfaceHolder和Surface,位于/android/view/。
具体实现类AVPlayer:
public final class AVPlayer implements IPlayer{
private BaseInternalPlayer mInternalPlayer;
// 调用BaseInternalPlayer内置的setDisplay和setSurface方法来操作。
@Override
public void setDisplay(SurfaceHolder surfaceHolder) {
if(isPlayerAvailable())
mInternalPlayer.setDisplay(surfaceHolder);
}
@Override
public void setSurface(Surface surface) {
if(isPlayerAvailable())
mInternalPlayer.setSurface(surface);
}
}
上述代码调用BaseInternalPlayer内置的setDisplay和setSurface方法来操作,如果采用ExoMediaPlayer:
public class ExoMediaPlayer extends BaseInternalPlayer {
private SimpleExoPlayer mInternalPlayer;
// 调用SimpleExoPlayer 内置的setDisplay和setSurface方法来操作,再往下走就进入EXO源码了
@Override
public void setDisplay(SurfaceHolder surfaceHolder) {
mInternalPlayer.setVideoSurfaceHolder(surfaceHolder);
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_SURFACE_HOLDER_UPDATE, null);
}
@Override
public void setSurface(Surface surface) {
mInternalPlayer.setVideoSurface(surface);
submitPlayerEvent(OnPlayerEventListener.PLAYER_EVENT_ON_SURFACE_UPDATE, null);
}
}
上述代码调用了调用SimpleExoPlayer 内置的setDisplay和setSurface方法来操作,再往下走就进入EXO源码了,setDisplay将在下述的IRender接口中调用。
接口IRender
public interface IRender {
interface IRenderHolder{
void bindPlayer(IPlayer player);
}
}
举RenderSurfaceView为例子分析,RenderTextureView流程一样:
public class RenderSurfaceView extends SurfaceView implements IRender {
private static final class InternalRenderHolder implements IRenderHolder{
private WeakReference<SurfaceHolder> mSurfaceHolder;
public InternalRenderHolder(SurfaceHolder surfaceHolder){
this.mSurfaceHolder = new WeakReference<>(surfaceHolder);
}
@Override
public void bindPlayer(IPlayer player) {
if(player!=null && mSurfaceHolder.get()!=null){
player.setDisplay(mSurfaceHolder.get());
}
}
}
}
RenderSurfaceView中调用了player#setDisplay()方法。
回到BaseVideoView
public class MyVideoViewActivity extends AppCompatActivity {
private BaseVideoView mVideoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_video_view);
mVideoView = findViewById(R.id.myBaseVideoView);
DataSource dataSource = new DataSource(DataUtils.VIDEO_URL_09);
dataSource.setTitle("音乐和艺术如何改变世界");
mVideoView.setDataSource(dataSource);
mVideoView.start();
}
}
进入BaseVideoView#setDataSource()方法:
public class BaseVideoView extends FrameLayout implements IVideoView, IStyleSetter {
@Override
public void setDataSource(DataSource dataSource) {
//init AudioManager
requestAudioFocus();
//release render on data change.
releaseRender();
//Reconfigure the rendering view each time the resource is switched
// 每次切换资源时重新配置呈现视图
setRenderType(mRenderType);
//set data to player
mPlayer.setDataSource(dataSource);
}
}
继续进入BaseVideoView#setRenderType()方法,每次切换资源时重新配置呈现视图:
public class BaseVideoView extends FrameLayout implements IVideoView, IStyleSetter {
@Override
public void setRenderType(int renderType) {
boolean renderChange = mRenderType!=renderType;
if(!renderChange && mRender!=null && !mRender.isReleased())
return;
releaseRender();
switch (renderType){
case IRender.RENDER_TYPE_SURFACE_VIEW:
mRenderType = IRender.RENDER_TYPE_SURFACE_VIEW;
mRender = new RenderSurfaceView(getContext());
break;
default:
case IRender.RENDER_TYPE_TEXTURE_VIEW:
mRenderType = IRender.RENDER_TYPE_TEXTURE_VIEW;
mRender = new RenderTextureView(getContext());
((RenderTextureView)mRender).setTakeOverSurfaceTexture(true);
break;
}
//clear render holder
mRenderHolder = null;
mPlayer.setSurface(null);
mRender.updateAspectRatio(mAspectRatio);
// 设置渲染回调方法
mRender.setRenderCallback(mRenderCallback);
//update some params
mRender.updateVideoSize(mVideoWidth, mVideoHeight);
mRender.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
//update video rotation
mRender.setVideoRotation(mVideoRotation);
//add to container
mSuperContainer.setRenderView(mRender.getRenderView());
}
}
关于BaseVideoView#mRenderCallback源码如下,设置渲染回调方法:
//on render holder ready ,bind the player.
private void bindRenderHolder(IRender.IRenderHolder renderHolder){
if(renderHolder!=null)
renderHolder.bindPlayer(mPlayer);
}
private IRender.IRenderCallback mRenderCallback = new IRender.IRenderCallback() {
@Override
public void onSurfaceCreated(IRender.IRenderHolder renderHolder, int width, int height) {
//on surface create ,try to attach player.
mRenderHolder = renderHolder;
bindRenderHolder(mRenderHolder);
}
@Override
public void onSurfaceChanged(IRender.IRenderHolder renderHolder,
int format, int width, int height) {
}
@Override
public void onSurfaceDestroy(IRender.IRenderHolder renderHolder) {
}
};
其中onSurfaceCreated()方法中bindRenderHolder(mRenderHolder)中的renderHolder.bindPlayer(mPlayer),那么什么地方调用onSurfaceCreated()方法?位于RenderSurfaceView的内部类InternalSurfaceHolderCallback,mRenderCallback.onSurfaceCreated(new InternalRenderHolder(holder),0,0);
public class RenderSurfaceView extends SurfaceView implements IRender {
public RenderSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mRenderMeasure = new RenderMeasure();
getHolder().addCallback(new InternalSurfaceHolderCallback());
}
private IRenderCallback mRenderCallback;
private static final class InternalRenderHolder implements IRenderHolder{
private WeakReference<SurfaceHolder> mSurfaceHolder;
public InternalRenderHolder(SurfaceHolder surfaceHolder){
this.mSurfaceHolder = new WeakReference<>(surfaceHolder);
}
@Override
public void bindPlayer(IPlayer player) {
if(player!=null && mSurfaceHolder.get()!=null){
player.setDisplay(mSurfaceHolder.get());
}
}
}
private class InternalSurfaceHolderCallback implements SurfaceHolder.Callback{
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(mRenderCallback!=null){
mRenderCallback.onSurfaceCreated(new InternalRenderHolder(holder),0,0);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
}
此处还是用了InternalSurfaceHolderCallback继承了SurfaceHolder.Callback。
综上,可总结为渲染流程图如下:

下面我们来具体分析Android#Surface及其相关类。
Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback
(1)Surface
Surface是原始图像缓冲区(raw buffer)的一个句柄,而原始图像缓冲区是由屏幕图像合成器(screen compositor)管理的。
原生缓冲区(raw buffer)存储着当前窗口的像素数据。
当得到一个Surface对象时,同时会得到一个Canvas(画布)对象。
Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原生缓冲器以及其它方面的内容。
public class Surface implements Parcelable {
private final Canvas mCanvas = new CompatibleCanvas();
}
(2)SurfaceView
SurfaceView,顾名思义就是Surface的View,通过SurfaceView就可以看到Surface的部分或者全部的内容。
Surface是用通过SurfaceView才能展示其中的内容。从这个意思上来说,SurfaceView中的View之确切的含义应该是viewport即“视口”的意思。
另一方面,SurfaceView是Android中View的子类。事实上,在Android中所有用于界面展示的类皆为View的子类,包括那些不可见的、各种各样的Layout。
所以说,SurfaceView中的View有两个含义:
1、视口(viewport)的意思
2、SurfaceView是View的派生类
**(3)SurfaceHolder **
从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,代表用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显可以理解为MVC中的Controller(控制器)。这样看起来三者之间的关系就清楚了很多。
M:Surface.java 用于存放数据模型
V:SurfaceView.java 用来显示视图
C:SurfaceHolder.java 作为控制器的存在
(4)SurfaceHolder.Callback
前面已经讲到SurfaceHolder是一个接口,它通过回调方法的方式,让我们可以感知到Surface的创建、销毁或者改变。其实这一点是通过其内部的静态子接口SurfaceHolder.Callback来实现的。
SurfaceHolder.Callback中定义了三个接口方法:
public interface Callback {
public void surfaceCreated(SurfaceHolder holder);
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height);
public void surfaceDestroyed(SurfaceHolder holder);
}
1、public void surfaceChanged(SurfaceHolderholder, int format, int width, int height)
当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
2、public void surfaceCreated(SurfaceHolderholder)
当surface对象创建后,该方法就会被立即调用。
3、 public void surfaceDestroyed(SurfaceHolderholder)
当surface对象在将要销毁前,该方法会被立即调用。
网友评论