前提
上一篇文章說到ffmpeg合成轉場效果,后來發現這樣的方案行不通的,一是合成時間太慢,而是需要實時的查看轉場的效果,所以應該要動態查看轉場的效果。所以用opengl實現轉場方案最合適不過了實現步驟:
圖片轉場:兩個圖片進行切換是,傳入前一張和當前張圖片的紋理到轉場的(transitionfilter)濾鏡中,在圖片切換的時候,展示transitionfilter
視頻轉場:截取當前視頻的第一幀和上一視頻的最后一幀圖片,同樣給transitionfilter賦值,在視頻切換的時候,顯示transitionfilter搭建環境注意點
因為用到opengl,所以得要用glsurfaview去承載渲染,對于視頻而言,根據相機用glsurfaview顯示一個道理
SurfaceTexture surfaceTexture = mOpenglDrawer.getSurfaceTexture();
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.
OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
requestRender();
}
});
Surface surface = new Surface(surfaceTexture);
mMediaPlayer.setSurface(surface);
if (isCurrentVideo()) {
mMediaPlayer.prepare();
mOpenglDrawer.setInputTextureVideo();
}
對于圖片,則手動去推動,按照一秒25幀默認,那么就是40ms推動一次渲染
剩下就是編寫opengl的fragment片段的事情了,不過對于視頻幀的轉場而言,需要對紋理進行轉化一下,因為最開始視頻進來的fragment定義的紋理對象是uniform samplerExternalOES vTexture;
所以需要創建一層FBO:
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
然后從FBO刷新出來的紋理便是sampler2D了,在用這個紋理去做transitionfilter的轉場
- 代碼演示
放一個最簡單的移動切換的fragment代碼:
varying vec2 textureCoordinate;
uniform float progress;
uniform sampler2D vTexture;
uniform sampler2D vTexture1;
uniform vec2 direction;
void main(){
vec2 p = textureCoordinate + progress*sign(direction);
float m =step(0.0, p.y) * step(p.y, 1.0) * step(0.0, p.x) * step(p.x, 1.0);
vec4 color = mix(texture2D(vTexture, textureCoordinate),
texture2D(vTexture1, textureCoordinate), m);
gl_FragColor = vec4(color);
}
豐富的轉場案例可以從這里得到:
https://gl-transitions.com/gallery
這個網站中,uv轉化成自己的紋理坐標, getFromColor(uv)換成自己的紋理:比如上面的我第一張紋理是texture2D(vTexture, textureCoordinate)
getToColor(uv)換成第二張紋理:對應我自己的是texture2D(vTexture1, textureCoordinate)
下篇文章介紹帶轉場效果、濾鏡的多視頻多圖片的視頻合成