Ignore:
Timestamp:
Apr 13, 2011 8:06:12 PM (13 years ago)
Author:
ming
Message:

Re #1213: Add on-the-fly format change capability for SDL OpenGL.

Location:
pjproject/branches/projects/2.0-dev/pjmedia/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c

    r3527 r3535  
    378378} 
    379379 
    380 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    381 @implementation SDLDelegate 
    382 - (int)sdl_thread 
    383 { 
    384 #else 
    385 static int sdlthread(void * data) 
    386 { 
    387     struct sdl_stream *strm = (struct sdl_stream*)data; 
    388 #endif 
    389     sdl_fmt_info *sdl_info = get_sdl_format_info(strm->param.fmt.id); 
     380static void destroy_sdl(struct sdl_stream *strm) 
     381{ 
     382    if (strm->surf) { 
     383        SDL_FreeSurface(strm->surf); 
     384        strm->surf = NULL; 
     385    } 
     386    if (strm->overlay) { 
     387        SDL_FreeYUVOverlay(strm->overlay); 
     388        strm->overlay = NULL; 
     389    } 
     390#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     391    if (strm->texture) { 
     392        glDeleteTextures(1, &strm->texture); 
     393        strm->texture = 0; 
     394    } 
     395#endif 
     396} 
     397 
     398static pj_status_t init_sdl(struct sdl_stream *strm, pjmedia_format *fmt) 
     399{ 
     400    sdl_fmt_info *sdl_info = get_sdl_format_info(fmt->id); 
    390401    const pjmedia_video_format_info *vfi; 
    391402    pjmedia_video_format_detail *vfd; 
    392403 
    393404    vfi = pjmedia_get_video_format_info(pjmedia_video_format_mgr_instance(), 
    394                                         strm->param.fmt.id); 
    395     if (!vfi || !sdl_info) { 
    396         strm->status = PJMEDIA_EVID_BADFORMAT; 
    397         goto on_return; 
    398     } 
    399  
    400     strm->vafp.size = strm->param.fmt.det.vid.size; 
     405                                        fmt->id); 
     406    if (!vfi || !sdl_info) 
     407        return PJMEDIA_EVID_BADFORMAT; 
     408 
     409    strm->vafp.size = fmt->det.vid.size; 
    401410    strm->vafp.buffer = NULL; 
    402     if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) { 
    403         strm->status = PJMEDIA_EVID_BADFORMAT; 
    404         goto on_return; 
    405     } 
    406  
    407     /* Initialize the SDL library */ 
    408     if (SDL_Init(SDL_INIT_VIDEO)) { 
    409         PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL")); 
    410         strm->status = PJMEDIA_EVID_INIT; 
    411         goto on_return; 
    412     } 
    413  
    414     vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE); 
     411    if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) 
     412        return PJMEDIA_EVID_BADFORMAT; 
     413 
     414    vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE); 
    415415    strm->rect.x = strm->rect.y = 0; 
    416416    strm->rect.w = (Uint16)vfd->size.w; 
    417417    strm->rect.h = (Uint16)vfd->size.h; 
    418418 
    419 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    420     if (strm->param.rend_id == OPENGL_DEV_IDX) { 
    421         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); 
    422     } 
    423 #endif 
    424  
    425     /* Initialize the display, requesting a software surface */ 
     419    /* Initialize the display */ 
    426420    strm->screen = SDL_SetVideoMode(strm->rect.w, strm->rect.h, 0, ( 
    427421#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     
    430424#endif 
    431425                                    SDL_RESIZABLE | SDL_SWSURFACE)); 
    432     if (strm->screen == NULL) { 
    433         strm->status = PJMEDIA_EVID_SYSERR; 
    434         goto on_return; 
    435     } 
     426    if (strm->screen == NULL) 
     427        return PJMEDIA_EVID_SYSERR; 
     428 
    436429    SDL_WM_SetCaption("pjmedia-SDL video", NULL); 
    437430 
     431    destroy_sdl(strm); 
     432 
    438433#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    439434    if (strm->param.rend_id == OPENGL_DEV_IDX) { 
     435        /* Init some OpenGL settings */ 
    440436        glDisable(GL_DEPTH_TEST); 
    441437        glDisable(GL_CULL_FACE); 
    442438        glEnable(GL_TEXTURE_2D); 
    443439         
     440        /* Init the viewport */ 
    444441        glViewport(0, 0, strm->rect.w, strm->rect.h); 
    445442        glMatrixMode(GL_PROJECTION); 
     
    452449        glLoadIdentity(); 
    453450         
     451        /* Create a texture */ 
    454452        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
    455453        glGenTextures(1, &strm->texture); 
    456454 
    457455#if defined(PJ_WIN32) && PJ_WIN32 != 0 
     456        /** 
     457         * On Win32 platform, the OpenGL drawing must be in the same 
     458         * thread that calls SDL_SetVideoMode(), hence we need a buffer 
     459         * for the frame from sdl_stream_put_frame() 
     460         */ 
    458461        if (strm->vafp.framebytes > strm->tex_buf_size) { 
    459462            strm->tex_buf_size = strm->vafp.framebytes; 
     
    471474                                          sdl_info->Bmask, 
    472475                                          sdl_info->Amask); 
    473         if (strm->surf == NULL) { 
    474             strm->status = PJMEDIA_EVID_SYSERR; 
    475             goto on_return; 
    476         } 
     476        if (strm->surf == NULL) 
     477            return PJMEDIA_EVID_SYSERR; 
    477478    } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) { 
    478479        strm->overlay = SDL_CreateYUVOverlay(strm->rect.w, strm->rect.h, 
    479480                                             sdl_info->sdl_format, 
    480481                                             strm->screen); 
    481         if (strm->overlay == NULL) { 
    482             strm->status = PJMEDIA_EVID_SYSERR; 
    483             goto on_return; 
    484         } 
    485     } 
     482        if (strm->overlay == NULL) 
     483            return PJMEDIA_EVID_SYSERR; 
     484    } 
     485 
     486    return PJ_SUCCESS; 
     487} 
     488 
     489#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
     490@implementation SDLDelegate 
     491- (int)sdl_thread 
     492{ 
     493#else 
     494static int sdlthread(void * data) 
     495{ 
     496    struct sdl_stream *strm = (struct sdl_stream*)data; 
     497#endif 
     498 
     499    /* Initialize the SDL library */ 
     500    if (SDL_Init(SDL_INIT_VIDEO)) { 
     501        PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL")); 
     502        strm->status = PJMEDIA_EVID_INIT; 
     503        goto on_return; 
     504    } 
     505 
     506#if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
     507    if (strm->param.rend_id == OPENGL_DEV_IDX) { 
     508        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); 
     509    } 
     510#endif 
     511 
     512    strm->status = init_sdl(strm, &strm->param.fmt); 
     513    if (strm->status != PJ_SUCCESS) 
     514        goto on_return; 
    486515 
    487516#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 
    488517on_return: 
    489518    if (strm->status != PJ_SUCCESS) { 
    490         if (strm->surf) { 
    491             SDL_FreeSurface(strm->surf); 
    492             strm->surf = NULL; 
    493         } 
    494          
    495         if (strm->overlay) { 
    496             SDL_FreeYUVOverlay(strm->overlay); 
    497             strm->overlay = NULL; 
    498         } 
    499     #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    500         if (strm->texture) { 
    501             glDeleteTextures(1, &strm->texture); 
    502             strm->texture = 0; 
    503         } 
    504     #endif 
    505          
     519        destory_sdl(strm);       
    506520        SDL_Quit(); 
    507521        strm->screen = NULL; 
     
    554568                    pj_assert(sevent.user.code == PJMEDIA_VID_DEV_CAP_FORMAT); 
    555569 
    556                     PJ_TODO(FIX_THIS_FOR_OPENGL); 
    557570                    fmt = (pjmedia_format *)sevent.user.data1; 
    558                     vfi = pjmedia_get_video_format_info( 
    559                               pjmedia_video_format_mgr_instance(), 
    560                               fmt->id); 
    561                     if (!vfi || !sdl_info) { 
    562                         strm->status = PJMEDIA_EVID_BADFORMAT; 
    563                         break; 
    564                     } 
    565  
    566                     vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE); 
    567                     strm->vafp.size = vfd->size; 
    568                     strm->vafp.buffer = NULL; 
    569                     if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) { 
    570                         strm->status = PJMEDIA_EVID_BADFORMAT; 
    571                         break; 
    572                     } 
    573  
    574                     strm->rect.w = (Uint16)vfd->size.w; 
    575                     strm->rect.h = (Uint16)vfd->size.h; 
    576  
    577                     /* Stop the stream */ 
     571 
     572                    /* Stop the stream */ 
    578573                    sdl_stream_stop((pjmedia_vid_dev_stream *)strm); 
    579574 
    580                     /* Initialize the display, requesting a software surface */ 
    581                     strm->screen = SDL_SetVideoMode(strm->rect.w, 
    582                                                     strm->rect.h, 0, 
    583                                                     SDL_RESIZABLE | 
    584                                                     SDL_SWSURFACE); 
    585                     if (strm->screen == NULL) { 
    586                         strm->status = PJMEDIA_EVID_SYSERR; 
    587                         break; 
    588                     } 
    589  
    590                     if (strm->surf) 
    591                         SDL_FreeSurface(strm->surf); 
    592                     if (strm->overlay) 
    593                         SDL_FreeYUVOverlay(strm->overlay); 
    594  
    595                     /* Update SDL info for the new format */ 
    596                     sdl_info = get_sdl_format_info(fmt->id); 
    597  
    598                     if (vfi->color_model == PJMEDIA_COLOR_MODEL_RGB) { 
    599                         strm->surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 
    600                                                           strm->rect.w, 
    601                                                           strm->rect.h, 
    602                                                           vfi->bpp, 
    603                                                           sdl_info->Rmask, 
    604                                                           sdl_info->Gmask, 
    605                                                           sdl_info->Bmask, 
    606                                                           sdl_info->Amask); 
    607                         if (strm->surf == NULL) { 
    608                             strm->status = PJMEDIA_EVID_SYSERR; 
    609                             break; 
    610                         } 
    611                     } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) { 
    612                         strm->overlay = SDL_CreateYUVOverlay( 
    613                                             strm->rect.w, 
    614                                             strm->rect.h, 
    615                                             sdl_info->sdl_format, 
    616                                             strm->screen); 
    617                         if (strm->overlay == NULL) { 
    618                             strm->status = PJMEDIA_EVID_SYSERR; 
    619                             break; 
    620                         } 
    621                     } 
    622  
    623                     /* Restart the stream */ 
    624                     sdl_stream_start((pjmedia_vid_dev_stream *)strm); 
    625  
    626                     strm->status = PJ_SUCCESS; 
     575                    /* Re-initialize SDL */ 
     576                    strm->status = init_sdl(strm, fmt); 
     577 
     578                    if (strm->status == PJ_SUCCESS) { 
     579                        pjmedia_format_copy(&strm->param.fmt, fmt);  
     580                        /* Restart the stream */ 
     581                        sdl_stream_start((pjmedia_vid_dev_stream *)strm); 
     582                    } 
     583 
    627584                    break; 
    628585                } 
     
    714671#endif 
    715672on_return: 
    716     if (strm->surf) { 
    717         SDL_FreeSurface(strm->surf); 
    718         strm->surf = NULL; 
    719     } 
    720  
    721     if (strm->overlay) { 
    722         SDL_FreeYUVOverlay(strm->overlay); 
    723         strm->overlay = NULL; 
    724     } 
    725 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 
    726     if (strm->texture) { 
    727         glDeleteTextures(1, &strm->texture); 
    728         strm->texture = 0; 
    729     } 
    730 #endif 
    731  
     673    destroy_sdl(strm); 
    732674    SDL_Quit(); 
    733675    strm->screen = NULL; 
     
    818760    else if (stream->param.rend_id == OPENGL_DEV_IDX) { 
    819761#if defined(PJ_WIN32) && PJ_WIN32 != 0 
    820         pj_assert(frame->size == stream->vafp.framebytes); 
    821         pj_memcpy(stream->tex_buf, frame->buf, frame->size); 
     762        pj_memcpy(stream->tex_buf, frame->buf, stream->vafp.framebytes); 
    822763#else 
    823764        draw_gl(stream, frame->buf); 
     
    892833        strm->delegate = [[SDLDelegate alloc]init]; 
    893834        strm->delegate->strm = strm; 
     835        /* On Mac OS X, we need to call SDL functions in the main thread */ 
    894836        [strm->delegate performSelectorOnMainThread:@selector(sdl_thread) 
    895837                        withObject:nil waitUntilDone:YES]; 
     
    1032974             
    1033975            strm->status = status; 
    1034         } else if (strm->status == PJ_SUCCESS) { 
    1035             pj_memcpy(&strm->param.fmt, pval, sizeof(strm->param.fmt)); 
    1036976        } 
    1037977         
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c

    r3509 r3535  
    3838struct pjmedia_vid_port 
    3939{ 
     40    pj_pool_t           *pool; 
    4041    pj_str_t             dev_name; 
    4142    pjmedia_dir          dir; 
     
    5051    pj_bool_t            destroy_client_port; 
    5152 
    52     pjmedia_converter   *cap_conv; 
    53     void                *cap_conv_buf; 
    54     pj_size_t            cap_conv_buf_size; 
     53    pjmedia_converter       *cap_conv; 
     54    void                    *cap_conv_buf; 
     55    pj_size_t                cap_conv_buf_size; 
     56    pjmedia_conversion_param cap_conv_param; 
    5557 
    5658    pjmedia_clock       *enc_clock, 
     
    136138    unsigned ptime_usec; 
    137139    pjmedia_vid_param vparam; 
    138     pjmedia_conversion_param conv_param; 
    139140 
    140141    PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL); 
     
    152153    /* Allocate videoport */ 
    153154    vp = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_port); 
     155    vp->pool = pool; 
    154156    vp->role = prm->active ? ROLE_ACTIVE : ROLE_PASSIVE; 
    155157    vp->dir = prm->vidparam.dir; 
     
    257259              vparam.fmt.det.vid.fps.num, vparam.fmt.det.vid.fps.denum)); 
    258260 
     261    if (vp->dir & PJMEDIA_DIR_CAPTURE) { 
     262        pjmedia_format_copy(&vp->cap_conv_param.src, &vparam.fmt); 
     263        pjmedia_format_copy(&vp->cap_conv_param.dst, &prm->vidparam.fmt); 
     264    } else { 
     265        pjmedia_format_copy(&vp->cap_conv_param.src, &prm->vidparam.fmt); 
     266        pjmedia_format_copy(&vp->cap_conv_param.dst, &vparam.fmt); 
     267    } 
     268 
    259269    /* Instantiate converter if necessary */ 
    260270    if (vparam.fmt.id != prm->vidparam.fmt.id || 
     
    268278        pjmedia_video_apply_fmt_param vafp; 
    269279 
    270         if (vp->dir & PJMEDIA_DIR_CAPTURE) { 
    271             pjmedia_format_copy(&conv_param.src, &vparam.fmt); 
    272             pjmedia_format_copy(&conv_param.dst, &prm->vidparam.fmt); 
    273  
    274             status = pjmedia_converter_create(NULL, pool, &conv_param, 
    275                                               &vp->cap_conv); 
    276         } else { 
    277             pjmedia_format_copy(&conv_param.src, &prm->vidparam.fmt); 
    278             pjmedia_format_copy(&conv_param.dst, &vparam.fmt); 
    279  
    280             status = pjmedia_converter_create(NULL, pool, &conv_param, 
    281                                               &vp->cap_conv); 
    282         } 
    283  
     280        status = pjmedia_converter_create(NULL, pool, &vp->cap_conv_param, 
     281                                          &vp->cap_conv); 
    284282        if (status != PJ_SUCCESS) { 
    285283            PJ_PERROR(4,(THIS_FILE, status, "Error creating converter")); 
     
    288286 
    289287        /* Allocate buffer for conversion */ 
    290         vfi = pjmedia_get_video_format_info(NULL, conv_param.dst.id); 
     288        vfi = pjmedia_get_video_format_info(NULL, vp->cap_conv_param.dst.id); 
    291289        if (!vfi) 
    292290            return PJMEDIA_EBADFMT; 
    293291 
    294292        pj_bzero(&vafp, sizeof(vafp)); 
    295         vafp.size = conv_param.dst.det.vid.size; 
     293        vafp.size = vp->cap_conv_param.dst.det.vid.size; 
    296294        status = vfi->apply_fmt(vfi, &vafp); 
    297295        if (status != PJ_SUCCESS) 
     
    354352 
    355353        vfi = pjmedia_get_video_format_info(NULL, vp->cap_conv? 
    356                                             conv_param.src.id: 
     354                                            vp->cap_conv_param.src.id: 
    357355                                            vparam.fmt.id); 
    358356        if (!vfi) { 
     
    362360 
    363361        pj_bzero(&vafp, sizeof(vafp)); 
    364         vafp.size = (vp->cap_conv? conv_param.src.det.vid.size: 
     362        vafp.size = (vp->cap_conv? vp->cap_conv_param.src.det.vid.size: 
    365363                     vparam.fmt.det.vid.size); 
    366364        status = vfi->apply_fmt(vfi, &vafp); 
     
    611609        pj_status_t status; 
    612610 
     611        pjmedia_vid_port_stop(vp); 
     612 
    613613        /* Retrieve the video format detail */ 
    614614        vfd = pjmedia_format_get_video_format_detail( 
     
    617617            return PJMEDIA_EVID_BADFORMAT; 
    618618        pj_assert(vfd->fps.num); 
     619 
     620        if (vp->cap_conv) { 
     621            /* Change the destination format to the new format */ 
     622            pjmedia_format_copy(&vp->cap_conv_param.src, 
     623                                &vp->client_port->info.fmt); 
     624            /* Only copy the size here */ 
     625            vp->cap_conv_param.dst.det.vid.size = 
     626                vp->client_port->info.fmt.det.vid.size, 
     627 
     628            /* Recreate converter */ 
     629            pjmedia_converter_destroy(vp->cap_conv); 
     630            status = pjmedia_converter_create(NULL, vp->pool, 
     631                                              &vp->cap_conv_param, 
     632                                              &vp->cap_conv); 
     633            if (status != PJ_SUCCESS) { 
     634                PJ_PERROR(4,(THIS_FILE, status, "Error recreating converter")); 
     635                return status; 
     636            } 
     637        } 
    619638 
    620639        status = pjmedia_vid_dev_stream_set_cap( 
     
    628647                                  status != PJMEDIA_EVID_ERR ? "success" : 
    629648                                  "failure")); 
    630             pjmedia_vid_port_stop(vp); 
    631649            return status; 
    632650        } 
     
    650668        /* Notify application of the format change. */ 
    651669        pevent.event_type = PJMEDIA_EVENT_FMT_CHANGED; 
    652         pj_memcpy(&pevent.event_desc.fmt_change.new_format, 
    653                   &vp->client_port->info.fmt, sizeof(pjmedia_format)); 
     670        pjmedia_format_copy(&pevent.event_desc.fmt_change.new_format, 
     671                            &vp->client_port->info.fmt); 
    654672        if (vp->strm_cb.on_event_cb) 
    655673            (*vp->strm_cb.on_event_cb)(vp->strm, vp->strm_cb_data, &pevent); 
     674 
     675        pjmedia_vid_port_start(vp); 
    656676    } 
    657677 
Note: See TracChangeset for help on using the changeset viewer.