Changeset 4978


Ignore:
Timestamp:
Jan 27, 2015 5:01:15 AM (9 years ago)
Author:
ming
Message:

Re #1790: more Android OpenGL renderer

  • Fix RGBA color compatibility
  • Add autodetection feature to stop rendering for consecutive failures, such as when app is in the bg
  • Allow video stream to be created first and supply the output window later


Location:
pjproject/trunk/pjmedia/src/pjmedia-videodev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/android_opengl.c

    r4928 r4978  
    3636 
    3737#define MAX_JOBS 1 
     38/* Define the number of errors before the stream stops trying to do rendering. 
     39 * To disable this feature, put 0. 
     40 */ 
     41#define STOP_IF_ERROR_RENDERING 5 
    3842 
    3943extern JavaVM *pj_jni_jvm; 
     
    8791    job_queue              *jq; 
    8892    pj_bool_t               is_running; 
     93    pj_int32_t              err_rend; 
    8994    const pjmedia_frame    *frame; 
    9095     
     
    132137}; 
    133138 
    134 ANativeWindow *def_native_win = NULL; 
    135  
    136139static void get_jvm(JNIEnv **jni_env) 
    137140{ 
     
    139142} 
    140143 
    141 void android_opengl_set_surface(jobject surface) 
     144void* android_opengl_get_surface(jobject surface) 
    142145{ 
    143146    JNIEnv *env = 0; 
    144  
    145     PJ_LOG(4, (THIS_FILE, "Setting default OpenGL surface")); 
    146  
    147     if (!surface) { 
    148         def_native_win = NULL; 
    149     } else { 
    150         get_jvm(&env); 
    151         if (env) def_native_win = ANativeWindow_fromSurface(env, surface); 
    152     } 
     147    get_jvm(&env); 
     148    return ((env && surface)? ANativeWindow_fromSurface(env, surface): NULL); 
    153149} 
    154150 
     
    245241{ 
    246242    struct andgl_stream *stream = (struct andgl_stream *)data; 
    247  
     243     
     244    if (!stream->window || stream->err_rend == 0) 
     245        return PJ_SUCCESS; 
     246     
    248247    pjmedia_vid_dev_opengl_draw(stream->gl_buf, stream->vid_size.w, 
    249248                                stream->vid_size.h, stream->frame->buf); 
    250249         
    251     return eglSwapBuffers(stream->display, stream->surface); 
     250    if (!eglSwapBuffers(stream->display, stream->surface)) { 
     251        if (eglGetError() == EGL_BAD_SURFACE && stream->err_rend > 0) { 
     252            stream->err_rend--; 
     253            if (stream->err_rend == 0) { 
     254                PJ_LOG(3, (THIS_FILE, "Stopping OpenGL rendering due to " 
     255                                      "consecutive errors. If app is in bg," 
     256                                      "it's advisable to stop the stream.")); 
     257            } 
     258        } 
     259        return eglGetError(); 
     260    } 
     261     
     262    return PJ_SUCCESS; 
    252263} 
    253264 
     
    256267    struct andgl_stream *stream = (struct andgl_stream *)data; 
    257268 
    258     pjmedia_vid_dev_opengl_destroy_buffers(stream->gl_buf); 
    259  
    260     eglMakeCurrent(stream->display, EGL_NO_SURFACE, EGL_NO_SURFACE, 
    261                    EGL_NO_CONTEXT); 
    262     eglDestroyContext(stream->display, stream->context); 
    263     eglDestroySurface(stream->display, stream->surface); 
    264     eglTerminate(stream->display); 
     269    if (stream->gl_buf) { 
     270        pjmedia_vid_dev_opengl_destroy_buffers(stream->gl_buf); 
     271        stream->gl_buf = NULL; 
     272    } 
     273 
     274    if (stream->display != EGL_NO_DISPLAY) { 
     275        eglMakeCurrent(stream->display, EGL_NO_SURFACE, EGL_NO_SURFACE, 
     276                       EGL_NO_CONTEXT); 
     277        if (stream->context != EGL_NO_CONTEXT) 
     278            eglDestroyContext(stream->display, stream->context); 
     279        if (stream->surface != EGL_NO_SURFACE) 
     280            eglDestroySurface(stream->display, stream->surface); 
     281        eglTerminate(stream->display); 
     282    } 
     283     
     284    if (stream->window) { 
     285        ANativeWindow_release(stream->window); 
     286        stream->window = NULL; 
     287    } 
    265288     
    266289    stream->display = EGL_NO_DISPLAY; 
     
    288311    pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 
    289312    strm->user_data = user_data; 
     313    strm->display = EGL_NO_DISPLAY; 
    290314     
    291315    vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE); 
     
    297321    } 
    298322 
    299     if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 
    300         andgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW, 
    301                              param->window.info.android.window); 
    302     } else { 
    303         strm->window = def_native_win; 
    304     } 
    305      
    306     if (!strm->window) { 
    307         PJ_LOG(3, (THIS_FILE, "Unable to find output window nor surface")); 
    308         status = PJ_EINVAL; 
    309         goto on_error; 
    310     } 
    311      
    312323    /* Set video format */ 
    313324    status = andgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_FORMAT, 
     
    320331        goto on_error; 
    321332 
    322     job_queue_post_job(strm->jq, init_opengl, strm, 0, &status); 
    323     if (status != PJ_SUCCESS) 
     333    if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 
     334        status = andgl_stream_set_cap(&strm->base, 
     335                                      PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW, 
     336                                      &param->window); 
     337    } 
     338     
     339    if (status != PJ_SUCCESS) { 
     340        PJ_LOG(3, (THIS_FILE, "Failed to initialize OpenGL with the specified" 
     341                              " output window")); 
    324342        goto on_error; 
     343    } 
    325344 
    326345    /* Apply the remaining settings */ 
     
    417436        return PJ_SUCCESS; 
    418437    } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 
    419         strm->window = (ANativeWindow *)pval; 
    420         strm->param.window.info.android.window = (void *)pval; 
    421         return PJ_SUCCESS; 
     438        pj_bool_t is_running = strm->is_running; 
     439        pj_status_t status = PJ_SUCCESS; 
     440        pjmedia_vid_dev_hwnd *wnd = (pjmedia_vid_dev_hwnd *)pval; 
     441        ANativeWindow *native_wnd = (ANativeWindow *)wnd->info.android.window; 
     442 
     443        if (strm->window == native_wnd) 
     444            return PJ_SUCCESS; 
     445         
     446        /* Stop the stream and re-init OpenGL */ 
     447        andgl_stream_stop(s); 
     448        job_queue_post_job(strm->jq, deinit_opengl, strm, 0, NULL); 
     449 
     450        strm->window = strm->param.window.info.android.window = native_wnd; 
     451        if (strm->window) { 
     452            job_queue_post_job(strm->jq, init_opengl, strm, 0, &status); 
     453        } 
     454 
     455        PJ_LOG(3, (THIS_FILE, "Re-initializing OpenGL with window %p: %s", 
     456                              strm->window, 
     457                              (status == PJ_SUCCESS? "success": "failed"))); 
     458         
     459        if (is_running) 
     460            andgl_stream_start(s); 
     461 
     462        return status; 
    422463    } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE) { 
    423464        pj_memcpy(&strm->param.disp_size, pval, sizeof(strm->param.disp_size)); 
     
    438479    struct andgl_stream *stream = (struct andgl_stream*)strm; 
    439480     
     481    stream->err_rend = STOP_IF_ERROR_RENDERING; 
     482    if (!stream->err_rend) stream->err_rend = 0xFFFF; 
    440483    stream->is_running = PJ_TRUE; 
    441484    PJ_LOG(4, (THIS_FILE, "Starting Android opengl stream")); 
     
    451494    pj_status_t status; 
    452495 
    453     if (!stream->is_running) 
     496    if (!stream->is_running || !stream->window) 
    454497        return PJ_EINVALIDOP; 
    455498     
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/opengl_dev.c

    r4925 r4978  
    3030#       include <GLES2/gl2.h> 
    3131#       include <GLES2/gl2ext.h> 
    32 #       define GL_BGRA GL_RGBA 
     32#       undef GL_RGBA 
     33#       define GL_RGBA GL_BGRA_EXT 
     34#       define GL_BGRA GL_BGRA_EXT 
    3335#   else 
    3436#       include <OpenGLES/ES2/gl.h> 
Note: See TracChangeset for help on using the changeset viewer.