Video Player based on GLSurfaceView

텍스처 있는 사각형 만들기까지 성공했다면, Android OpenGL ES에서 동영상 플레이어를 구현하는 방법자체는 간단합니다. SurfaceTexture에 대한 기본적인 내용을 알고 계시다면 더욱 이해하기 쉽습니다.

쉐이더 코드부터 차근차근 살펴보겠습니다.
버텍스 쉐이더코드는 텍스처 있는 사각형 만들기에 있던 것과 같아 생략합니다.

"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"varying vec2 v_texCoord;"+
"uniform samplerExternalOES s_texture;"+
"void main() {" +
"  gl_FragColor = texture2D(s_texture, v_texCoord);" +
"}";

위의 코드는 프레그먼트 쉐이더 코드 입니다. 달라진점을 보면 GL_OES_EGL_image_external 익스텐션이 추가되었다는 것입니다.  SurfaceTexture를 사용하여 Surface에 렌더링 된것은 OpenGL ES의 External Texture로 변환이 되는데, GL_OES_EGL_image_external 익스텐션은 OpenGL ES에서 지원하지 않는 내부 형식을 가진 EGLImage를 바인딩 할 수 있게 해줍니다. 

좀 더 자세한 내용은 이 익스텐션에 대한 크로노스의 문서스택오버플로의 관련 질의응답을 보시면 좋을 것 같습니다

동영상을 재생시키기 위한 준비를 하기위해 MediaPlayer를 이용했습니다.

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("동영상 경로");
mediaPlayer.prepare();
mediaPlayer.start();

동영상의 경로는 웹에 있는 sample-videos.com의 것을 사용했습니다.

https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4

동영상은 재생되었지만 화면에 그릴려면 Surface가 하나 필요합니다.

int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

SurfaceTexture surfaceTexture = new SurfaceTexture(textureId);
Surface surface = new Surface(surfaceTexture);
mediaPlayer.setSurface(surface);
surface.release();

texture를 하나 생성하여 SurfaceTexture를 만들고, SurfaceTexture를 통해 또 다시 Surface를 만듭니다. 해당 Surface를 MediaPlayer에게 넘겨주면 MediaPlayer에서 동영상을 Surface에 그리기 시작합니다.

Notice : OpenGL과 관련된 예를들면, 텍스쳐를 생성하고 바인딩 하는 작업은 GL Thread내에서 이루어져야 합니다.

이제 onDrawFrame()이 불릴때 SurfaceTexture 버퍼를 릴리즈 해줘야합니다.

surfaceTexture.updateTexImage();

해당 메소드를 호출하면 이미지 스트림에서 텍스처 이미지를 가장 최근의 프레임으로 업데이트 하게되고, 텍스처를 GL_TEXTURE_EXTERNAL_OES 텍스처 타겟에 암묵적으로 바인딩하게 됩니다.

동영상의 프레임 버퍼가 다 채워지기 전에 GL 쓰레드의 onDrawFrame이 호출 될 수 있습니다. GL쓰레드와 버퍼큐의 쓰레드를 동기화하고 싶다면 세마포어, synchnized 키워드 등을 이용하시면 됩니다.

본 프로젝트의 소스코드는 github에서 확인 하실 수 있습니다.

카테고리: Graphics

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.