Ignore:
Timestamp:
Aug 24, 2011 5:54:25 AM (13 years ago)
Author:
ming
Message:

Re #1334:

  • Removed support for SDL 1.2
  • Add job queue inside SDL
File:
1 edited

Legend:

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

    r3715 r3718  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    1818 */ 
    19 #include <pjmedia/converter.h> 
    2019#include <pjmedia-videodev/videodev_imp.h> 
    2120#include <pj/assert.h> 
     
    2423 
    2524#if defined(PJMEDIA_VIDEO_DEV_HAS_SDL) && PJMEDIA_VIDEO_DEV_HAS_SDL != 0 
    26  
    27 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    28 #   include "TargetConditionals.h" 
    29 #   include <Foundation/Foundation.h> 
    30 #   define SDL_USE_ONE_THREAD_PER_DISPLAY 1 
    31 #elif defined(PJ_WIN32) && PJ_WIN32 != 0  
    32 #   define SDL_USE_ONE_THREAD_PER_DISPLAY 1 
    33 #else 
    34 #   define SDL_USE_ONE_THREAD_PER_DISPLAY 0 
    35 #endif 
    3625 
    3726#include <SDL.h> 
     
    4231#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    4332 
     33#if !(SDL_VERSION_ATLEAST(1,3,0)) 
     34#   error "SDL 1.3 or later is required" 
     35#endif 
     36 
     37#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
     38#   include "TargetConditionals.h" 
     39#   include <Foundation/Foundation.h> 
     40#endif 
     41 
    4442#define THIS_FILE               "sdl_dev.c" 
    4543#define DEFAULT_CLOCK_RATE      90000 
     
    4745#define DEFAULT_HEIGHT          480 
    4846#define DEFAULT_FPS             25 
    49  
    50 #if !(SDL_VERSION_ATLEAST(1,3,0)) 
    51 #   define SDL_PIXELFORMAT_RGBA8888 0 
    52 #   define SDL_PIXELFORMAT_RGB24    0 
    53 #   define SDL_PIXELFORMAT_BGRA8888 0 
    54 #   define SDL_PIXELFORMAT_ABGR8888 0 
    55 #   define SDL_PIXELFORMAT_BGR24    0 
    56 #   define SDL_PIXELFORMAT_ARGB8888 0 
    57 #   define SDL_PIXELFORMAT_RGB24    0 
    58 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 
    5947 
    6048typedef struct sdl_fmt_info 
     
    9886}; 
    9987 
    100 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    101 @interface SDLDelegate: NSObject 
    102 { 
    103     @public 
    104     struct sdl_stream       *strm; 
    105     struct sdl_factory      *sf; 
    106     pjmedia_event_type       ev_type; 
    107     pj_status_t              status; 
    108 } 
    109  
    110 - (void)sdl_init; 
    111 - (void)sdl_quit; 
    112 - (void)detect_fmt_change; 
    113 - (void)sdl_create; 
    114 - (void)sdl_destroy; 
    115 - (void)handle_event; 
    116 - (void)put_frame; 
    117 @end 
    118 #endif /* PJ_DARWINOS */ 
    119  
    12088/* sdl_ device info */ 
    12189struct sdl_dev_info 
     
    13199}; 
    132100 
     101#define MAX_JOBS 8 
     102 
     103typedef pj_status_t (*job_func_ptr)(void *data); 
     104 
     105typedef struct job { 
     106    job_func_ptr    func; 
     107    void           *data; 
     108    unsigned        flags; 
     109    pj_status_t     retval; 
     110} job; 
     111 
     112#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
     113@interface JQDelegate: NSObject 
     114{ 
     115    @public 
     116    job *pjob; 
     117} 
     118 
     119- (void)run_job; 
     120@end 
     121 
     122@implementation JQDelegate 
     123- (void)run_job 
     124{ 
     125    pjob->retval = (*pjob->func)(pjob->data); 
     126} 
     127@end 
     128#endif /* PJ_DARWINOS */ 
     129 
     130typedef struct job_queue { 
     131    job            *jobs[MAX_JOBS]; 
     132    pj_sem_t       *job_sem[MAX_JOBS]; 
     133    pj_mutex_t     *mutex; 
     134    pj_thread_t    *thread; 
     135    pj_sem_t       *sem; 
     136 
     137    int             head, tail; 
     138    pj_bool_t       is_full; 
     139    pj_bool_t       is_quitting; 
     140} job_queue; 
     141 
    133142/* sdl_ factory */ 
    134143struct sdl_factory 
     
    140149    unsigned                     dev_count; 
    141150    struct sdl_dev_info         *dev_info; 
     151    job_queue                   *jq; 
    142152 
    143153    pj_thread_t                 *sdl_thread;        /**< SDL thread.        */ 
    144     pj_status_t                  status; 
    145154    pj_sem_t                    *sem; 
    146155    pj_mutex_t                  *mutex; 
    147156    struct stream_list           streams; 
    148157    pj_bool_t                    is_quitting; 
     158    pj_thread_desc               thread_desc; 
     159    pj_thread_t                 *ev_thread; 
    149160}; 
    150161 
     
    159170    void                        *user_data;         /**< Application data.  */ 
    160171 
    161     pj_thread_t                 *sdl_thread;        /**< SDL thread.        */ 
    162     pj_bool_t                    is_initialized; 
    163     pj_bool_t                    is_quitting; 
    164     pj_bool_t                    is_destroyed; 
     172    struct sdl_factory          *sf; 
     173    const pjmedia_frame         *frame; 
    165174    pj_bool_t                    is_running; 
    166     pj_bool_t                    render_exited; 
    167     pj_status_t                  status; 
    168     pjmedia_format              *new_fmt; 
    169     pjmedia_rect_size           *new_disp_size; 
    170175    pj_timestamp                 last_ts; 
    171     pjmedia_frame                frame; 
    172     pj_size_t                    frame_buf_size; 
    173176    struct stream_list           list_entry; 
    174     struct sdl_factory          *sf; 
    175  
    176 #if SDL_VERSION_ATLEAST(1,3,0) 
     177 
    177178    SDL_Window                  *window;            /**< Display window.    */ 
    178179    SDL_Renderer                *renderer;          /**< Display renderer.  */ 
    179180    SDL_Texture                 *scr_tex;           /**< Screen texture.    */ 
    180181    int                          pitch;             /**< Pitch value.       */ 
    181 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    182182    SDL_Rect                     rect;              /**< Frame rectangle.   */ 
    183183    SDL_Rect                     dstrect;           /**< Display rectangle. */ 
    184     SDL_Surface                 *screen;            /**< Display screen.    */ 
    185     SDL_Surface                 *surf;              /**< RGB surface.       */ 
    186     SDL_Overlay                 *overlay;           /**< YUV overlay.       */ 
    187184#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    188 #   if SDL_VERSION_ATLEAST(1,3,0) 
    189185    SDL_GLContext               *gl_context; 
    190 #   endif /* SDL_VERSION_ATLEAST(1,3,0) */  
    191186    GLuint                       texture; 
    192187#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    193188 
    194189    pjmedia_video_apply_fmt_param vafp; 
    195 }; 
    196  
    197 struct sdl_dev_t 
    198 { 
    199     struct sdl_factory *sf; 
    200     struct sdl_stream  *strm; 
    201190}; 
    202191 
     
    234223static pj_status_t sdl_stream_destroy(pjmedia_vid_dev_stream *strm); 
    235224 
    236 static int sdl_thread(void * data); 
     225static pj_status_t resize_disp(struct sdl_stream *strm, 
     226                               pjmedia_rect_size *new_disp_size); 
     227static pj_status_t sdl_destroy_all(void *data); 
     228 
     229/* Job queue prototypes */ 
     230static pj_status_t job_queue_create(pj_pool_t *pool, job_queue **pjq); 
     231static pj_status_t job_queue_post_job(job_queue *jq, job_func_ptr func, 
     232                                      void *data, unsigned flags, 
     233                                      pj_status_t *retval); 
     234static pj_status_t job_queue_destroy(job_queue *jq); 
    237235 
    238236/* Operations */ 
     
    281279} 
    282280 
     281static pj_status_t sdl_init(void * data) 
     282{ 
     283    PJ_UNUSED_ARG(data); 
     284 
     285    if (SDL_Init(SDL_INIT_VIDEO)) { 
     286        PJ_LOG(3, (THIS_FILE, "Failed initializing SDL")); 
     287        return PJMEDIA_EVID_INIT; 
     288    } 
     289 
     290    return PJ_SUCCESS; 
     291} 
     292 
     293static struct sdl_stream* find_stream(struct sdl_factory *sf, 
     294                                      Uint32 windowID, 
     295                                      pjmedia_event *pevent) 
     296{ 
     297    struct stream_list *it, *itBegin; 
     298    struct sdl_stream *strm = NULL; 
     299 
     300    itBegin = &sf->streams; 
     301    for (it = itBegin->next; it != itBegin; it = it->next) { 
     302        if (SDL_GetWindowID(it->stream->window) == windowID) 
     303        { 
     304            strm = it->stream; 
     305            break; 
     306        } 
     307    } 
     308  
     309    if (strm) 
     310        pjmedia_event_init(pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 
     311                           &strm->base.epub); 
     312 
     313    return strm; 
     314} 
     315 
     316static pj_status_t handle_event(void *data) 
     317{ 
     318    struct sdl_factory *sf = (struct sdl_factory*)data; 
     319    SDL_Event sevent; 
     320 
     321    if (!pj_thread_is_registered()) 
     322        pj_thread_register("sdl_ev", sf->thread_desc, &sf->ev_thread); 
     323 
     324    while (SDL_PollEvent(&sevent)) { 
     325        struct sdl_stream *strm = NULL; 
     326        pjmedia_event pevent; 
     327 
     328        pj_mutex_lock(sf->mutex); 
     329        pevent.type = PJMEDIA_EVENT_NONE; 
     330        switch(sevent.type) { 
     331        case SDL_MOUSEBUTTONDOWN: 
     332            strm = find_stream(sf, sevent.button.windowID, &pevent); 
     333            pevent.type = PJMEDIA_EVENT_MOUSE_BTN_DOWN; 
     334            break; 
     335        case SDL_WINDOWEVENT: 
     336            strm = find_stream(sf, sevent.window.windowID, &pevent); 
     337            switch (sevent.window.event) { 
     338            case SDL_WINDOWEVENT_RESIZED: 
     339                pevent.type = PJMEDIA_EVENT_WND_RESIZED; 
     340                pevent.data.wnd_resized.new_size.w = 
     341                    sevent.window.data1; 
     342                pevent.data.wnd_resized.new_size.h = 
     343                    sevent.window.data2; 
     344                break; 
     345            case SDL_WINDOWEVENT_CLOSE: 
     346                pevent.type = PJMEDIA_EVENT_WND_CLOSING; 
     347                break; 
     348            } 
     349            break; 
     350        default: 
     351            break; 
     352        } 
     353 
     354        if (strm && pevent.type != PJMEDIA_EVENT_NONE) { 
     355            pj_status_t status; 
     356 
     357            pjmedia_event_publish(&strm->base.epub, &pevent); 
     358 
     359            switch (pevent.type) { 
     360            case PJMEDIA_EVENT_WND_RESIZED: 
     361                status = resize_disp(strm, &pevent.data.wnd_resized.new_size); 
     362                if (status != PJ_SUCCESS) 
     363                    PJ_LOG(3, (THIS_FILE, "Failed resizing the display.")); 
     364                break; 
     365            case PJMEDIA_EVENT_WND_CLOSING: 
     366                if (pevent.data.wnd_closing.cancel) { 
     367                    /* Cancel the closing operation */ 
     368                    break; 
     369                } 
     370 
     371                /* Proceed to cleanup SDL. App must still call 
     372                 * pjmedia_dev_stream_destroy() when getting WND_CLOSED 
     373                 * event 
     374                 */ 
     375                sdl_stream_stop(&strm->base); 
     376                sdl_destroy_all(strm); 
     377                pjmedia_event_init(&pevent, PJMEDIA_EVENT_WND_CLOSED, 
     378                                   &strm->last_ts, 
     379                                   &strm->base.epub); 
     380                pjmedia_event_publish(&strm->base.epub, &pevent); 
     381 
     382                /* 
     383                 * Note: don't access the stream after this point, it 
     384                 * might have been destroyed 
     385                 */ 
     386                break; 
     387            default: 
     388                /* Just to prevent gcc warning about unused enums */ 
     389                break; 
     390            } 
     391        } 
     392 
     393        pj_mutex_unlock(sf->mutex); 
     394    } 
     395 
     396    return PJ_SUCCESS; 
     397} 
     398 
     399static int sdl_ev_thread(void *data) 
     400{ 
     401    struct sdl_factory *sf = (struct sdl_factory*)data; 
     402 
     403    while(1) { 
     404        pj_status_t status; 
     405 
     406        pj_mutex_lock(sf->mutex); 
     407        if (pj_list_empty(&sf->streams)) { 
     408            pj_mutex_unlock(sf->mutex); 
     409            /* Wait until there is any stream. */ 
     410            pj_sem_wait(sf->sem); 
     411        } else 
     412            pj_mutex_unlock(sf->mutex); 
     413 
     414        if (sf->is_quitting) 
     415            break; 
     416 
     417        job_queue_post_job(sf->jq, handle_event, sf, 0, &status); 
     418 
     419        pj_thread_sleep(50); 
     420    } 
     421 
     422    return 0; 
     423} 
     424 
     425static pj_status_t sdl_quit(void *data) 
     426{ 
     427    PJ_UNUSED_ARG(data); 
     428    SDL_Quit(); 
     429    return PJ_SUCCESS; 
     430} 
     431 
    283432/* API: init factory */ 
    284433static pj_status_t sdl_factory_init(pjmedia_vid_dev_factory *f) 
     
    287436    struct sdl_dev_info *ddi; 
    288437    unsigned i, j; 
    289     struct sdl_dev_t sdl_dev; 
    290438    pj_status_t status; 
    291439    SDL_version version; 
     440 
     441    status = job_queue_create(sf->pool, &sf->jq); 
     442    if (status != PJ_SUCCESS) 
     443        return PJMEDIA_EVID_INIT; 
     444 
     445    job_queue_post_job(sf->jq, sdl_init, NULL, 0, &status); 
     446    if (status != PJ_SUCCESS) 
     447        return status; 
    292448 
    293449    pj_list_init(&sf->streams); 
     
    301457        return status; 
    302458 
    303     sf->status = PJ_EUNKNOWN; 
    304     sdl_dev.sf = sf; 
    305     sdl_dev.strm = NULL; 
    306     status = pj_thread_create(sf->pool, "sdl_thread", sdl_thread, 
    307                               &sdl_dev, 0, 0, &sf->sdl_thread); 
    308     if (status != PJ_SUCCESS) { 
    309         return PJMEDIA_EVID_INIT; 
    310     } 
    311  
    312     while (sf->status == PJ_EUNKNOWN) 
    313         pj_thread_sleep(10); 
    314  
    315     if (sf->status != PJ_SUCCESS) 
    316         return sf->status; 
     459    /* Create event handler thread. */ 
     460    status = pj_thread_create(sf->pool, "sdl_thread", sdl_ev_thread, 
     461                              sf, 0, 0, &sf->sdl_thread); 
     462    if (status != PJ_SUCCESS) 
     463        return status; 
    317464 
    318465    sf->dev_count = 1; 
     
    346493        ddi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT | 
    347494                         PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE; 
    348 #if SDL_VERSION_ATLEAST(1,3,0) 
    349495        ddi->info.caps |= PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW; 
    350 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    351496 
    352497        for (j = 0; j < ddi->info.fmt_cnt; j++) { 
     
    370515    struct sdl_factory *sf = (struct sdl_factory*)f; 
    371516    pj_pool_t *pool = sf->pool; 
     517    pj_status_t status; 
    372518 
    373519    pj_assert(pj_list_empty(&sf->streams)); 
     
    388534        sf->sem = NULL; 
    389535    } 
     536 
     537    job_queue_post_job(sf->jq, sdl_quit, NULL, 0, &status); 
     538    job_queue_destroy(sf->jq); 
    390539 
    391540    sf->pool = NULL; 
     
    462611} 
    463612 
    464 static void sdl_destroy(struct sdl_stream *strm, pj_bool_t destroy_win) 
    465 { 
    466     PJ_UNUSED_ARG(destroy_win); 
    467  
    468     if (strm->surf) { 
    469         SDL_FreeSurface(strm->surf); 
    470         strm->surf = NULL; 
    471     } 
    472     if (strm->overlay) { 
    473         SDL_FreeYUVOverlay(strm->overlay); 
    474         strm->overlay = NULL; 
    475     } 
     613static pj_status_t sdl_destroy(void *data) 
     614{ 
     615    struct sdl_stream *strm = (struct sdl_stream *)data; 
     616 
    476617#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    477618    if (strm->texture) { 
     
    479620        strm->texture = 0; 
    480621    } 
    481 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    482 #if SDL_VERSION_ATLEAST(1,3,0) 
    483 #   if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    484622    if (strm->gl_context) { 
    485623        SDL_GL_DeleteContext(strm->gl_context); 
    486624        strm->gl_context = NULL; 
    487625    } 
    488 #   endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
     626#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    489627    if (strm->scr_tex) { 
    490628        SDL_DestroyTexture(strm->scr_tex); 
     
    495633        strm->renderer = NULL; 
    496634    } 
    497 #   if !defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE == 0 
    498     if (destroy_win) { 
    499         if (strm->window && 
    500             !(strm->param.flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW)) 
    501         { 
    502             SDL_DestroyWindow(strm->window); 
    503         } 
    504         strm->window = NULL; 
    505     } 
    506 #   endif /* TARGET_OS_IPHONE */ 
    507 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    508 } 
    509  
    510 static pj_status_t sdl_create_view(struct sdl_stream *strm, 
    511                                    pjmedia_format *fmt) 
    512 { 
    513     sdl_fmt_info *sdl_info = get_sdl_format_info(fmt->id); 
     635 
     636    return PJ_SUCCESS; 
     637} 
     638 
     639static pj_status_t sdl_destroy_all(void *data) 
     640{ 
     641    struct sdl_stream *strm = (struct sdl_stream *)data; 
     642 
     643    sdl_destroy(data); 
     644#if !defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE == 0 
     645    if (strm->window && 
     646        !(strm->param.flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW)) 
     647    { 
     648        SDL_DestroyWindow(strm->window); 
     649    } 
     650    strm->window = NULL; 
     651#endif /* TARGET_OS_IPHONE */ 
     652 
     653    return PJ_SUCCESS; 
     654} 
     655 
     656static pj_status_t sdl_create_rend(struct sdl_stream * strm, 
     657                                   pjmedia_format *fmt) 
     658{ 
     659    sdl_fmt_info *sdl_info; 
    514660    const pjmedia_video_format_info *vfi; 
    515661    pjmedia_video_format_detail *vfd; 
    516662 
     663    fmt = &strm->param.fmt; 
     664    sdl_info = get_sdl_format_info(fmt->id); 
    517665    vfi = pjmedia_get_video_format_info(pjmedia_video_format_mgr_instance(), 
    518666                                        fmt->id); 
     
    537685    strm->dstrect.h = (Uint16)strm->param.disp_size.h; 
    538686 
    539     sdl_destroy(strm, PJ_FALSE); 
    540  
    541 #if SDL_VERSION_ATLEAST(1,3,0) 
     687    sdl_destroy(strm); 
     688 
     689#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     690    if (strm->param.rend_id == OPENGL_DEV_IDX) { 
     691        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); 
     692    } 
     693#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
     694 
    542695    if (!strm->window) { 
    543         Uint32 flags = SDL_WINDOW_SHOWN | /*SDL_WINDOW_RESIZABLE*/ 
    544                        SDL_WINDOW_BORDERLESS; 
    545  
    546 #   if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     696        Uint32 flags = /*SDL_WINDOW_RESIZABLE; */ SDL_WINDOW_BORDERLESS; 
     697 
     698        if (!((strm->param.flags & PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE) && 
     699            strm->param.window_hide)) 
     700            flags |= SDL_WINDOW_SHOWN; 
     701 
     702#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    547703        if (strm->param.rend_id == OPENGL_DEV_IDX) 
    548704            flags |= SDL_WINDOW_OPENGL; 
    549 #   endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
     705#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    550706 
    551707        if (strm->param.flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 
    552708            /* Use the window supplied by the application. */ 
    553             strm->window = SDL_CreateWindowFrom(strm->param.window.info.window); 
     709            strm->window = SDL_CreateWindowFrom( 
     710                               strm->param.window.info.window); 
    554711        } else { 
    555712            /* Create the window where we will draw. */ 
     
    565722    } 
    566723 
    567     SDL_SetWindowSize(strm->window, strm->param.disp_size.w, 
    568                       strm->param.disp_size.h); 
    569  
    570724    /** 
    571725      * We must call SDL_CreateRenderer in order for draw calls to 
     
    576730        return PJMEDIA_EVID_SYSERR; 
    577731 
    578 #   if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     732#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    579733    if (strm->param.rend_id == OPENGL_DEV_IDX) { 
    580734        strm->gl_context = SDL_GL_CreateContext(strm->window); 
     
    582736            return PJMEDIA_EVID_SYSERR; 
    583737        SDL_GL_MakeCurrent(strm->window, strm->gl_context); 
    584     } 
    585 #   endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    586  
    587     strm->screen = SDL_GetWindowSurface(strm->window); 
    588  
    589 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    590     /* Initialize the display */ 
    591     strm->screen = SDL_SetVideoMode(strm->param.disp_size.w,  
    592                                     strm->param.disp_size.h, 0, ( 
    593 #   if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    594                                     strm->param.rend_id == OPENGL_DEV_IDX? 
    595                                     SDL_OPENGL | SDL_RESIZABLE: 
    596 #   endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    597                                     SDL_RESIZABLE | SDL_SWSURFACE)); 
    598     if (strm->screen == NULL) 
    599         return PJMEDIA_EVID_SYSERR; 
    600  
    601     SDL_WM_SetCaption("pjmedia-SDL video", NULL); 
    602  
    603 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    604  
    605 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    606     if (strm->param.rend_id == OPENGL_DEV_IDX) { 
    607         /* Init some OpenGL settings */ 
     738 
     739        /* Init some OpenGL settings */ 
    608740        glDisable(GL_DEPTH_TEST); 
    609741        glDisable(GL_CULL_FACE); 
     
    629761    } else 
    630762#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    631 #if SDL_VERSION_ATLEAST(1,3,0) 
    632763    {     
    633764        strm->scr_tex = SDL_CreateTexture(strm->renderer, sdl_info->sdl_format, 
     
    639770        strm->pitch = strm->rect.w * SDL_BYTESPERPIXEL(sdl_info->sdl_format); 
    640771    } 
    641 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    642     if (vfi->color_model == PJMEDIA_COLOR_MODEL_RGB) { 
    643         strm->surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 
    644                                           strm->rect.w, strm->rect.h, 
    645                                           vfi->bpp, 
    646                                           sdl_info->Rmask, 
    647                                           sdl_info->Gmask, 
    648                                           sdl_info->Bmask, 
    649                                           sdl_info->Amask); 
    650         if (strm->surf == NULL) 
    651             return PJMEDIA_EVID_SYSERR; 
    652     } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) { 
    653         strm->overlay = SDL_CreateYUVOverlay(strm->rect.w, strm->rect.h, 
    654                                              sdl_info->sdl_format, 
    655                                              strm->screen); 
    656         if (strm->overlay == NULL) 
    657             return PJMEDIA_EVID_SYSERR; 
    658     } 
    659 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    660  
    661     if (strm->vafp.framebytes > strm->frame_buf_size) { 
    662         strm->frame_buf_size = strm->vafp.framebytes; 
    663         strm->frame.buf = pj_pool_alloc(strm->pool, strm->vafp.framebytes); 
    664     } 
    665  
    666     return PJ_SUCCESS; 
    667 } 
    668  
    669 static pj_status_t sdl_create(struct sdl_stream *strm) 
    670 { 
    671     strm->is_initialized = PJ_TRUE; 
    672  
    673 #if !(SDL_VERSION_ATLEAST(1,3,0)) 
    674     if (SDL_Init(SDL_INIT_VIDEO)) { 
    675         strm->status = PJMEDIA_EVID_INIT; 
    676         return strm->status; 
    677     } 
    678 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 
    679  
     772 
     773    return PJ_SUCCESS; 
     774} 
     775 
     776static pj_status_t sdl_create(void *data) 
     777{ 
     778    struct sdl_stream *strm = (struct sdl_stream *)data; 
     779    return sdl_create_rend(strm, &strm->param.fmt); 
     780} 
     781 
     782static pj_status_t resize_disp(struct sdl_stream *strm, 
     783                               pjmedia_rect_size *new_disp_size) 
     784{ 
     785    pj_memcpy(&strm->param.disp_size, new_disp_size, 
     786              sizeof(strm->param.disp_size)); 
     787     
     788    if (strm->scr_tex) { 
     789        strm->dstrect.x = strm->dstrect.y = 0; 
     790        strm->dstrect.w = (Uint16)strm->param.disp_size.w; 
     791        strm->dstrect.h = (Uint16)strm->param.disp_size.h; 
     792        SDL_RenderSetViewport(strm->renderer, &strm->dstrect); 
     793    } 
    680794#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    681     if (strm->param.rend_id == OPENGL_DEV_IDX) { 
    682         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); 
     795    else if (strm->param.rend_id == OPENGL_DEV_IDX) { 
     796        sdl_create_rend(strm, &strm->param.fmt); 
    683797    } 
    684798#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    685799 
    686     strm->status = sdl_create_view(strm, &strm->param.fmt); 
    687     return strm->status; 
    688 } 
    689  
    690 static void detect_fmt_change(struct sdl_stream *strm) 
    691 { 
    692     strm->status = PJ_SUCCESS; 
    693     if (strm->new_fmt || strm->new_disp_size) { 
    694         if (strm->new_disp_size) { 
    695             pj_memcpy(&strm->param.disp_size, strm->new_disp_size, 
    696                       sizeof(strm->param.disp_size)); 
    697 #if SDL_VERSION_ATLEAST(1,3,0) 
    698             if (strm->scr_tex) { 
    699                 strm->dstrect.x = strm->dstrect.y = 0; 
    700                 strm->dstrect.w = (Uint16)strm->param.disp_size.w; 
    701                 strm->dstrect.h = (Uint16)strm->param.disp_size.h; 
    702                 SDL_RenderSetViewport(strm->renderer, &strm->dstrect); 
    703                 strm->new_fmt = NULL; 
    704                 strm->new_disp_size = NULL; 
    705                 return; 
    706             } 
    707 #endif 
    708         } 
    709  
    710         /* Re-initialize SDL */ 
    711         strm->status = sdl_create_view(strm, (strm->new_fmt? strm->new_fmt : 
    712                                        &strm->param.fmt)); 
    713  
    714         if (strm->status == PJ_SUCCESS) { 
    715             if (strm->new_fmt) 
    716                 pjmedia_format_copy(&strm->param.fmt, strm->new_fmt); 
    717         } 
    718         strm->new_fmt = NULL; 
    719         strm->new_disp_size = NULL; 
    720     } 
    721 } 
    722  
    723 static pj_status_t put_frame(struct sdl_stream *stream, 
    724                              const pjmedia_frame *frame) 
    725 { 
    726     if (!stream->is_running) 
    727         return PJ_SUCCESS; 
    728  
    729     if (stream->surf) { 
    730         if (SDL_MUSTLOCK(stream->surf)) { 
    731             if (SDL_LockSurface(stream->surf) < 0) { 
    732                 PJ_LOG(3, (THIS_FILE, "Unable to lock SDL surface")); 
    733                 return PJMEDIA_EVID_NOTREADY; 
    734             } 
    735         } 
    736          
    737         pj_memcpy(stream->surf->pixels, frame->buf, 
    738                   stream->vafp.framebytes); 
    739          
    740         if (SDL_MUSTLOCK(stream->surf)) { 
    741             SDL_UnlockSurface(stream->surf); 
    742         } 
    743 #if SDL_VERSION_ATLEAST(1,3,0) 
    744         SDL_UpdateWindowSurface(stream->window); 
    745 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    746         SDL_BlitSurface(stream->surf, NULL, stream->screen, &stream->dstrect); 
    747 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    748     } else if (stream->overlay) { 
    749         int i, sz, offset; 
    750          
    751         if (SDL_LockYUVOverlay(stream->overlay) < 0) { 
    752             PJ_LOG(3, (THIS_FILE, "Unable to lock SDL overlay")); 
    753             return PJMEDIA_EVID_NOTREADY; 
    754         } 
    755          
    756         for (i = 0, offset = 0; i < stream->overlay->planes; i++) { 
    757             sz = stream->vafp.plane_bytes[i]; 
    758             pj_memcpy(stream->overlay->pixels[i], 
    759                       (char *)frame->buf + offset, sz); 
    760             offset += sz; 
    761         } 
    762          
    763         SDL_UnlockYUVOverlay(stream->overlay); 
    764         SDL_DisplayYUVOverlay(stream->overlay, &stream->dstrect); 
    765     } 
    766 #if SDL_VERSION_ATLEAST(1,3,0) 
    767     else if (stream->scr_tex) { 
     800    return PJ_SUCCESS; 
     801} 
     802 
     803static pj_status_t change_format(struct sdl_stream *strm, 
     804                                 pjmedia_format *new_fmt) 
     805{ 
     806    pj_status_t status; 
     807 
     808    /* Recreate SDL renderer */ 
     809    status = sdl_create_rend(strm, (new_fmt? new_fmt : 
     810                                   &strm->param.fmt)); 
     811    if (status == PJ_SUCCESS && new_fmt) 
     812        pjmedia_format_copy(&strm->param.fmt, new_fmt); 
     813 
     814    return status; 
     815} 
     816 
     817static pj_status_t put_frame(void *data) 
     818{ 
     819    struct sdl_stream *stream = (struct sdl_stream *)data; 
     820    const pjmedia_frame *frame = stream->frame; 
     821 
     822    if (stream->scr_tex) { 
    768823        SDL_UpdateTexture(stream->scr_tex, NULL, frame->buf, stream->pitch); 
    769824        SDL_RenderClear(stream->renderer); 
     
    772827        SDL_RenderPresent(stream->renderer); 
    773828    } 
    774 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    775829#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    776830    else if (stream->param.rend_id == OPENGL_DEV_IDX && stream->texture) { 
     
    788842        glVertex2i(stream->param.disp_size.w, stream->param.disp_size.h); 
    789843        glEnd(); 
    790 #   if SDL_VERSION_ATLEAST(1,3,0) 
    791844        SDL_GL_SwapWindow(stream->window); 
    792 #   else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    793         SDL_GL_SwapBuffers(); 
    794 #   endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    795845    } 
    796846#endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    797847 
    798848    return PJ_SUCCESS; 
    799 } 
    800  
    801 static struct sdl_stream* find_stream(struct sdl_factory *sf, 
    802                                       Uint32 windowID, 
    803                                       pjmedia_event *pevent) 
    804 { 
    805     struct stream_list *it, *itBegin; 
    806     struct sdl_stream *strm = NULL; 
    807  
    808     itBegin = &sf->streams; 
    809     for (it = itBegin->next; it != itBegin; it = it->next) { 
    810 #if SDL_VERSION_ATLEAST(1,3,0) 
    811         if (SDL_GetWindowID(it->stream->window) == windowID) 
    812 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    813         PJ_UNUSED_ARG(windowID); 
    814 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    815         { 
    816             strm = it->stream; 
    817             break; 
    818         } 
    819     } 
    820   
    821     if (strm) 
    822         pjmedia_event_init(pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 
    823                            &strm->base.epub); 
    824  
    825     return strm; 
    826 } 
    827  
    828 static int poll_event(struct sdl_factory *sf, pjmedia_event *pevent, 
    829                       struct sdl_stream **strm) 
    830 { 
    831     int retval; 
    832     SDL_Event sevent; 
    833  
    834     retval = SDL_PollEvent(&sevent); 
    835     if (retval) { 
    836 #if !(SDL_VERSION_ATLEAST(1,3,0)) 
    837         *strm = find_stream(sf, 0, pevent); 
    838         pj_assert(strm); 
    839 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 
    840  
    841         switch(sevent.type) { 
    842             case SDL_MOUSEBUTTONDOWN: 
    843 #if SDL_VERSION_ATLEAST(1,3,0) 
    844                 *strm = find_stream(sf, sevent.button.windowID, pevent); 
    845 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    846                 pevent->type = PJMEDIA_EVENT_MOUSE_BTN_DOWN; 
    847                 break; 
    848 #if SDL_VERSION_ATLEAST(1,3,0) 
    849             case SDL_WINDOWEVENT: 
    850                 *strm = find_stream(sf, sevent.window.windowID, pevent); 
    851                 switch (sevent.window.event) { 
    852                     case SDL_WINDOWEVENT_RESIZED: 
    853                         pevent->type = PJMEDIA_EVENT_WND_RESIZED; 
    854                         pevent->data.wnd_resized.new_size.w = 
    855                             sevent.window.data1; 
    856                         pevent->data.wnd_resized.new_size.h = 
    857                             sevent.window.data2; 
    858                         break; 
    859                     case SDL_WINDOWEVENT_CLOSE: 
    860                         pevent->type = PJMEDIA_EVENT_WND_CLOSING; 
    861                         break; 
    862                 } 
    863                 break; 
    864 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    865             case SDL_VIDEORESIZE: 
    866                 pevent->type = PJMEDIA_EVENT_WND_RESIZED; 
    867                 pevent->data.wnd_resized.new_size.w = sevent.resize.w; 
    868                 pevent->data.wnd_resized.new_size.h = sevent.resize.h; 
    869                 break; 
    870             case SDL_QUIT: 
    871                 pevent->type = PJMEDIA_EVENT_WND_CLOSING; 
    872                 break; 
    873 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    874         } 
    875     } 
    876  
    877     return retval; 
    878 } 
    879  
    880 static struct sdl_stream* handle_event(struct sdl_factory *sf, 
    881                                        struct sdl_stream *rcv_strm, 
    882                                        pjmedia_event_type *ev_type) 
    883 { 
    884     struct sdl_stream *strm = NULL; 
    885     pjmedia_event pevent; 
    886  
    887     *ev_type = PJMEDIA_EVENT_NONE; 
    888     while (poll_event(sf, &pevent, &strm)) { 
    889         *ev_type = pevent.type; 
    890         if (pevent.type != PJMEDIA_EVENT_NONE && strm && 
    891             (!rcv_strm || rcv_strm == strm)) 
    892         { 
    893             pjmedia_event_publish(&strm->base.epub, &pevent); 
    894  
    895             switch (pevent.type) { 
    896             case PJMEDIA_EVENT_WND_RESIZED: 
    897                 strm->new_disp_size = &pevent.data.wnd_resized.new_size; 
    898                 strm->status = PJ_SUCCESS; 
    899                 detect_fmt_change(strm); 
    900                 if (strm->status != PJ_SUCCESS) 
    901                     return strm; 
    902                 break; 
    903  
    904             case PJMEDIA_EVENT_WND_CLOSING: 
    905                 if (pevent.data.wnd_closing.cancel) { 
    906                     /* Cancel the closing operation */ 
    907                     break; 
    908                 } 
    909  
    910                 /* Proceed to cleanup SDL. App must still call 
    911                  * pjmedia_dev_stream_destroy() when getting WND_CLOSED 
    912                  * event 
    913                  */ 
    914                 strm->is_quitting = PJ_TRUE; 
    915                 sdl_stream_stop(&strm->base); 
    916  
    917                 return strm; 
    918             default: 
    919                 /* Just to prevent gcc warning about unused enums */ 
    920                 break; 
    921             } 
    922         } 
    923     } 
    924  
    925     return strm; 
    926 } 
    927  
    928 static int sdl_thread(void * data) 
    929 { 
    930     struct sdl_dev_t *sdl_dev = (struct sdl_dev_t *)data; 
    931     struct sdl_factory *sf = sdl_dev->sf; 
    932     struct sdl_stream *strm = sdl_dev->strm; 
    933  
    934 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    935     NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init]; 
    936     SDLDelegate *delegate = [[SDLDelegate alloc] init]; 
    937 #endif /* PJ_DARWINOS */ 
    938  
    939 #if SDL_VERSION_ATLEAST(1,3,0) 
    940 #   if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    941     [delegate performSelectorOnMainThread:@selector(sdl_init)  
    942               withObject:nil waitUntilDone:YES]; 
    943     if (delegate->status != PJ_SUCCESS) 
    944         goto on_error; 
    945 #   else /* PJ_DARWINOS */ 
    946     /* Initialize the SDL library */ 
    947     if (SDL_Init(SDL_INIT_VIDEO)) { 
    948         sf->status = PJMEDIA_EVID_INIT; 
    949         goto on_error; 
    950     } 
    951 #   endif /* PJ_DARWINOS */ 
    952 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    953     sf->status = PJ_SUCCESS; 
    954  
    955     while (!sf->is_quitting) { 
    956         struct stream_list *it, *itBegin; 
    957         pjmedia_event_type ev_type; 
    958         struct sdl_stream *ev_stream; 
    959  
    960         pj_mutex_lock(sf->mutex); 
    961  
    962         if (!strm && pj_list_empty(&sf->streams)) { 
    963             /* Wait until there is any stream. */ 
    964             pj_mutex_unlock(sf->mutex); 
    965             pj_sem_wait(sf->sem); 
    966             pj_mutex_lock(sf->mutex); 
    967         } 
    968  
    969         itBegin = &sf->streams; 
    970         for (it = itBegin->next; it != itBegin; it = it->next) { 
    971             if ((strm && it->stream != strm) || it->stream->is_quitting) 
    972                 continue; 
    973  
    974             if (!it->stream->is_initialized) { 
    975 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    976                 delegate->strm = it->stream; 
    977                 [delegate performSelectorOnMainThread:@selector(sdl_create) 
    978                           withObject:nil waitUntilDone:YES]; 
    979 #else /* PJ_DARWINOS */ 
    980                 sdl_create(it->stream); 
    981 #endif /* PJ_DARWINOS */ 
    982             } 
    983  
    984 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    985             delegate->strm = it->stream; 
    986             [delegate performSelectorOnMainThread:@selector(detect_fmt_change) 
    987                       withObject:nil waitUntilDone:YES]; 
    988             [delegate performSelectorOnMainThread:@selector(put_frame) 
    989                       withObject:nil waitUntilDone:YES]; 
    990 #else /* PJ_DARWINOS */ 
    991             detect_fmt_change(it->stream); 
    992             put_frame(it->stream, &it->stream->frame); 
    993 #endif /* PJ_DARWINOS */ 
    994         } 
    995  
    996 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    997         delegate->sf = sf; 
    998         delegate->strm = strm; 
    999         [delegate performSelectorOnMainThread:@selector(handle_event) 
    1000                   withObject:nil waitUntilDone:YES]; 
    1001         ev_stream = delegate->strm; 
    1002         ev_type = delegate->ev_type; 
    1003 #else /* PJ_DARWINOS */ 
    1004         ev_stream = handle_event(sf, strm, &ev_type); 
    1005 #endif /* PJ_DARWINOS */ 
    1006  
    1007         itBegin = &sf->streams; 
    1008         for (it = itBegin->next; it != itBegin; it = it->next) { 
    1009             if ((strm && it->stream != strm) || !it->stream->is_quitting || 
    1010                 it->stream->is_destroyed) 
    1011                 continue; 
    1012  
    1013 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    1014             delegate->strm = it->stream; 
    1015             [delegate performSelectorOnMainThread:@selector(sdl_destroy) 
    1016                       withObject:nil waitUntilDone:YES]; 
    1017 #   if !(SDL_VERSION_ATLEAST(1,3,0)) 
    1018             [delegate performSelectorOnMainThread:@selector(sdl_quit) 
    1019                       withObject:nil waitUntilDone:YES]; 
    1020 #   endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 
    1021 #else /* PJ_DARWINOS */ 
    1022             sdl_destroy(it->stream, PJ_TRUE); 
    1023 #   if !(SDL_VERSION_ATLEAST(1,3,0)) 
    1024             SDL_Quit(); 
    1025 #   endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 
    1026 #endif /* PJ_DARWINOS */ 
    1027             it->stream->screen = NULL; 
    1028             it->stream->is_destroyed = PJ_TRUE; 
    1029  
    1030             if (ev_type == PJMEDIA_EVENT_WND_CLOSING && 
    1031                 it->stream == ev_stream) 
    1032             { 
    1033                 pjmedia_event p_event; 
    1034  
    1035                 pjmedia_event_init(&p_event, PJMEDIA_EVENT_WND_CLOSED, 
    1036                                    &it->stream->last_ts, 
    1037                                    &it->stream->base.epub); 
    1038                 pjmedia_event_publish(&it->stream->base.epub, &p_event); 
    1039  
    1040                 /* 
    1041                  * Note: don't access the stream after this point, it 
    1042                  * might have been destroyed 
    1043                  */ 
    1044             } 
    1045  
    1046             if (strm) { 
    1047                 pj_mutex_unlock(sf->mutex); 
    1048                 return 0; 
    1049             } 
    1050         } 
    1051  
    1052         pj_mutex_unlock(sf->mutex); 
    1053     } 
    1054  
    1055 on_error: 
    1056 #if SDL_VERSION_ATLEAST(1,3,0) 
    1057 #   if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    1058     [delegate performSelectorOnMainThread:@selector(sdl_quit)  
    1059               withObject:nil waitUntilDone:YES]; 
    1060     [delegate release]; 
    1061     [apool release]; 
    1062 #   else /* PJ_DARWINOS */ 
    1063     SDL_Quit(); 
    1064 #   endif /* PJ_DARWINOS */ 
    1065 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    1066  
    1067     return 0; 
    1068849} 
    1069850 
     
    1073854{ 
    1074855    struct sdl_stream *stream = (struct sdl_stream*)strm; 
     856    pj_status_t status; 
    1075857 
    1076858    stream->last_ts.u64 = frame->timestamp.u64; 
    1077859 
    1078     if (!stream->is_running) { 
    1079         stream->render_exited = PJ_TRUE; 
    1080         return PJ_SUCCESS; 
    1081     } 
     860    if (!stream->is_running) 
     861        return PJ_EINVALIDOP; 
    1082862 
    1083863    if (frame->size==0 || frame->buf==NULL || 
     
    1085865        return PJ_SUCCESS; 
    1086866 
    1087     pj_memcpy(stream->frame.buf, frame->buf, stream->vafp.framebytes); 
    1088  
    1089     return PJ_SUCCESS; 
     867    stream->frame = frame; 
     868    job_queue_post_job(stream->sf->jq, put_frame, strm, 0, &status); 
     869     
     870    return status; 
    1090871} 
    1091872 
     
    1105886    PJ_ASSERT_RETURN(param->dir == PJMEDIA_DIR_RENDER, PJ_EINVAL); 
    1106887 
    1107 #if !SDL_VERSION_ATLEAST(1,3,0) 
    1108     /* Prior to 1.3, SDL does not support multiple renderers. */ 
    1109     pj_mutex_lock(sf->mutex); 
    1110     if (!pj_list_empty(&sf->streams)) { 
    1111         pj_mutex_unlock(sf->mutex); 
    1112         return PJMEDIA_EVID_NOTREADY; 
    1113     } 
    1114     pj_mutex_unlock(sf->mutex); 
    1115 #endif 
    1116  
    1117888    /* Create and Initialize stream descriptor */ 
    1118889    pool = pj_pool_create(sf->pf, "sdl-dev", 1000, 1000, NULL); 
     
    1126897    strm->user_data = user_data; 
    1127898    pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_SDL); 
    1128     pj_list_init(&strm->list_entry); 
    1129     strm->list_entry.stream = strm; 
    1130899 
    1131900    /* Create render stream here */ 
    1132901    if (param->dir & PJMEDIA_DIR_RENDER) { 
    1133         struct sdl_dev_t sdl_dev; 
    1134  
    1135         strm->status = PJ_SUCCESS; 
    1136         sdl_dev.sf = strm->sf; 
    1137         sdl_dev.strm = strm; 
    1138         pj_mutex_lock(strm->sf->mutex); 
    1139 #if !SDL_USE_ONE_THREAD_PER_DISPLAY 
    1140         if (pj_list_empty(&strm->sf->streams)) 
    1141             pj_sem_post(strm->sf->sem); 
    1142 #endif /* !SDL_USE_ONE_THREAD_PER_DISPLAY */ 
    1143         pj_list_insert_after(&strm->sf->streams, &strm->list_entry); 
    1144         pj_mutex_unlock(strm->sf->mutex); 
    1145  
    1146 #if SDL_USE_ONE_THREAD_PER_DISPLAY 
    1147         status = pj_thread_create(pool, "sdl_thread", sdl_thread, 
    1148                                   &sdl_dev, 0, 0, &strm->sdl_thread); 
     902        job_queue_post_job(sf->jq, sdl_create, strm, 0, &status); 
    1149903        if (status != PJ_SUCCESS) { 
    1150904            goto on_error; 
    1151905        } 
    1152 #endif /* SDL_USE_ONE_THREAD_PER_DISPLAY */ 
    1153  
    1154         while(strm->status == PJ_SUCCESS && !strm->surf && !strm->overlay 
    1155 #if SDL_VERSION_ATLEAST(1,3,0) 
    1156               && !strm->scr_tex 
    1157 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    1158 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    1159               && !strm->texture 
    1160 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 
    1161               ) 
    1162         { 
    1163             pj_thread_sleep(10); 
    1164         } 
    1165         if ((status = strm->status) != PJ_SUCCESS) { 
    1166             goto on_error; 
    1167         } 
     906        pj_list_init(&strm->list_entry); 
     907        strm->list_entry.stream = strm; 
     908        pj_mutex_lock(strm->sf->mutex); 
     909        if (pj_list_empty(&strm->sf->streams)) 
     910            pj_sem_post(strm->sf->sem); 
     911        pj_list_insert_after(&strm->sf->streams, &strm->list_entry); 
     912        pj_mutex_unlock(strm->sf->mutex); 
    1168913    } 
    1169914 
     
    1174919                           &param->window_pos); 
    1175920    } 
    1176     if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE) { 
    1177         sdl_stream_set_cap(&strm->base, 
    1178                            PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, 
    1179                            &param->window_hide); 
    1180     } 
    1181921 
    1182922    /* Done */ 
     
    1225965} 
    1226966 
    1227 /* API: get capability */ 
    1228 static pj_status_t sdl_stream_get_cap(pjmedia_vid_dev_stream *s, 
    1229                                       pjmedia_vid_dev_cap cap, 
    1230                                       void *pval) 
    1231 { 
    1232     struct sdl_stream *strm = (struct sdl_stream*)s; 
    1233  
    1234     PJ_UNUSED_ARG(strm); 
    1235  
    1236     PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 
    1237  
    1238 #if SDL_VERSION_ATLEAST(1,3,0) 
     967struct strm_cap { 
     968    struct sdl_stream   *strm; 
     969    pjmedia_vid_dev_cap  cap; 
     970    union { 
     971        void            *pval; 
     972        const void      *cpval; 
     973    } pval; 
     974}; 
     975 
     976static pj_status_t get_cap(void *data) 
     977{ 
     978    struct strm_cap *scap = (struct strm_cap *)data; 
     979    struct sdl_stream *strm = scap->strm; 
     980    pjmedia_vid_dev_cap cap = scap->cap; 
     981    void *pval = scap->pval.pval; 
     982 
    1239983    if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) 
    1240984    { 
     
    1244988        if (SDL_GetWindowWMInfo(strm->window, &info)) { 
    1245989            pjmedia_vid_dev_hwnd *wnd = (pjmedia_vid_dev_hwnd *)pval; 
    1246             if (info.subsystem == SDL_SYSWM_WINDOWS) { 
     990            if (0) { } 
    1247991#if defined(SDL_VIDEO_DRIVER_WINDOWS) 
     992            else if (info.subsystem == SDL_SYSWM_WINDOWS) { 
    1248993                wnd->type = PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS; 
    1249994                wnd->info.win.hwnd = (void *)info.info.win.window; 
     995            } 
    1250996#endif 
    1251             } else if (info.subsystem == SDL_SYSWM_X11) { 
    1252997#if defined(SDL_VIDEO_DRIVER_X11) 
     998            else if (info.subsystem == SDL_SYSWM_X11) { 
    1253999                wnd->info.x11.window = (void *)info.info.x11.window; 
    12541000                wnd->info.x11.display = (void *)info.info.x11.display; 
     1001            } 
    12551002#endif 
    1256             } else if (info.subsystem == SDL_SYSWM_COCOA) { 
    12571003#if defined(SDL_VIDEO_DRIVER_COCOA) 
     1004            else if (info.subsystem == SDL_SYSWM_COCOA) { 
    12581005                wnd->info.cocoa.window = (void *)info.info.cocoa.window; 
     1006            } 
    12591007#endif 
    1260             } else if (info.subsystem == SDL_SYSWM_UIKIT) { 
    12611008#if defined(SDL_VIDEO_DRIVER_UIKIT) 
     1009            else if (info.subsystem == SDL_SYSWM_UIKIT) { 
    12621010                wnd->info.ios.window = (void *)info.info.uikit.window; 
     1011            } 
    12631012#endif 
     1013            else { 
     1014                return PJMEDIA_EVID_INVCAP; 
    12641015            } 
    12651016            return PJ_SUCCESS; 
     
    12791030        return PJ_SUCCESS; 
    12801031    } 
    1281 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 
    1282     PJ_UNUSED_ARG(cap); 
    1283 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    12841032 
    12851033    return PJMEDIA_EVID_INVCAP; 
    12861034} 
    12871035 
    1288 /* API: set capability */ 
    1289 static pj_status_t sdl_stream_set_cap(pjmedia_vid_dev_stream *s, 
     1036/* API: get capability */ 
     1037static pj_status_t sdl_stream_get_cap(pjmedia_vid_dev_stream *s, 
    12901038                                      pjmedia_vid_dev_cap cap, 
    1291                                       const void *pval) 
     1039                                      void *pval) 
    12921040{ 
    12931041    struct sdl_stream *strm = (struct sdl_stream*)s; 
    1294  
    1295     PJ_UNUSED_ARG(strm); 
     1042    struct strm_cap scap; 
     1043    pj_status_t status; 
    12961044 
    12971045    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 
    12981046 
    1299 #if SDL_VERSION_ATLEAST(1,3,0) 
     1047    scap.strm = strm; 
     1048    scap.cap = cap; 
     1049    scap.pval.pval = pval; 
     1050 
     1051    job_queue_post_job(strm->sf->jq, get_cap, &scap, 0, &status); 
     1052 
     1053    return status; 
     1054} 
     1055 
     1056static pj_status_t set_cap(void *data) 
     1057{ 
     1058    struct strm_cap *scap = (struct strm_cap *)data; 
     1059    struct sdl_stream *strm = scap->strm; 
     1060    pjmedia_vid_dev_cap cap = scap->cap; 
     1061    const void *pval = scap->pval.cpval; 
     1062 
    13001063    if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION) { 
    13011064        SDL_SetWindowPosition(strm->window, ((pjmedia_coord *)pval)->x, 
     
    13081071            SDL_ShowWindow(strm->window); 
    13091072        return PJ_SUCCESS; 
    1310     } else 
    1311 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 
    1312     if (cap == PJMEDIA_VID_DEV_CAP_FORMAT) { 
    1313         strm->new_fmt = (pjmedia_format *)pval; 
    1314         while (strm->new_fmt) 
    1315             pj_thread_sleep(10); 
    1316          
    1317         if (strm->status != PJ_SUCCESS) { 
    1318             pj_status_t status = strm->status; 
     1073    } else if (cap == PJMEDIA_VID_DEV_CAP_FORMAT) { 
     1074        pj_status_t status; 
     1075 
     1076        status = change_format(strm, (pjmedia_format *)pval); 
     1077        if (status != PJ_SUCCESS) { 
     1078            pj_status_t status_; 
    13191079             
    13201080            /** 
     
    13221082             * to its original format. 
    13231083             */ 
    1324             strm->new_fmt = &strm->param.fmt; 
    1325             while (strm->new_fmt) 
    1326                 pj_thread_sleep(10); 
    1327              
    1328             if (strm->status != PJ_SUCCESS) { 
     1084            status_ = change_format(strm, &strm->param.fmt); 
     1085            if (status_ != PJ_SUCCESS) { 
    13291086                /** 
    13301087                 * This means that we failed to revert to our 
     
    13331090                status = PJMEDIA_EVID_ERR; 
    13341091            } 
    1335              
    1336             strm->status = status; 
    13371092        } 
    13381093         
    1339         return strm->status; 
     1094        return status; 
    13401095    } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE) { 
    1341         strm->new_disp_size = (pjmedia_rect_size *)pval; 
    1342         while (strm->new_disp_size) 
    1343             pj_thread_sleep(10); 
    1344          
    1345         return strm->status; 
     1096        pjmedia_rect_size *new_size = (pjmedia_rect_size *)pval; 
     1097 
     1098        SDL_SetWindowSize(strm->window, new_size->w, new_size->h); 
     1099        return resize_disp(strm, new_size); 
    13461100    } 
    13471101 
    13481102    return PJMEDIA_EVID_INVCAP; 
     1103} 
     1104 
     1105/* API: set capability */ 
     1106static pj_status_t sdl_stream_set_cap(pjmedia_vid_dev_stream *s, 
     1107                                      pjmedia_vid_dev_cap cap, 
     1108                                      const void *pval) 
     1109{ 
     1110    struct sdl_stream *strm = (struct sdl_stream*)s; 
     1111    struct strm_cap scap; 
     1112    pj_status_t status; 
     1113 
     1114    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 
     1115 
     1116    scap.strm = strm; 
     1117    scap.cap = cap; 
     1118    scap.pval.cpval = pval; 
     1119 
     1120    job_queue_post_job(strm->sf->jq, set_cap, &scap, 0, &status); 
     1121 
     1122    return status; 
    13491123} 
    13501124 
     
    13571131 
    13581132    stream->is_running = PJ_TRUE; 
    1359     stream->render_exited = PJ_FALSE; 
    1360  
    1361     return PJ_SUCCESS; 
    1362 } 
     1133 
     1134    return PJ_SUCCESS; 
     1135} 
     1136 
    13631137 
    13641138/* API: Stop stream. */ 
     
    13661140{ 
    13671141    struct sdl_stream *stream = (struct sdl_stream*)strm; 
    1368     unsigned i; 
    13691142 
    13701143    PJ_LOG(4, (THIS_FILE, "Stopping sdl video stream")); 
    13711144 
    1372     /* Wait for renderer put_frame() to finish */ 
    13731145    stream->is_running = PJ_FALSE; 
    1374     for (i=0; !stream->render_exited && i<50; ++i) 
    1375         pj_thread_sleep(10); 
    13761146 
    13771147    return PJ_SUCCESS; 
     
    13831153{ 
    13841154    struct sdl_stream *stream = (struct sdl_stream*)strm; 
     1155    pj_status_t status; 
    13851156 
    13861157    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
     
    13881159    sdl_stream_stop(strm); 
    13891160 
    1390     if (!stream->is_quitting) { 
    1391         stream->is_quitting = PJ_TRUE; 
    1392         if (stream->sdl_thread) 
    1393             pj_thread_join(stream->sdl_thread); 
    1394         while (!stream->is_destroyed) { 
    1395             pj_thread_sleep(10); 
    1396         } 
    1397     } 
     1161    job_queue_post_job(stream->sf->jq, sdl_destroy_all, strm, 0, &status); 
     1162    if (status != PJ_SUCCESS) 
     1163        return status; 
    13981164 
    13991165    pj_mutex_lock(stream->sf->mutex); 
     
    14071173} 
    14081174 
     1175/**************************************************************************** 
     1176 * Job queue implementation 
     1177 */ 
     1178static int job_thread(void * data) 
     1179{ 
     1180    job_queue *jq = (job_queue *)data; 
     1181 
     1182    while (1) { 
     1183        job *jb; 
     1184 
     1185        /* Wait until there is a job. */ 
     1186        pj_sem_wait(jq->sem); 
     1187 
     1188        /* Make sure there is no pending jobs before we quit. */ 
     1189        if (jq->is_quitting && jq->head == jq->tail && !jq->is_full) 
     1190            break; 
     1191 
     1192        jb = jq->jobs[jq->head]; 
     1193        jb->retval = (*jb->func)(jb->data); 
     1194        pj_sem_post(jq->job_sem[jq->head]); 
     1195        pj_mutex_lock(jq->mutex); 
     1196        jq->head = (jq->head + 1) % MAX_JOBS; 
     1197        jq->is_full = PJ_FALSE; 
     1198        pj_mutex_unlock(jq->mutex); 
     1199    } 
     1200 
     1201    return 0; 
     1202} 
     1203 
     1204static pj_status_t job_queue_create(pj_pool_t *pool, job_queue **pjq) 
     1205{ 
     1206    unsigned i; 
     1207    pj_status_t status; 
     1208 
     1209    job_queue *jq = PJ_POOL_ZALLOC_T(pool, job_queue); 
     1210    pj_sem_create(pool, "thread_sem", 0, MAX_JOBS + 1, &jq->sem); 
     1211 
    14091212#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    1410 @implementation SDLDelegate 
    1411 - (void)sdl_init 
    1412 { 
    1413     if (SDL_Init(SDL_INIT_VIDEO)) { 
    1414         PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL")); 
    1415         status = PJMEDIA_EVID_INIT; 
    1416     } 
    1417     status = PJ_SUCCESS; 
    1418 } 
    1419  
    1420 - (void)sdl_quit 
    1421 { 
    1422     SDL_Quit(); 
    1423 } 
    1424  
    1425 - (void)detect_fmt_change 
    1426 { 
    1427     detect_fmt_change(strm); 
    1428 } 
    1429  
    1430 - (void)sdl_create 
    1431 { 
    1432     sdl_create(strm); 
    1433 } 
    1434  
    1435 - (void)sdl_destroy 
    1436 { 
    1437     sdl_destroy(strm, PJ_TRUE); 
    1438 } 
    1439  
    1440 - (void)handle_event 
    1441 { 
    1442     strm = handle_event(sf, strm, &ev_type); 
    1443 } 
    1444  
    1445 - (void)put_frame 
    1446 { 
    1447     put_frame(strm, &strm->frame); 
    1448 } 
    1449  
    1450 @end 
     1213    PJ_UNUSED_ARG(status); 
     1214#else 
     1215    status = pj_thread_create(pool, "job_th", job_thread, jq, 0, 0, 
     1216                              &jq->thread); 
     1217    if (status != PJ_SUCCESS) { 
     1218        job_queue_destroy(jq); 
     1219        return status; 
     1220    } 
    14511221#endif /* PJ_DARWINOS */ 
     1222 
     1223    for (i = 0; i < MAX_JOBS; i++) { 
     1224        pj_sem_create(pool, "job_sem", 0, 1, &jq->job_sem[i]); 
     1225    } 
     1226    pj_mutex_create_recursive(pool, "job_mutex", &jq->mutex); 
     1227 
     1228    *pjq = jq; 
     1229    return PJ_SUCCESS; 
     1230} 
     1231 
     1232static pj_status_t job_queue_post_job(job_queue *jq, job_func_ptr func, 
     1233                                      void *data, unsigned flags, 
     1234                                      pj_status_t *retval) 
     1235{ 
     1236    job jb; 
     1237    int tail; 
     1238 
     1239    if (jq->is_quitting) 
     1240        return PJ_EBUSY; 
     1241 
     1242    jb.func = func; 
     1243    jb.data = data; 
     1244    jb.flags = flags; 
     1245 
     1246#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
     1247    PJ_UNUSED_ARG(tail); 
     1248    NSAutoreleasePool *apool = [[NSAutoreleasePool alloc]init]; 
     1249    JQDelegate *jqd = [[JQDelegate alloc]init]; 
     1250    jqd->pjob = &jb; 
     1251    [jqd performSelectorOnMainThread:@selector(run_job) 
     1252         withObject:nil waitUntilDone:YES]; 
     1253    [jqd release]; 
     1254    [apool release]; 
     1255#else /* PJ_DARWINOS */ 
     1256    pj_mutex_lock(jq->mutex); 
     1257    if (jq->is_full) { 
     1258        /* Sorry, the queue is full! */ 
     1259        pj_mutex_unlock(jq->mutex); 
     1260        *retval = PJ_ETOOMANY; 
     1261        return PJ_ETOOMANY; 
     1262    } 
     1263    jq->jobs[jq->tail] = &jb; 
     1264    tail = jq->tail; 
     1265    jq->tail = (jq->tail + 1) % MAX_JOBS; 
     1266    if (jq->tail == jq->head) 
     1267        jq->is_full = PJ_TRUE; 
     1268    pj_mutex_unlock(jq->mutex); 
     1269 
     1270    pj_sem_post(jq->sem); 
     1271    /* Wait until our posted job is completed. */ 
     1272    pj_sem_wait(jq->job_sem[tail]); 
     1273#endif /* PJ_DARWINOS */ 
     1274 
     1275    *retval = jb.retval; 
     1276 
     1277    return PJ_SUCCESS; 
     1278} 
     1279 
     1280static pj_status_t job_queue_destroy(job_queue *jq) 
     1281{ 
     1282    unsigned i; 
     1283 
     1284    jq->is_quitting = PJ_TRUE; 
     1285 
     1286    if (jq->thread) { 
     1287        pj_sem_post(jq->sem); 
     1288        pj_thread_join(jq->thread); 
     1289    } 
     1290 
     1291    if (jq->sem) { 
     1292        pj_sem_destroy(jq->sem); 
     1293        jq->sem = NULL; 
     1294    } 
     1295    for (i = 0; i < MAX_JOBS; i++) { 
     1296        pj_sem_destroy(jq->job_sem[i]); 
     1297    } 
     1298    pj_mutex_destroy(jq->mutex); 
     1299 
     1300    return PJ_SUCCESS; 
     1301} 
    14521302 
    14531303#ifdef _MSC_VER 
Note: See TracChangeset for help on using the changeset viewer.