opengl es 2.0 - OpenTok Android Lib How to Show publisher View (Camera Preview) in Round shape -
i using opentok android sdk 2.4+ (https://tokbox.com/developer/sdks/android/)
currently in sdk it's showing publisher(camera preview) in square area wants in round shape (publisher camera view in round shape).
note: publisherview using opengl glsurfaceview show camera preview.
i using attached "customvideorenderer.java" class extending class "basevideorenderer". not familiar opengl not able understand should change in code.
so please me out of it.. display publisher view in round shape.
public class customvideorenderer extends basevideorenderer { private context mcontext; private glsurfaceview mview; private myrenderer mrenderer; static class myrenderer implements glsurfaceview.renderer { int mtextureids[] = new int[3]; float[] mscalematrix = new float[16]; private floatbuffer mvertexbuffer; private floatbuffer mtexturebuffer; private shortbuffer mdrawlistbuffer; boolean mvideofitenabled = true; boolean mvideodisabled = false; // number of coordinates per vertex in array static final int coords_per_vertex = 3; static final int texturecoords_per_vertex = 2; static float mxyzcoords[] = {-1.0f, 1.0f, 0.0f, // top left -1.0f, -1.0f, 0.0f, // bottom left 1.0f, -1.0f, 0.0f, // bottom right 1.0f, 1.0f, 0.0f // top right }; static float muvcoords[] = {0, 0, // top left 0, 1, // bottom left 1, 1, // bottom right 1, 0}; // top right private short mvertexindex[] = {0, 1, 2, 0, 2, 3}; // order draw // vertices private final string vertexshadercode = "uniform mat4 umvpmatrix;" + "attribute vec4 aposition;\n" + "attribute vec2 atexturecoord;\n" + "varying vec2 vtexturecoord;\n" + "void main() {\n" + " gl_position = umvpmatrix * aposition;\n" + " vtexturecoord = atexturecoord;\n" + "}\n"; private final string fragmentshadercode = "precision mediump float;\n" + "uniform sampler2d ytex;\n" + "uniform sampler2d utex,vtex;\n" + "varying vec2 vtexturecoord;\n" + "void main(void) {\n" + " float nx,ny,r,g,b,y,u,v;\n" + " mediump vec4 txl,ux,vx;" + " nx=vtexturecoord[0];\n" + " ny=vtexturecoord[1];\n" + " y=texture2d(ytex,vec2(nx,ny)).r;\n" + " u=texture2d(utex,vec2(nx,ny)).r;\n" + " v=texture2d(vtex,vec2(nx,ny)).r;\n" + " y=1.0-1.1643*(y-0.0625);\n" // invert effect // + " y=1.1643*(y-0.0625);\n" // normal renderer + " u=u-0.5;\n" + " v=v-0.5;\n" + " r=y+1.5958*v;\n" + " g=y-0.39173*u-0.81290*v;\n" + " b=y+2.017*u;\n" + " gl_fragcolor=vec4(r,g,b,1.0);\n" + "}\n"; reentrantlock mframelock = new reentrantlock(); frame mcurrentframe; private int mprogram; private int mtexturewidth; private int mtextureheight; private int mviewportwidth; private int mviewportheight; public myrenderer() { bytebuffer bb = bytebuffer.allocatedirect(mxyzcoords.length * 4); bb.order(byteorder.nativeorder()); mvertexbuffer = bb.asfloatbuffer(); mvertexbuffer.put(mxyzcoords); mvertexbuffer.position(0); bytebuffer tb = bytebuffer.allocatedirect(muvcoords.length * 4); tb.order(byteorder.nativeorder()); mtexturebuffer = tb.asfloatbuffer(); mtexturebuffer.put(muvcoords); mtexturebuffer.position(0); bytebuffer dlb = bytebuffer.allocatedirect(mvertexindex.length * 2); dlb.order(byteorder.nativeorder()); mdrawlistbuffer = dlb.asshortbuffer(); mdrawlistbuffer.put(mvertexindex); mdrawlistbuffer.position(0); } @override public void onsurfacecreated(gl10 gl, eglconfig config) { gl.glclearcolor(0, 0, 0, 1); gles20.glclear(gles20.gl_color_buffer_bit); int vertexshader = loadshader(gles20.gl_vertex_shader,vertexshadercode); int fragmentshader = loadshader(gles20.gl_fragment_shader,fragmentshadercode); mprogram = gles20.glcreateprogram(); // create empty opengl es // program gles20.glattachshader(mprogram, vertexshader); // add vertex // shader program gles20.glattachshader(mprogram, fragmentshader); // add fragment // shader // program gles20.gllinkprogram(mprogram); int positionhandle = gles20.glgetattriblocation(mprogram, "aposition"); int texturehandle = gles20.glgetattriblocation(mprogram, "atexturecoord"); gles20.glvertexattribpointer(positionhandle, coords_per_vertex, gles20.gl_float, false, coords_per_vertex * 4, mvertexbuffer); gles20.glenablevertexattribarray(positionhandle); gles20.glvertexattribpointer(texturehandle, texturecoords_per_vertex, gles20.gl_float, false, texturecoords_per_vertex * 4, mtexturebuffer); gles20.glenablevertexattribarray(texturehandle); gles20.gluseprogram(mprogram); int = gles20.glgetuniformlocation(mprogram, "ytex"); gles20.gluniform1i(i, 0); /* bind ytex texture unit 0 */ = gles20.glgetuniformlocation(mprogram, "utex"); gles20.gluniform1i(i, 1); /* bind utex texture unit 1 */ = gles20.glgetuniformlocation(mprogram, "vtex"); gles20.gluniform1i(i, 2); /* bind vtex texture unit 2 */ mtexturewidth = 0; mtextureheight = 0; } static void initializetexture(int name, int id, int width, int height) { gles20.glactivetexture(name); gles20.glbindtexture(gles20.gl_texture_2d, id); gles20.gltexparameterf(gles20.gl_texture_2d, gles20.gl_texture_min_filter, gles20.gl_nearest); gles20.gltexparameterf(gles20.gl_texture_2d, gles20.gl_texture_mag_filter, gles20.gl_linear); gles20.gltexparameterf(gles20.gl_texture_2d, gles20.gl_texture_wrap_s, gles20.gl_clamp_to_edge); gles20.gltexparameterf(gles20.gl_texture_2d, gles20.gl_texture_wrap_t, gles20.gl_clamp_to_edge); gles20.glteximage2d(gles20.gl_texture_2d, 0, gles20.gl_luminance, width, height, 0, gles20.gl_luminance, gles20.gl_unsigned_byte, null); } void setuptextures(frame frame) { if (mtextureids[0] != 0) { gles20.gldeletetextures(3, mtextureids, 0); } gles20.glgentextures(3, mtextureids, 0); int w = frame.getwidth(); int h = frame.getheight(); int hw = (w + 1) >> 1; int hh = (h + 1) >> 1; initializetexture(gles20.gl_texture0, mtextureids[0], w, h); initializetexture(gles20.gl_texture1, mtextureids[1], hw, hh); initializetexture(gles20.gl_texture2, mtextureids[2], hw, hh); mtexturewidth = frame.getwidth(); mtextureheight = frame.getheight(); } void updatetextures(frame frame) { int width = frame.getwidth(); int height = frame.getheight(); int half_width = (width + 1) >> 1; int half_height = (height + 1) >> 1; int y_size = width * height; int uv_size = half_width * half_height; bytebuffer bb = frame.getbuffer(); // if reusing frame, make sure reset position , // limit bb.clear(); if (bb.remaining() == y_size + uv_size * 2) { bb.position(0); gles20.glpixelstorei(gles20.gl_unpack_alignment, 1); gles20.glpixelstorei(gles20.gl_pack_alignment, 1); gles20.glactivetexture(gles20.gl_texture0); gles20.glbindtexture(gles20.gl_texture_2d, mtextureids[0]); gles20.gltexsubimage2d(gles20.gl_texture_2d, 0, 0, 0, width, height, gles20.gl_luminance, gles20.gl_unsigned_byte, bb); bb.position(y_size); gles20.glactivetexture(gles20.gl_texture1); gles20.glbindtexture(gles20.gl_texture_2d, mtextureids[1]); gles20.gltexsubimage2d(gles20.gl_texture_2d, 0, 0, 0, half_width, half_height, gles20.gl_luminance, gles20.gl_unsigned_byte, bb); bb.position(y_size + uv_size); gles20.glactivetexture(gles20.gl_texture2); gles20.glbindtexture(gles20.gl_texture_2d, mtextureids[2]); gles20.gltexsubimage2d(gles20.gl_texture_2d, 0, 0, 0, half_width, half_height, gles20.gl_luminance, gles20.gl_unsigned_byte, bb); } else { mtexturewidth = 0; mtextureheight = 0; } } @override public void onsurfacechanged(gl10 gl, int width, int height) { gles20.glviewport(0, 0, width, height); mviewportwidth = width; mviewportheight = height; } @override public void ondrawframe(gl10 gl) { mframelock.lock(); if (mcurrentframe != null && !mvideodisabled) { gles20.gluseprogram(mprogram); if (mtexturewidth != mcurrentframe.getwidth() || mtextureheight != mcurrentframe.getheight()) { setuptextures(mcurrentframe); } updatetextures(mcurrentframe); matrix.setidentitym(mscalematrix, 0); float scalex = 1.0f, scaley = 1.0f; float ratio = (float) mcurrentframe.getwidth() / mcurrentframe.getheight(); float vratio = (float) mviewportwidth / mviewportheight; if (mvideofitenabled) { if (ratio > vratio) { scaley = vratio / ratio; } else { scalex = ratio / vratio; } } else { if (ratio < vratio) { scaley = vratio / ratio; } else { scalex = ratio / vratio; } } matrix.scalem(mscalematrix, 0, scalex * (mcurrentframe.ismirroredx() ? -1.0f : 1.0f), scaley, 1); int mmvpmatrixhandle = gles20.glgetuniformlocation(mprogram, "umvpmatrix"); gles20.gluniformmatrix4fv(mmvpmatrixhandle, 1, false, mscalematrix, 0); gles20.gldrawelements(gles20.gl_triangles, mvertexindex.length, gles20.gl_unsigned_short, mdrawlistbuffer); } else { //black frame when video disabled gl.glclearcolor(0, 0, 0, 1); gles20.glclear(gles20.gl_color_buffer_bit); } mframelock.unlock(); } public void displayframe(frame frame) { mframelock.lock(); if (this.mcurrentframe != null) { this.mcurrentframe.recycle(); } this.mcurrentframe = frame; mframelock.unlock(); } public static int loadshader(int type, string shadercode) { int shader = gles20.glcreateshader(type); gles20.glshadersource(shader, shadercode); gles20.glcompileshader(shader); return shader; } public void disablevideo(boolean b) { mframelock.lock(); mvideodisabled = b; if (mvideodisabled) { if (this.mcurrentframe != null) { this.mcurrentframe.recycle(); } this.mcurrentframe = null; } mframelock.unlock(); } public void enablevideofit(boolean enablevideofit) { mvideofitenabled = enablevideofit; } } public customvideorenderer(context context) { this.mcontext = context; mview = new glsurfaceview(context); mview.seteglcontextclientversion(2); mrenderer = new myrenderer(); mview.setrenderer(mrenderer); mview.setrendermode(glsurfaceview.rendermode_when_dirty); } @override public void onframe(frame frame) { mrenderer.displayframe(frame); mview.requestrender(); } @override public void setstyle(string key, string value) { if (basevideorenderer.style_video_scale.equals(key)) { if (basevideorenderer.style_video_fit.equals(value)) { mrenderer.enablevideofit(true); } else if (basevideorenderer.style_video_fill.equals(value)) { mrenderer.enablevideofit(false); } } } @override public void onvideopropertieschanged(boolean videoenabled) { mrenderer.disablevideo(!videoenabled); } @override public view getview() { return mview; } @override public void onpause() { mview.onpause(); } @override public void onresume() { mview.onresume(); }
}
Comments
Post a Comment