在講代碼實(shí)現(xiàn)之前,我先講講TextureView, SurfaceTexture,OpenGL ES都是些什么鬼東西,我又是怎么使用這幾個(gè)東西來顯示一個(gè)視頻的。
TextureView 顧名思義也就是一個(gè)繼承了View的一個(gè)View控件而已,官網(wǎng)的解釋是這樣的:
A TextureView can be used to display a content stream. Such a content stream can for instance be a video or an OpenGL scene. The content stream can come from the application's process as well as a remote process.
它能夠去顯示一個(gè)內(nèi)容流,比如視頻流,OpenGL渲染的場景等。這些流可以是本地程序進(jìn)程也可以是遠(yuǎn)程進(jìn)程流,有點(diǎn)繞,我的理解就是,比如既可以是本地視頻流,也可以是網(wǎng)絡(luò)視頻流。
注意的是: TextureView 采用的是硬件加速器去渲染,就類似視頻的硬解碼跟軟解碼,一個(gè)靠的是GPU解碼,一個(gè)靠CPU解碼。
那么如何去使用這個(gè)TextureView呢?
OK,現(xiàn)在SurfaceTexture就要上場了,從這兩個(gè)類的命名我們就知道TextureView重點(diǎn)是View,而SurfaceTexture 重點(diǎn)是Texture它的官網(wǎng)解釋:
Captures frames from an image stream as an OpenGL ES texture.The image stream may come from either camera preview or video decode. *
也就是說它能捕獲一個(gè)圖像流的一幀來作為OpenGL 的texture也就是紋理。這個(gè)圖片流主要是來自相機(jī)的預(yù)覽或視頻的解碼。(我想這個(gè)特性是不應(yīng)該可以用來做很多事了)。
到這兒,texture也有了,那么OpenGL*也就可以出來干活了,它能夠綁定texture并將其在TextureView上一幀一幀的給繪制出來,就形成了我們所看到視頻圖像了(具體關(guān)于SurfaceTexture、TextureView大家可以參考這里)
說了這么,是該來點(diǎn)代碼來瞧瞧了,好的代碼就跟讀文學(xué)小說一樣,那樣的優(yōu)美,并不是說我寫的代碼很優(yōu)美啦,這只是追求。。。
代碼
先從MainActicity主類開始:
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener,
MediaPlayer.OnPreparedListener{
/**本地視頻的路徑*/
public String videoPath = Environment.getExternalStorageDirectory().getPath()+"/aoa.mkv";
private TextureView textureView;
private MediaPlayer mediaPlayer;
/**
* 視頻繪制前的配置就發(fā)生在這個(gè)對(duì)象所在類中.
* 真正的繪制工作則在它的子類中VideoTextureSurfaceRenderer
*/
private TextureSurfaceRenderer videoRenderer;
private int surfaceWidth;
private int surfaceHeight;
private Surface surface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView) findViewById(R.id.id_textureview);
//注冊(cè)一個(gè)SurfaceTexture,用于監(jiān)聽SurfaceTexure
textureView.setSurfaceTextureListener(this);
}
/**
* 播放視頻的入口,當(dāng)SurfaceTexure可得到時(shí)被調(diào)用
*/
private void playVideo() {
if (mediaPlayer == null) {
videoRenderer = new VideoTextureSurfaceRenderer(this, textureView.getSurfaceTexture(), surfaceWidth, surfaceHeight);
surface = new Surface(videoRenderer.getSurfaceTexture());
initMediaPlayer();
}
}
private void initMediaPlayer() {
this.mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(videoPath);
mediaPlayer.setSurface(surface);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setLooping(true);
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
@Override
public void onPrepared(MediaPlayer mp) {
try {
if (mp != null) {
mp.start(); //視頻開始播放了
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
if (textureView.isAvailable()) {
playVideo();
}
}
@Override
protected void onPause() {
super.onPause();
if (videoRenderer != null) {
videoRenderer.onPause(); //記得去停止視頻的繪制線程
}
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer =null;
}
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
surfaceWidth = width;
surfaceHeight = height;
playVideo();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
}
這就是程序的入口類,關(guān)于Mediaplayer是怎么播放時(shí)視頻源的,我就在此就不說了,這里面其實(shí)還有很多東西的,大家可以自行的查查。有一點(diǎn)我需要說說就是,一般MediaPlayer.setSurface(param)里面的參數(shù)param都是SurfaceView.SurfaceHolder,而我這兒直接用的是Surface (關(guān)于Surface可以參考這里),我這個(gè)視頻播放與其它的視頻播放的區(qū)別就在此。這篇先暫時(shí)寫在這兒啦,后續(xù)核心的繪制工作,就后面有空就再寫了。上面寫的如果有什么問題希望大家能多多指點(diǎn),感激不盡!
下一篇已寫好TextureView+SurfaceTexture+OpenGL ES來播放視頻(二)