Changeset 5047 for pjproject/trunk


Ignore:
Timestamp:
Apr 7, 2015 1:47:51 AM (10 years ago)
Author:
ming
Message:

Fixed #1835: Fixed crash in iOS OpenGL renderer when in background and assertion during destruction

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m

    r4925 r5047  
    3232#define THIS_FILE               "ios_opengl_dev.c" 
    3333 
     34/* If this is enabled, iOS OpenGL will not return error during creation when 
     35 * in the background. Instead, it will perform the initialization later 
     36 * during rendering. 
     37 */  
     38#define ALLOW_DELAYED_INITIALIZATION    0 
     39 
    3440typedef struct iosgl_fmt_info 
    3541{ 
     
    6167    void                   *user_data;          /**< Application data  */ 
    6268     
     69    pj_bool_t               is_running; 
    6370    pj_status_t             status; 
    6471    pj_timestamp            frame_ts; 
     
    6774    const pjmedia_frame    *frame; 
    6875     
    69     gl_buffers                  *gl_buf; 
    70     GLView                      *gl_view; 
    71     EAGLContext                 *ogl_context; 
     76    gl_buffers             *gl_buf; 
     77    GLView                 *gl_view; 
     78    EAGLContext            *ogl_context; 
    7279}; 
    7380 
     
    129136} 
    130137 
    131 - (void) init_buffers 
     138- (void) init_gl 
    132139{ 
    133140    /* Initialize OpenGL ES 2 */ 
     
    140147     nil]; 
    141148     
     149    /* EAGLContext initialization will crash if we are in background mode */ 
     150    if ([UIApplication sharedApplication].applicationState == 
     151        UIApplicationStateBackground) { 
     152        stream->status = PJMEDIA_EVID_INIT; 
     153        return; 
     154    } 
     155     
    142156    stream->ogl_context = [[EAGLContext alloc] initWithAPI: 
    143157                           kEAGLRenderingAPIOpenGLES2]; 
     
    145159        ![EAGLContext setCurrentContext:stream->ogl_context]) 
    146160    { 
     161        NSLog(@"Failed in initializing EAGLContext"); 
    147162        stream->status = PJMEDIA_EVID_SYSERR; 
    148163        return; 
     
    160175} 
    161176 
     177- (void)deinit_gl 
     178{ 
     179    if ([EAGLContext currentContext] == stream->ogl_context) 
     180        [EAGLContext setCurrentContext:nil]; 
     181     
     182    if (stream->ogl_context) { 
     183        [stream->ogl_context release]; 
     184        stream->ogl_context = NULL; 
     185    } 
     186     
     187    if (stream->gl_buf) { 
     188        pjmedia_vid_dev_opengl_destroy_buffers(stream->gl_buf); 
     189        stream->gl_buf = NULL; 
     190    } 
     191     
     192    [self removeFromSuperview]; 
     193} 
     194 
    162195- (void)render 
    163196{ 
     
    165198    if ([UIApplication sharedApplication].applicationState == 
    166199        UIApplicationStateBackground) 
     200    { 
    167201        return; 
    168      
     202    } 
     203 
     204#if ALLOW_DELAYED_INITIALIZATION 
     205    if (stream->status != PJ_SUCCESS) { 
     206        if (stream->status == PJMEDIA_EVID_INIT) { 
     207            [self init_gl]; 
     208            NSLog(@"Initializing OpenGL now %s", stream->status == PJ_SUCCESS? 
     209                  "success": "failed"); 
     210        } 
     211         
     212        return; 
     213    } 
     214#endif 
     215 
    169216    if (![EAGLContext setCurrentContext:stream->ogl_context]) { 
    170217        /* Failed to set context */ 
     
    174221    pjmedia_vid_dev_opengl_draw(stream->gl_buf, stream->vid_size.w, stream->vid_size.h, 
    175222                                stream->frame->buf); 
     223} 
     224 
     225- (void)finish_render 
     226{ 
     227    /* Do nothing. This function is serialized in the main thread, so when 
     228     * it is called, we can be sure that render() has completed. 
     229     */ 
    176230} 
    177231 
     
    219273    /* Perform OpenGL buffer initializations in the main thread. */ 
    220274    strm->status = PJ_SUCCESS; 
    221     [strm->gl_view performSelectorOnMainThread:@selector(init_buffers) 
     275    [strm->gl_view performSelectorOnMainThread:@selector(init_gl) 
    222276                                    withObject:nil waitUntilDone:YES]; 
    223     if ((status = strm->status) != PJ_SUCCESS) { 
    224         PJ_LOG(3, (THIS_FILE, "Unable to create and init OpenGL buffers")); 
    225         goto on_error; 
     277    if ((status = strm->status) != PJ_SUCCESS) 
     278    { 
     279        if (status == PJMEDIA_EVID_INIT) { 
     280            PJ_LOG(3, (THIS_FILE, "Failed to initialize iOS OpenGL because " 
     281                                  "we are in background")); 
     282#if !ALLOW_DELAYED_INITIALIZATION 
     283            goto on_error; 
     284#endif 
     285        } else { 
     286            PJ_LOG(3, (THIS_FILE, "Unable to create and init OpenGL buffers")); 
     287            goto on_error; 
     288        } 
    226289    } 
    227290     
     
    377440    struct iosgl_stream *stream = (struct iosgl_stream*)strm; 
    378441     
    379     PJ_UNUSED_ARG(stream); 
    380      
    381442    PJ_LOG(4, (THIS_FILE, "Starting ios opengl stream")); 
     443    stream->is_running = PJ_TRUE; 
    382444     
    383445    return PJ_SUCCESS; 
     
    389451{ 
    390452    struct iosgl_stream *stream = (struct iosgl_stream*)strm; 
     453     
     454    if (!stream->is_running) 
     455        return PJ_EINVALIDOP; 
    391456     
    392457    stream->frame = frame; 
     
    394459    [stream->gl_view performSelectorOnMainThread:@selector(render) 
    395460                           withObject:nil waitUntilDone:YES]; 
    396     //    dispatch_async(dispatch_get_main_queue(), 
    397     //                   ^{[stream->gl_view render];}); 
    398461     
    399462    [stream->ogl_context presentRenderbuffer:GL_RENDERBUFFER]; 
     
    407470    struct iosgl_stream *stream = (struct iosgl_stream*)strm; 
    408471     
    409     PJ_UNUSED_ARG(stream); 
    410      
    411472    PJ_LOG(4, (THIS_FILE, "Stopping ios opengl stream")); 
     473    stream->is_running = PJ_FALSE; 
     474 
     475    /* Wait until the rendering finishes */ 
     476    [stream->gl_view performSelectorOnMainThread:@selector(finish_render) 
     477                     withObject:nil waitUntilDone:YES]; 
    412478 
    413479    return PJ_SUCCESS; 
     
    422488    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    423489     
    424     iosgl_stream_stop(strm); 
    425      
    426     if ([EAGLContext currentContext] == stream->ogl_context) 
    427         [EAGLContext setCurrentContext:nil]; 
    428      
    429     if (stream->ogl_context) { 
    430         [stream->ogl_context release]; 
    431         stream->ogl_context = NULL; 
    432     } 
     490    if (stream->is_running) 
     491        iosgl_stream_stop(strm); 
    433492     
    434493    if (stream->gl_view) { 
    435         UIView *view = stream->gl_view; 
    436         dispatch_async(dispatch_get_main_queue(), 
    437                       ^{ 
    438                           [view removeFromSuperview]; 
    439                           [view release]; 
    440                        }); 
     494        [stream->gl_view performSelectorOnMainThread:@selector(deinit_gl) 
     495                         withObject:nil waitUntilDone:YES]; 
     496 
     497        [stream->gl_view release]; 
    441498        stream->gl_view = NULL; 
    442499    } 
    443500     
    444     pjmedia_vid_dev_opengl_destroy_buffers(stream->gl_buf); 
    445      
    446501    pj_pool_release(stream->pool); 
    447502     
Note: See TracChangeset for help on using the changeset viewer.