总共有以下两层,下层为Video层(SurfaceView),上层为3D OpenGL层(View),Video全屏显示,3D无图形元素的地方透明,即可以看到下层的视频。
其主要功能为:1) 向Activity中增加一个SurfaceView,并使3D OpenGL层(View)位于最上面。
2) 播放视频
其完整原代码如下所示:
package org.cocos2dx.cpp;
import android.app.NativeActivity;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.view.ViewGroup;
import java.io.IOException;
public class Cocos2dxActivity extends NativeActivity{
private static final String TAG="MyGame";
private SurfaceView mediaPlayView;
private SurfaceHolder mediaSurfaceHolder = null;
private MediaPlayer mediaPlayer;
private boolean isMediaPlay = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate start...");
mediaPlayView = new SurfaceView(this);
mediaSurfaceHolder = mediaPlayView.getHolder();
mediaSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mediaSurfaceHolder.addCallback(new MediaSurfaceHolderCallBack());
LinearLayout.LayoutParams para = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
/*
LinearLayout.LayoutParams para = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
*/
//this.setContentView(mediaPlayView); // remove old views
this.addContentView(mediaPlayView,para); // keep old views
ViewGroup vg = (ViewGroup)mediaPlayView.getParent();
Log.d(TAG,"child count=" + vg.getChildCount());
/*
int count = vg.getChildCount();
for(int i=0; idelete
//EGL_GREEN_SIZE, 6, -->delete
//EGL_RED_SIZE, 5, -->delete
EGL_BUFFER_SIZE, 32, //-->new field
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};*/
//2.Set the format of window
getWindow().setFormat(PixelFormat.TRANSLUCENT);
}
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG,"onPrepared...");
int mVideoWidth = 0;
int mVideoHeight = 0;
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
mediaSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
mp.start();
//Log.d(TAG,"isPlaying: " + mediaPlayer.isPlaying());
//mediaPlayer.setLooping(true);
isMediaPlay = true;
}
};
private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
Log.d(TAG,"onCompletion...");
//isMediaPlay = false;
mp.seekTo(0);
mp.start();
}
};
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
private class MediaSurfaceHolderCallBack implements SurfaceHolder.Callback{
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.d(TAG,"surfaceChanged...,width="+width+", height="+height);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG,"surfaceCreated...");
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(mPreparedListener);
mediaPlayer.setOnCompletionListener(mCompletionListener);
try {
//mediaPlayer.setDataSource("/sdcard/video/aoa.mp4");
mediaPlayer.setDataSource("/sdcard/NativeMedia.ts");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setDisplay(mediaSurfaceHolder);
try {
mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if( mediaPlayer.isPlaying() ){
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
if( mediaSurfaceHolder != null ){
mediaSurfaceHolder = null;
}
}
}
}
其代码变化如下engine_init_display:
#if 0
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_BLUE_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_RED_SIZE, 5,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
#else
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
//EGL_BLUE_SIZE, 5, -->delete
//EGL_GREEN_SIZE, 6, -->delete
//EGL_RED_SIZE, 5, -->delete
EGL_BUFFER_SIZE, 32, //-->new field
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
#endif
在engine_draw_frame中增加一行代码:glClearColor(0.0f,0.0f,0.0f,0.0f);
static void engine_draw_frame(struct engine* engine) {
LOG_RENDER_DEBUG("engine_draw_frame(...)");
pthread_t thisthread = pthread_self();
LOG_RENDER_DEBUG("pthread_self() = %X", thisthread);
// add code to clear color buffer for transparency
glClearColor(0.0f,0.0f,0.0f,0.0f);
if (engine->display == NULL) {
// No display.
LOGW("engine_draw_frame : No display.");
return;
}
dispatch_pending_runnables();
cocos2d::Director::getInstance()->mainLoop();
LOG_RENDER_DEBUG("engine_draw_frame : just called cocos' mainLoop()");
/* // Just fill the screen with a color. */
/* glClearColor(((float)engine->state.x)/engine->width, engine->state.angle, */
/* ((float)engine->state.y)/engine->height, 1); */
/* glClear(GL_COLOR_BUFFER_BIT); */
if (s_pfEditTextCallback && editboxText)
{
s_pfEditTextCallback(editboxText, s_ctx);
free(editboxText);
editboxText = NULL;
}
eglSwapBuffers(engine->display, engine->surface);
}