android视频自定义渲染,十、Android视频框架PlayerBase#渲染流程

时间: 2023-12-16 admin IT培训

android视频自定义渲染,十、Android视频框架PlayerBase#渲染流程

android视频自定义渲染,十、Android视频框架PlayerBase#渲染流程

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 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 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。

综上,可总结为渲染流程图如下:

渲染流程.png

下面我们来具体分析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对象在将要销毁前,该方法会被立即调用。