diff options
author | Liong Sauw Ming <ming@teluu.com> | 2014-09-22 07:03:25 +0000 |
---|---|---|
committer | Liong Sauw Ming <ming@teluu.com> | 2014-09-22 07:03:25 +0000 |
commit | 74e9fd84c72a87cc00e659eddb34b4f8f970a7b8 (patch) | |
tree | 511b7b83ad86f8e38d193d03428a5cbbb6d846ae /pjmedia | |
parent | 7e466f2b480ba0120aa15e9ca63edd18f7364af6 (diff) |
Re #1790: Use OpenGL textures instead of platform dependent textures.
This revision contains:
* remove the generation of iOS texture (instead directly use OpenGL textures)
* add iOS and Android window type
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4925 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/include/pjmedia-videodev/opengl_dev.h | 7 | ||||
-rw-r--r-- | pjmedia/include/pjmedia-videodev/videodev.h | 15 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-videodev/ios_opengl_dev.m | 89 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-videodev/opengl_dev.c | 94 |
4 files changed, 87 insertions, 118 deletions
diff --git a/pjmedia/include/pjmedia-videodev/opengl_dev.h b/pjmedia/include/pjmedia-videodev/opengl_dev.h index 750df8e5..3763b2f0 100644 --- a/pjmedia/include/pjmedia-videodev/opengl_dev.h +++ b/pjmedia/include/pjmedia-videodev/opengl_dev.h @@ -40,14 +40,13 @@ pjmedia_vid_dev_opengl_imp_create_stream(pj_pool_t *pool, typedef struct gl_buffers gl_buffers; /* Create OpenGL buffers. */ -void pjmedia_vid_dev_opengl_create_buffers(pj_pool_t *pool, +void pjmedia_vid_dev_opengl_create_buffers(pj_pool_t *pool, pj_bool_t direct, gl_buffers **glb); /* Initialize OpenGL buffers. */ pj_status_t pjmedia_vid_dev_opengl_init_buffers(gl_buffers *glb); /* Render a texture. */ -pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, - unsigned int texture, - unsigned int name); +pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb,unsigned int width, + unsigned int height, void *pixels); /* Destroy OpenGL buffers. */ void pjmedia_vid_dev_opengl_destroy_buffers(gl_buffers *glb); diff --git a/pjmedia/include/pjmedia-videodev/videodev.h b/pjmedia/include/pjmedia-videodev/videodev.h index d7def15b..0bcb1686 100644 --- a/pjmedia/include/pjmedia-videodev/videodev.h +++ b/pjmedia/include/pjmedia-videodev/videodev.h @@ -58,7 +58,17 @@ typedef enum pjmedia_vid_dev_hwnd_type /** * Native window handle on Windows. */ - PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS + PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS, + + /** + * Native view on iOS. + */ + PJMEDIA_VID_DEV_HWND_TYPE_IOS, + + /** + * Native window handle on Android. + */ + PJMEDIA_VID_DEV_HWND_TYPE_ANDROID } pjmedia_vid_dev_hwnd_type; @@ -90,6 +100,9 @@ typedef struct pjmedia_vid_dev_hwnd struct { void *window; /**< Window */ } ios; + struct { + void *window; /**< Native window */ + } android; void *window; } info; diff --git a/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m b/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m index 77ad6ba2..150fcad5 100644 --- a/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m +++ b/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m @@ -34,13 +34,12 @@ typedef struct iosgl_fmt_info { pjmedia_format_id pjmedia_format; - UInt32 iosgl_format; } iosgl_fmt_info; /* Supported formats */ static iosgl_fmt_info iosgl_fmts[] = { - {PJMEDIA_FORMAT_BGRA, kCVPixelFormatType_32BGRA} , + {PJMEDIA_FORMAT_BGRA} , }; @interface GLView : UIView @@ -65,14 +64,11 @@ struct iosgl_stream pj_timestamp frame_ts; unsigned ts_inc; pjmedia_rect_size vid_size; + const pjmedia_frame *frame; gl_buffers *gl_buf; GLView *gl_view; EAGLContext *ogl_context; - CVOpenGLESTextureCacheRef vid_texture; - CVImageBufferRef pb; - void *pb_addr; - CVOpenGLESTextureRef texture; }; @@ -153,7 +149,8 @@ static iosgl_fmt_info* get_iosgl_format_info(pjmedia_format_id id) } /* Create GL buffers */ - pjmedia_vid_dev_opengl_create_buffers(stream->pool, &stream->gl_buf); + pjmedia_vid_dev_opengl_create_buffers(stream->pool, PJ_FALSE, + &stream->gl_buf); [stream->ogl_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)[stream->gl_view layer]]; @@ -174,9 +171,8 @@ static iosgl_fmt_info* get_iosgl_format_info(pjmedia_format_id id) return; } - pjmedia_vid_dev_opengl_draw(stream->gl_buf, - (unsigned int)CVOpenGLESTextureGetTarget(stream->texture), - (unsigned int)CVOpenGLESTextureGetName(stream->texture)); + pjmedia_vid_dev_opengl_draw(stream->gl_buf, stream->vid_size.w, stream->vid_size.h, + stream->frame->buf); } @end @@ -193,7 +189,6 @@ pjmedia_vid_dev_opengl_imp_create_stream(pj_pool_t *pool, const pjmedia_video_format_detail *vfd; pj_status_t status = PJ_SUCCESS; CGRect rect; - CVReturn err; strm = PJ_POOL_ZALLOC_T(pool, struct iosgl_stream); pj_memcpy(&strm->param, param, sizeof(*param)); @@ -230,17 +225,6 @@ pjmedia_vid_dev_opengl_imp_create_stream(pj_pool_t *pool, goto on_error; } - /* Create a new CVOpenGLESTexture cache */ - err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, - strm->ogl_context, NULL, - &strm->vid_texture); - if (err) { - PJ_LOG(3, (THIS_FILE, "Unable to create OpenGL texture cache %d", - err)); - status = PJMEDIA_EVID_SYSERR; - goto on_error; - } - /* Apply the remaining settings */ if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW, @@ -343,13 +327,7 @@ static pj_status_t iosgl_stream_set_cap(pjmedia_vid_dev_stream *s, pj_memcpy(&strm->vid_size, &vfd->size, sizeof(vfd->size)); if (strm->param.disp_size.w == 0 || strm->param.disp_size.h == 0) pj_memcpy(&strm->param.disp_size, &vfd->size, sizeof(vfd->size)); - - /* Invalidate the buffer */ - if (strm->pb) { - CVPixelBufferRelease(strm->pb); - strm->pb = NULL; - } - + return PJ_SUCCESS; } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { UIView *view = (UIView *)pval; @@ -410,45 +388,8 @@ static pj_status_t iosgl_stream_put_frame(pjmedia_vid_dev_stream *strm, const pjmedia_frame *frame) { struct iosgl_stream *stream = (struct iosgl_stream*)strm; - CVReturn err; - - /* Pixel buffer will only create a wrapper for the frame's buffer, - * so if the frame buffer changes, we have to recreate pb - */ - if (!stream->pb || (frame->buf && stream->pb_addr != frame->buf)) { - if (stream->pb) { - CVPixelBufferRelease(stream->pb); - stream->pb = NULL; - } - err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, - stream->vid_size.w, - stream->vid_size.h, - kCVPixelFormatType_32BGRA, - frame->buf, - stream->vid_size.w * 4, - NULL, NULL, NULL, &stream->pb); - if (err) { - PJ_LOG(3, (THIS_FILE, "Unable to create pixel buffer %d", err)); - return PJMEDIA_EVID_SYSERR; - } - stream->pb_addr = frame->buf; - } - - /* Create a CVOpenGLESTexture from the CVImageBuffer */ - err=CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, - stream->vid_texture, - stream->pb, NULL, - GL_TEXTURE_2D, GL_RGBA, - stream->vid_size.w, - stream->vid_size.h, - GL_BGRA, - GL_UNSIGNED_BYTE, - 0, &stream->texture); - if (!stream->texture || err) { - PJ_LOG(3, (THIS_FILE, "Unable to create OpenGL texture %d", err)); - return PJMEDIA_EVID_SYSERR; - } + stream->frame = frame; /* Perform OpenGL drawing in the main thread. */ [stream->gl_view performSelectorOnMainThread:@selector(render) withObject:nil waitUntilDone:YES]; @@ -456,10 +397,6 @@ static pj_status_t iosgl_stream_put_frame(pjmedia_vid_dev_stream *strm, // ^{[stream->gl_view render];}); [stream->ogl_context presentRenderbuffer:GL_RENDERBUFFER]; - - /* Flush the CVOpenGLESTexture cache and release the texture */ - CVOpenGLESTextureCacheFlush(stream->vid_texture, 0); - CFRelease(stream->texture); return PJ_SUCCESS; } @@ -486,16 +423,6 @@ static pj_status_t iosgl_stream_destroy(pjmedia_vid_dev_stream *strm) iosgl_stream_stop(strm); - if (stream->pb) { - CVPixelBufferRelease(stream->pb); - stream->pb = NULL; - } - - if (stream->vid_texture) { - CFRelease(stream->vid_texture); - stream->vid_texture = NULL; - } - if ([EAGLContext currentContext] == stream->ogl_context) [EAGLContext setCurrentContext:nil]; diff --git a/pjmedia/src/pjmedia-videodev/opengl_dev.c b/pjmedia/src/pjmedia-videodev/opengl_dev.c index 7db7dba4..9dd26d37 100644 --- a/pjmedia/src/pjmedia-videodev/opengl_dev.c +++ b/pjmedia/src/pjmedia-videodev/opengl_dev.c @@ -26,8 +26,14 @@ #include <pjmedia-videodev/opengl_dev.h> #ifdef PJMEDIA_VIDEO_DEV_HAS_OPENGL_ES -# include <OpenGLES/ES2/gl.h> -# include <OpenGLES/ES2/glext.h> +# if PJ_ANDROID +# include <GLES2/gl2.h> +# include <GLES2/gl2ext.h> +# define GL_BGRA GL_RGBA +# else +# include <OpenGLES/ES2/gl.h> +# include <OpenGLES/ES2/glext.h> +# endif #else # include <GL/gl.h> # include <GL/glext.h> @@ -39,7 +45,11 @@ #define DEFAULT_HEIGHT 360 #define DEFAULT_FPS 15 -#define LOG(a) +#if PJ_ANDROID +# define LOG(a) PJ_LOG(3, (THIS_FILE, a)) +#else +# define LOG(a) +#endif enum { ATTRIB_VERTEX, @@ -69,12 +79,14 @@ void main() \ /* OpenGL buffers structure. */ struct gl_buffers { - GLuint frameBuf; - GLuint rendBuf; - GLuint directProg; - - int rendBufW; - int rendBufH; + GLuint frameBuf; + GLuint rendBuf; + GLuint rendTex; + GLuint directProg; + + int rendBufW; + int rendBufH; + pj_bool_t direct; }; /* Supported formats */ @@ -200,18 +212,23 @@ GLint create_program(const GLchar *vertSource, const GLchar *fragSource, return status; } -void pjmedia_vid_dev_opengl_create_buffers(pj_pool_t *pool, gl_buffers **glb) +void pjmedia_vid_dev_opengl_create_buffers(pj_pool_t *pool, pj_bool_t direct, + gl_buffers **glb) { gl_buffers *glbuf = PJ_POOL_ZALLOC_T(pool, gl_buffers); *glb = glbuf; glDisable(GL_DEPTH_TEST); - glGenFramebuffers(1, &glbuf->frameBuf); - glBindFramebuffer(GL_FRAMEBUFFER, glbuf->frameBuf); + if (!(glbuf->direct = direct)) { + glGenFramebuffers(1, &glbuf->frameBuf); + glBindFramebuffer(GL_FRAMEBUFFER, glbuf->frameBuf); + + glGenRenderbuffers(1, &glbuf->rendBuf); + glBindRenderbuffer(GL_RENDERBUFFER, glbuf->rendBuf); + } - glGenRenderbuffers(1, &glbuf->rendBuf); - glBindRenderbuffer(GL_RENDERBUFFER, glbuf->rendBuf); + glGenTextures(1, &glbuf->rendTex); } pj_status_t pjmedia_vid_dev_opengl_init_buffers(gl_buffers *glb) @@ -221,16 +238,18 @@ pj_status_t pjmedia_vid_dev_opengl_init_buffers(gl_buffers *glb) ATTRIB_TEXTUREPOSITON }; GLchar *attribName[NUM_ATTRIBUTES] = { "position", "texCoord" }; - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, - &glb->rendBufW); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, - &glb->rendBufH); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, glb->rendBuf); - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - LOG("Unable to create frame buffer"); - return -1; + if (!glb->direct ) { + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, + &glb->rendBufW); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, + &glb->rendBufH); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, glb->rendBuf); + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LOG("Unable to create frame buffer"); + return -1; + } } create_program(vertSrc, fragSrc, NUM_ATTRIBUTES, @@ -245,8 +264,8 @@ pj_status_t pjmedia_vid_dev_opengl_init_buffers(gl_buffers *glb) return PJ_SUCCESS; } -pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, unsigned int texture, - unsigned int name) +pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, unsigned int width, + unsigned int height, void *pixels) { static const GLfloat squareVertices[] = { -1.0f, -1.0f, @@ -257,10 +276,8 @@ pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, unsigned int texture, GLfloat textureVertices[] = { 0, 1, 1, 1, 0, 0, 1, 0 }; - GLenum tex = (GLenum) texture; - GLuint nam = (GLuint) name; - glBindTexture(tex, nam); + glBindTexture(GL_TEXTURE_2D, glb->rendTex); /* Set texture parameters */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -268,10 +285,17 @@ pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, unsigned int texture, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindFramebuffer(GL_FRAMEBUFFER, glb->frameBuf); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, + 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pixels); + + glFlush(); + + /* Do we render directly to the screen? */ + glBindFramebuffer(GL_FRAMEBUFFER, (glb->direct? 0: glb->frameBuf)); /* Set the view port to the entire view */ - glViewport(0, 0, glb->rendBufW, glb->rendBufH); + glViewport(0, 0, (glb->direct? width: glb->rendBufW), + (glb->direct? height: glb->rendBufH)); /* Draw the texture on the screen with OpenGL ES 2 */ /* Use program */ @@ -288,7 +312,8 @@ pj_status_t pjmedia_vid_dev_opengl_draw(gl_buffers *glb, unsigned int texture, glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); /* Present */ - glBindRenderbuffer(GL_RENDERBUFFER, glb->rendBuf); + if (!glb->direct) + glBindRenderbuffer(GL_RENDERBUFFER, glb->rendBuf); return PJ_SUCCESS; } @@ -305,6 +330,11 @@ void pjmedia_vid_dev_opengl_destroy_buffers(gl_buffers *glb) glb->rendBuf = 0; } + if (glb->rendTex) { + glDeleteTextures(1, &glb->rendTex); + glb->rendTex = 0; + } + if (glb->directProg) { glDeleteProgram(glb->directProg); glb->directProg = 0; |