Ignore:
Timestamp:
Dec 28, 2016 3:40:07 AM (7 years ago)
Author:
nanang
Message:

Re #1900: More merged from trunk (r5512 mistakenly contains merged changes in third-party dir only).

Location:
pjproject/branches/projects/uwp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/uwp

  • pjproject/branches/projects/uwp/pjmedia/src/pjmedia-videodev/videodev.c

    r5125 r5513  
    1919#include <pjmedia-videodev/videodev_imp.h> 
    2020#include <pj/assert.h> 
    21 #include <pj/errno.h> 
    22 #include <pj/log.h> 
    23 #include <pj/pool.h> 
    24 #include <pj/string.h> 
    2521 
    2622 
     
    2925 
    3026#define THIS_FILE   "videodev.c" 
    31  
    32 #define DEFINE_CAP(name, info)  {name, info} 
    33  
    34 /* Capability names */ 
    35 static struct cap_info 
    36 { 
    37     const char *name; 
    38     const char *info; 
    39 } cap_infos[] =  
    40 { 
    41     DEFINE_CAP("format",        "Video format"), 
    42     DEFINE_CAP("scale",         "Input dimension"), 
    43     DEFINE_CAP("window",        "Window handle"), 
    44     DEFINE_CAP("resize",        "Renderer resize"), 
    45     DEFINE_CAP("position",      "Renderer position"), 
    46     DEFINE_CAP("hide",          "Renderer hide"), 
    47     DEFINE_CAP("preview",       "Input preview"), 
    48     DEFINE_CAP("orientation",   "Video orientation"), 
    49     DEFINE_CAP("switch",        "Switch device"), 
    50     DEFINE_CAP("wndflags",      "Window flags") 
    51 }; 
    52  
    53  
    54 /* 
    55  * The device index seen by application and driver is different.  
    56  * 
    57  * At application level, device index is index to global list of device. 
    58  * At driver level, device index is index to device list on that particular 
    59  * factory only. 
    60  */ 
    61 #define MAKE_DEV_ID(f_id, index)   (((f_id & 0xFFFF) << 16) | (index & 0xFFFF)) 
    62 #define GET_INDEX(dev_id)          ((dev_id) & 0xFFFF) 
    63 #define GET_FID(dev_id)            ((dev_id) >> 16) 
    64 #define DEFAULT_DEV_ID              0 
    6527 
    6628 
     
    9456#endif 
    9557 
    96 #if PJMEDIA_VIDEO_DEV_HAS_IOS 
    97 pjmedia_vid_dev_factory* pjmedia_ios_factory(pj_pool_factory *pf); 
     58#if PJMEDIA_VIDEO_DEV_HAS_DARWIN 
     59pjmedia_vid_dev_factory* pjmedia_darwin_factory(pj_pool_factory *pf); 
    9860#endif 
    9961 
     
    11072 
    11173 
    112 /* driver structure */ 
    113 struct driver 
    114 { 
    115     /* Creation function */ 
    116     pjmedia_vid_dev_factory_create_func_ptr create; 
    117     /* Factory instance */ 
    118     pjmedia_vid_dev_factory *f; 
    119     char                     name[32];      /* Driver name                  */ 
    120     unsigned                 dev_cnt;       /* Number of devices            */ 
    121     unsigned                 start_idx;     /* Start index in global list   */ 
    122     int                      cap_dev_idx;   /* Default capture device.      */ 
    123     int                      rend_dev_idx;  /* Default render device        */ 
    124 }; 
    125  
    126 /* The video device subsystem */ 
    127 static struct vid_subsys 
    128 { 
    129     unsigned         init_count;        /* How many times init() is called  */ 
    130     pj_pool_factory *pf;                /* The pool factory.                */ 
    131  
    132     unsigned         drv_cnt;           /* Number of drivers.               */ 
    133     struct driver    drv[MAX_DRIVERS];  /* Array of drivers.                */ 
    134  
    135     unsigned         dev_cnt;           /* Total number of devices.         */ 
    136     pj_uint32_t      dev_list[MAX_DEVS];/* Array of device IDs.             */ 
    137  
    138 } vid_subsys; 
    139  
    140 /* API: get capability name/info */ 
    141 PJ_DEF(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap, 
    142                                              const char **p_desc) 
    143 { 
    144     const char *desc; 
    145     unsigned i; 
    146  
    147     if (p_desc==NULL) p_desc = &desc; 
    148  
    149     for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 
    150         if ((1 << i)==cap) 
    151             break; 
    152     } 
    153  
    154     if (i==PJ_ARRAY_SIZE(cap_infos)) { 
    155         *p_desc = "??"; 
    156         return "??"; 
    157     } 
    158  
    159     *p_desc = cap_infos[i].info; 
    160     return cap_infos[i].name; 
    161 } 
    162  
    163 static pj_status_t get_cap_pointer(const pjmedia_vid_dev_param *param, 
    164                                    pjmedia_vid_dev_cap cap, 
    165                                    void **ptr, 
    166                                    unsigned *size) 
    167 { 
    168 #define FIELD_INFO(name)    *ptr = (void*)&param->name; \ 
    169                             *size = sizeof(param->name) 
    170  
    171     switch (cap) { 
    172     case PJMEDIA_VID_DEV_CAP_FORMAT: 
    173         FIELD_INFO(fmt); 
    174         break; 
    175     case PJMEDIA_VID_DEV_CAP_INPUT_SCALE: 
    176         FIELD_INFO(disp_size); 
    177         break; 
    178     case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW: 
    179         FIELD_INFO(window); 
    180         break; 
    181     case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE: 
    182         FIELD_INFO(disp_size); 
    183         break; 
    184     case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION: 
    185         FIELD_INFO(window_pos); 
    186         break; 
    187     case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE: 
    188         FIELD_INFO(window_hide); 
    189         break; 
    190     case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW: 
    191         FIELD_INFO(native_preview); 
    192         break; 
    193     case PJMEDIA_VID_DEV_CAP_ORIENTATION: 
    194         FIELD_INFO(orient); 
    195         break; 
    196     /* The PJMEDIA_VID_DEV_CAP_SWITCH does not have an entry in the 
    197      * param (it doesn't make sense to open a stream and tell it 
    198      * to switch immediately). 
    199      */ 
    200     case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS: 
    201         FIELD_INFO(window_flags); 
    202         break; 
    203     default: 
    204         return PJMEDIA_EVID_INVCAP; 
    205     } 
    206  
    207 #undef FIELD_INFO 
    208  
    209     return PJ_SUCCESS; 
    210 } 
    211  
    212 /* API: set cap value to param */ 
    213 PJ_DEF(pj_status_t) 
    214 pjmedia_vid_dev_param_set_cap( pjmedia_vid_dev_param *param, 
    215                                pjmedia_vid_dev_cap cap, 
    216                                const void *pval) 
    217 { 
    218     void *cap_ptr; 
    219     unsigned cap_size; 
    220     pj_status_t status; 
    221  
    222     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    223     if (status != PJ_SUCCESS) 
    224         return status; 
    225  
    226     pj_memcpy(cap_ptr, pval, cap_size); 
    227     param->flags |= cap; 
    228  
    229     return PJ_SUCCESS; 
    230 } 
    231  
    232 /* API: get cap value from param */ 
    233 PJ_DEF(pj_status_t) 
    234 pjmedia_vid_dev_param_get_cap( const pjmedia_vid_dev_param *param, 
    235                                pjmedia_vid_dev_cap cap, 
    236                                void *pval) 
    237 { 
    238     void *cap_ptr; 
    239     unsigned cap_size; 
    240     pj_status_t status; 
    241  
    242     status = get_cap_pointer(param, cap, &cap_ptr, &cap_size); 
    243     if (status != PJ_SUCCESS) 
    244         return status; 
    245  
    246     if ((param->flags & cap) == 0) { 
    247         pj_bzero(cap_ptr, cap_size); 
    248         return PJMEDIA_EVID_INVCAP; 
    249     } 
    250  
    251     pj_memcpy(pval, cap_ptr, cap_size); 
    252     return PJ_SUCCESS; 
    253 } 
    254  
    255 /* Internal: init driver */ 
    256 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh) 
    257 { 
    258     struct driver *drv = &vid_subsys.drv[drv_idx]; 
    259     pjmedia_vid_dev_factory *f; 
    260     unsigned i, dev_cnt; 
    261     pj_status_t status; 
    262  
    263     if (!refresh) { 
    264         /* Create the factory */ 
    265         f = (*drv->create)(vid_subsys.pf); 
    266         if (!f) 
    267             return PJ_EUNKNOWN; 
    268  
    269         /* Call factory->init() */ 
    270         status = f->op->init(f); 
    271         if (status != PJ_SUCCESS) { 
    272             f->op->destroy(f); 
    273             return status; 
    274         } 
    275     } else { 
    276         f = drv->f; 
    277     } 
    278  
    279     /* Get number of devices */ 
    280     dev_cnt = f->op->get_dev_count(f); 
    281     if (dev_cnt + vid_subsys.dev_cnt > MAX_DEVS) { 
    282         PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 
    283                               " there are too many devices", 
    284                               vid_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 
    285         dev_cnt = MAX_DEVS - vid_subsys.dev_cnt; 
    286     } 
    287  
    288     /* enabling this will cause pjsua-lib initialization to fail when there 
    289      * is no video device installed in the system, even when pjsua has been 
    290      * run with --null-video 
    291      * 
    292     if (dev_cnt == 0) { 
    293         f->op->destroy(f); 
    294         return PJMEDIA_EVID_NODEV; 
    295     } 
    296     */ 
    297  
    298     /* Fill in default devices */ 
    299     drv->rend_dev_idx = drv->cap_dev_idx = -1; 
    300     for (i=0; i<dev_cnt; ++i) { 
    301         pjmedia_vid_dev_info info; 
    302  
    303         status = f->op->get_dev_info(f, i, &info); 
    304         if (status != PJ_SUCCESS) { 
    305             f->op->destroy(f); 
    306             return status; 
    307         } 
    308  
    309         if (drv->name[0]=='\0') { 
    310             /* Set driver name */ 
    311             pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name)); 
    312             drv->name[sizeof(drv->name)-1] = '\0'; 
    313         } 
    314  
    315         if (drv->rend_dev_idx < 0 && (info.dir & PJMEDIA_DIR_RENDER)) { 
    316             /* Set default render device */ 
    317             drv->rend_dev_idx = i; 
    318         } 
    319         if (drv->cap_dev_idx < 0 && (info.dir & PJMEDIA_DIR_CAPTURE)) { 
    320             /* Set default capture device */ 
    321             drv->cap_dev_idx = i; 
    322         } 
    323  
    324         if (drv->rend_dev_idx >= 0 && drv->cap_dev_idx >= 0) { 
    325             /* Done. */ 
    326             break; 
    327         } 
    328     } 
    329  
    330     /* Register the factory */ 
    331     drv->f = f; 
    332     drv->f->sys.drv_idx = drv_idx; 
    333     drv->start_idx = vid_subsys.dev_cnt; 
    334     drv->dev_cnt = dev_cnt; 
    335  
    336     /* Register devices to global list */ 
    337     for (i=0; i<dev_cnt; ++i) { 
    338         vid_subsys.dev_list[vid_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i); 
    339     } 
    340  
    341     return PJ_SUCCESS; 
    342 } 
    343  
    344 /* Internal: deinit driver */ 
    345 static void deinit_driver(unsigned drv_idx) 
    346 { 
    347     struct driver *drv = &vid_subsys.drv[drv_idx]; 
    348  
    349     if (drv->f) { 
    350         drv->f->op->destroy(drv->f); 
    351         drv->f = NULL; 
    352     } 
    353  
    354     drv->dev_cnt = 0; 
    355     drv->rend_dev_idx = drv->cap_dev_idx = -1; 
    356 } 
    357  
    35874/* API: Initialize the video device subsystem. */ 
    35975PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf) 
     
    36177    unsigned i; 
    36278    pj_status_t status = PJ_SUCCESS; 
     79    pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 
    36380 
    36481    /* Allow init() to be called multiple times as long as there is matching 
    36582     * number of shutdown(). 
    36683     */ 
    367     if (vid_subsys.init_count++ != 0) { 
     84    if (vid_subsys->init_count++ != 0) { 
    36885        return PJ_SUCCESS; 
    36986    } 
     
    37592 
    37693    /* Init */ 
    377     vid_subsys.pf = pf; 
    378     vid_subsys.drv_cnt = 0; 
    379     vid_subsys.dev_cnt = 0; 
     94    vid_subsys->pf = pf; 
     95    vid_subsys->drv_cnt = 0; 
     96    vid_subsys->dev_cnt = 0; 
    38097 
    38198    /* Register creation functions */ 
    38299#if PJMEDIA_VIDEO_DEV_HAS_V4L2 
    383     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_v4l2_factory; 
     100    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_v4l2_factory; 
    384101#endif 
    385102#if PJMEDIA_VIDEO_DEV_HAS_QT 
    386     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_qt_factory; 
     103    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory; 
    387104#endif 
    388105#if PJMEDIA_VIDEO_DEV_HAS_OPENGL 
    389     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_opengl_factory; 
    390 #endif 
    391 #if PJMEDIA_VIDEO_DEV_HAS_IOS 
    392     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_ios_factory; 
     106    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory; 
     107#endif 
     108#if PJMEDIA_VIDEO_DEV_HAS_DARWIN 
     109    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_darwin_factory; 
    393110#endif 
    394111#if PJMEDIA_VIDEO_DEV_HAS_DSHOW 
    395     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_dshow_factory; 
     112    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_dshow_factory; 
    396113#endif 
    397114#if PJMEDIA_VIDEO_DEV_HAS_FFMPEG 
    398     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_ffmpeg_factory; 
     115    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ffmpeg_factory; 
    399116#endif 
    400117#if PJMEDIA_VIDEO_DEV_HAS_SDL 
    401     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_sdl_factory; 
     118    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_sdl_factory; 
    402119#endif 
    403120#if PJMEDIA_VIDEO_DEV_HAS_ANDROID 
    404     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_and_factory; 
     121    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_and_factory; 
    405122#endif 
    406123#if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC 
     
    408125     * a real capturer, if any. 
    409126     */ 
    410     vid_subsys.drv[vid_subsys.drv_cnt++].create = &pjmedia_cbar_factory; 
     127    vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_cbar_factory; 
    411128#endif 
    412129 
    413130    /* Initialize each factory and build the device ID list */ 
    414     for (i=0; i<vid_subsys.drv_cnt; ++i) { 
    415         status = init_driver(i, PJ_FALSE); 
     131    for (i=0; i<vid_subsys->drv_cnt; ++i) { 
     132        status = pjmedia_vid_driver_init(i, PJ_FALSE); 
    416133        if (status != PJ_SUCCESS) { 
    417             deinit_driver(i); 
     134            pjmedia_vid_driver_deinit(i); 
    418135            continue; 
    419136        } 
    420137    } 
    421138 
    422     return vid_subsys.dev_cnt ? PJ_SUCCESS : status; 
     139    return vid_subsys->dev_cnt ? PJ_SUCCESS : status; 
    423140} 
    424141 
     
    430147    pj_bool_t refresh = PJ_FALSE; 
    431148    pj_status_t status; 
    432  
    433     if (vid_subsys.init_count == 0) 
     149    pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 
     150 
     151    if (vid_subsys->init_count == 0) 
    434152        return PJMEDIA_EVID_INIT; 
    435153 
    436     vid_subsys.drv[vid_subsys.drv_cnt].create = adf; 
    437     vid_subsys.drv[vid_subsys.drv_cnt].f = factory; 
     154    vid_subsys->drv[vid_subsys->drv_cnt].create = adf; 
     155    vid_subsys->drv[vid_subsys->drv_cnt].f = factory; 
    438156 
    439157    if (factory) { 
     
    447165    } 
    448166 
    449     status = init_driver(vid_subsys.drv_cnt, refresh); 
     167    status = pjmedia_vid_driver_init(vid_subsys->drv_cnt, refresh); 
    450168    if (status == PJ_SUCCESS) { 
    451         vid_subsys.drv_cnt++; 
     169        vid_subsys->drv_cnt++; 
    452170    } else { 
    453         deinit_driver(vid_subsys.drv_cnt); 
     171        pjmedia_vid_driver_deinit(vid_subsys->drv_cnt); 
    454172    } 
    455173 
     
    463181{ 
    464182    unsigned i, j; 
    465  
    466     if (vid_subsys.init_count == 0) 
     183    pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 
     184 
     185    if (vid_subsys->init_count == 0) 
    467186        return PJMEDIA_EVID_INIT; 
    468187 
    469     for (i=0; i<vid_subsys.drv_cnt; ++i) { 
    470         struct driver *drv = &vid_subsys.drv[i]; 
     188    for (i=0; i<vid_subsys->drv_cnt; ++i) { 
     189        pjmedia_vid_driver *drv = &vid_subsys->drv[i]; 
    471190 
    472191        if ((factory && drv->f==factory) || (adf && drv->create == adf)) { 
    473192            for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 
    474193            { 
    475                 vid_subsys.dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV; 
     194                vid_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV; 
    476195            } 
    477196 
    478             deinit_driver(i); 
     197            pjmedia_vid_driver_deinit(i); 
    479198            pj_bzero(drv, sizeof(*drv)); 
    480199            return PJ_SUCCESS; 
     
    488207PJ_DEF(pj_pool_factory*) pjmedia_vid_dev_subsys_get_pool_factory(void) 
    489208{ 
    490     return vid_subsys.pf; 
     209    pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 
     210    return vid_subsys->pf; 
    491211} 
    492212 
     
    495215{ 
    496216    unsigned i; 
     217    pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 
    497218 
    498219    /* Allow shutdown() to be called multiple times as long as there is 
    499220     * matching number of init(). 
    500221     */ 
    501     if (vid_subsys.init_count == 0) { 
     222    if (vid_subsys->init_count == 0) { 
    502223        return PJ_SUCCESS; 
    503224    } 
    504     --vid_subsys.init_count; 
    505  
    506     if (vid_subsys.init_count == 0) { 
    507         for (i=0; i<vid_subsys.drv_cnt; ++i) { 
    508             deinit_driver(i); 
     225    --vid_subsys->init_count; 
     226 
     227    if (vid_subsys->init_count == 0) { 
     228        for (i=0; i<vid_subsys->drv_cnt; ++i) { 
     229            pjmedia_vid_driver_deinit(i); 
    509230        } 
    510231 
    511         vid_subsys.pf = NULL; 
     232        vid_subsys->pf = NULL; 
    512233    } 
    513234    return PJ_SUCCESS; 
    514235} 
    515236 
    516 /* API: Refresh the list of video devices installed in the system. */ 
    517 PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void) 
    518 { 
    519     unsigned i; 
    520      
    521     vid_subsys.dev_cnt = 0; 
    522     for (i=0; i<vid_subsys.drv_cnt; ++i) { 
    523         struct driver *drv = &vid_subsys.drv[i]; 
    524          
    525         if (drv->f && drv->f->op->refresh) { 
    526             pj_status_t status = drv->f->op->refresh(drv->f); 
    527             if (status != PJ_SUCCESS) { 
    528                 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device " 
    529                                                  "list for %s", drv->name)); 
    530             } 
    531         } 
    532         init_driver(i, PJ_TRUE); 
    533     } 
    534     return PJ_SUCCESS; 
    535 } 
    536  
    537 /* API: Get the number of video devices installed in the system. */ 
    538 PJ_DEF(unsigned) pjmedia_vid_dev_count(void) 
    539 { 
    540     return vid_subsys.dev_cnt; 
    541 } 
    542  
    543 /* Internal: convert local index to global device index */ 
    544 static pj_status_t make_global_index(unsigned drv_idx,  
    545                                      pjmedia_vid_dev_index *id) 
    546 { 
    547     if (*id < 0) { 
    548         return PJ_SUCCESS; 
    549     } 
    550  
    551     /* Check that factory still exists */ 
    552     PJ_ASSERT_RETURN(vid_subsys.drv[drv_idx].f, PJ_EBUG); 
    553  
    554     /* Check that device index is valid */ 
    555     PJ_ASSERT_RETURN(*id>=0 && *id<(int)vid_subsys.drv[drv_idx].dev_cnt,  
    556                      PJ_EBUG); 
    557  
    558     *id += vid_subsys.drv[drv_idx].start_idx; 
    559     return PJ_SUCCESS; 
    560 } 
    561  
    562 /* Internal: lookup device id */ 
    563 static pj_status_t lookup_dev(pjmedia_vid_dev_index id, 
    564                               pjmedia_vid_dev_factory **p_f, 
    565                               unsigned *p_local_index) 
    566 { 
    567     int f_id, index; 
    568  
    569     if (id < 0) { 
    570         unsigned i; 
    571  
    572         if (id <= PJMEDIA_VID_INVALID_DEV) 
    573             return PJMEDIA_EVID_INVDEV; 
    574  
    575         for (i=0; i<vid_subsys.drv_cnt; ++i) { 
    576             struct driver *drv = &vid_subsys.drv[i]; 
    577             if (id==PJMEDIA_VID_DEFAULT_CAPTURE_DEV &&  
    578                 drv->cap_dev_idx >= 0)  
    579             { 
    580                 id = drv->cap_dev_idx; 
    581                 make_global_index(i, &id); 
    582                 break; 
    583             } else if (id==PJMEDIA_VID_DEFAULT_RENDER_DEV &&  
    584                 drv->rend_dev_idx >= 0)  
    585             { 
    586                 id = drv->rend_dev_idx; 
    587                 make_global_index(i, &id); 
    588                 break; 
    589             } 
    590         } 
    591  
    592         if (id < 0) { 
    593             return PJMEDIA_EVID_NODEFDEV; 
    594         } 
    595     } 
    596  
    597     f_id = GET_FID(vid_subsys.dev_list[id]); 
    598     index = GET_INDEX(vid_subsys.dev_list[id]); 
    599  
    600     if (f_id < 0 || f_id >= (int)vid_subsys.drv_cnt) 
    601         return PJMEDIA_EVID_INVDEV; 
    602  
    603     if (index < 0 || index >= (int)vid_subsys.drv[f_id].dev_cnt) 
    604         return PJMEDIA_EVID_INVDEV; 
    605  
    606     *p_f = vid_subsys.drv[f_id].f; 
    607     *p_local_index = (unsigned)index; 
    608  
    609     return PJ_SUCCESS; 
    610  
    611 } 
    612  
    613 /* API: lookup device id */ 
    614 PJ_DEF(pj_status_t) 
    615 pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id, 
    616                                 pjmedia_vid_dev_factory **p_f, 
    617                                 unsigned *p_local_index) 
    618 { 
    619     return lookup_dev(id, p_f, p_local_index); 
    620 } 
    621  
    622 /* API: from factory and local index, get global index */ 
    623 PJ_DEF(pj_status_t) 
    624 pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f, 
    625                                  unsigned local_idx, 
    626                                  pjmedia_vid_dev_index *pid) 
    627 { 
    628     PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS, 
    629                      PJ_EINVALIDOP); 
    630     *pid = local_idx; 
    631     return make_global_index(f->sys.drv_idx, pid); 
    632 } 
    633  
    634 /* API: Get device information. */ 
    635 PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id, 
    636                                              pjmedia_vid_dev_info *info) 
    637 { 
    638     pjmedia_vid_dev_factory *f; 
    639     unsigned index; 
    640     pj_status_t status; 
    641  
    642     PJ_ASSERT_RETURN(info, PJ_EINVAL); 
    643     PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); 
    644  
    645     if (id <= PJMEDIA_VID_INVALID_DEV) 
    646         return PJMEDIA_EVID_INVDEV; 
    647  
    648     status = lookup_dev(id, &f, &index); 
    649     if (status != PJ_SUCCESS) 
    650         return status; 
    651  
    652     status = f->op->get_dev_info(f, index, info); 
    653  
    654     /* Make sure device ID is the real ID (not PJMEDIA_VID_DEFAULT_*_DEV) */ 
    655     info->id = index; 
    656     make_global_index(f->sys.drv_idx, &info->id); 
    657  
    658     return status; 
    659 } 
    660  
    661 /* API: find device */ 
    662 PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name, 
    663                                             const char *dev_name, 
    664                                             pjmedia_vid_dev_index *id) 
    665 { 
    666     pjmedia_vid_dev_factory *f = NULL; 
    667     unsigned drv_idx, dev_idx; 
    668  
    669     PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 
    670     PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); 
    671  
    672     for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) { 
    673         if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name)) 
    674         { 
    675             f = vid_subsys.drv[drv_idx].f; 
    676             break; 
    677         } 
    678     } 
    679  
    680     if (!f) 
    681         return PJ_ENOTFOUND; 
    682  
    683     for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx) 
    684     { 
    685         pjmedia_vid_dev_info info; 
    686         pj_status_t status; 
    687  
    688         status = f->op->get_dev_info(f, dev_idx, &info); 
    689         if (status != PJ_SUCCESS) 
    690             return status; 
    691  
    692         if (!pj_ansi_stricmp(dev_name, info.name)) 
    693             break; 
    694     } 
    695  
    696     if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt) 
    697         return PJ_ENOTFOUND; 
    698  
    699     *id = dev_idx; 
    700     make_global_index(drv_idx, id); 
    701  
    702     return PJ_SUCCESS; 
    703 } 
    704  
    705 /* API: Initialize the video device parameters with default values for the 
    706  * specified device. 
    707  */ 
    708 PJ_DEF(pj_status_t) pjmedia_vid_dev_default_param(pj_pool_t *pool, 
    709                                                   pjmedia_vid_dev_index id, 
    710                                                   pjmedia_vid_dev_param *param) 
    711 { 
    712     pjmedia_vid_dev_factory *f; 
    713     unsigned index; 
    714     pj_status_t status; 
    715  
    716     PJ_ASSERT_RETURN(param, PJ_EINVAL); 
    717     PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); 
    718  
    719     if (id <= PJMEDIA_VID_INVALID_DEV) 
    720         return PJMEDIA_EVID_INVDEV; 
    721  
    722     status = lookup_dev(id, &f, &index); 
    723     if (status != PJ_SUCCESS) 
    724         return status; 
    725  
    726     status = f->op->default_param(pool, f, index, param); 
    727     if (status != PJ_SUCCESS) 
    728         return status; 
    729  
    730     /* Normalize device IDs */ 
    731     make_global_index(f->sys.drv_idx, &param->cap_id); 
    732     make_global_index(f->sys.drv_idx, &param->rend_id); 
    733  
    734     return PJ_SUCCESS; 
    735 } 
    736  
    737 /* API: Open video stream object using the specified parameters. */ 
    738 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create( 
    739                                         pjmedia_vid_dev_param *prm, 
    740                                         const pjmedia_vid_dev_cb *cb, 
    741                                         void *user_data, 
    742                                         pjmedia_vid_dev_stream **p_vid_strm) 
    743 { 
    744     pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL; 
    745     pj_status_t status; 
    746  
    747     PJ_ASSERT_RETURN(prm && prm->dir && p_vid_strm, PJ_EINVAL); 
    748     PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); 
    749     PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE || 
    750                      prm->dir==PJMEDIA_DIR_RENDER || 
    751                      prm->dir==PJMEDIA_DIR_CAPTURE_RENDER, 
    752                      PJ_EINVAL); 
    753  
    754     /* Normalize cap_id */ 
    755     if (prm->dir & PJMEDIA_DIR_CAPTURE) { 
    756         unsigned index; 
    757  
    758         if (prm->cap_id < 0) 
    759             prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
    760  
    761         status = lookup_dev(prm->cap_id, &cap_f, &index); 
    762         if (status != PJ_SUCCESS) 
    763             return status; 
    764  
    765         prm->cap_id = index; 
    766         f = cap_f; 
    767     } 
    768  
    769     /* Normalize rend_id */ 
    770     if (prm->dir & PJMEDIA_DIR_RENDER) { 
    771         unsigned index; 
    772  
    773         if (prm->rend_id < 0) 
    774             prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV; 
    775  
    776         status = lookup_dev(prm->rend_id, &rend_f, &index); 
    777         if (status != PJ_SUCCESS) 
    778             return status; 
    779  
    780         prm->rend_id = index; 
    781         f = rend_f; 
    782     } 
    783  
    784     PJ_ASSERT_RETURN(f != NULL, PJ_EBUG); 
    785  
    786     /* For now, cap_id and rend_id must belong to the same factory */ 
    787     PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) || 
    788                      (cap_f == rend_f), 
    789                      PJMEDIA_EVID_INVDEV); 
    790  
    791     /* Create the stream */ 
    792     status = f->op->create_stream(f, prm, cb, 
    793                                   user_data, p_vid_strm); 
    794     if (status != PJ_SUCCESS) 
    795         return status; 
    796  
    797     /* Assign factory id to the stream */ 
    798     (*p_vid_strm)->sys.drv_idx = f->sys.drv_idx; 
    799     return PJ_SUCCESS; 
    800 } 
    801  
    802 /* API: Get the running parameters for the specified video stream. */ 
    803 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_param( 
    804                                             pjmedia_vid_dev_stream *strm, 
    805                                             pjmedia_vid_dev_param *param) 
    806 { 
    807     pj_status_t status; 
    808  
    809     PJ_ASSERT_RETURN(strm && param, PJ_EINVAL); 
    810     PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT); 
    811  
    812     status = strm->op->get_param(strm, param); 
    813     if (status != PJ_SUCCESS) 
    814         return status; 
    815  
    816     /* Normalize device id's */ 
    817     make_global_index(strm->sys.drv_idx, &param->cap_id); 
    818     make_global_index(strm->sys.drv_idx, &param->rend_id); 
    819  
    820     return PJ_SUCCESS; 
    821 } 
    822  
    823 /* API: Get the value of a specific capability of the video stream. */ 
    824 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_cap( 
    825                                             pjmedia_vid_dev_stream *strm, 
    826                                             pjmedia_vid_dev_cap cap, 
    827                                             void *value) 
    828 { 
    829     return strm->op->get_cap(strm, cap, value); 
    830 } 
    831  
    832 /* API: Set the value of a specific capability of the video stream. */ 
    833 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_set_cap( 
    834                                             pjmedia_vid_dev_stream *strm, 
    835                                             pjmedia_vid_dev_cap cap, 
    836                                             const void *value) 
    837 { 
    838     /* For fast switching, device global index needs to be converted to 
    839      * local index before forwarding the request to the device stream. 
    840      */ 
    841     if (cap == PJMEDIA_VID_DEV_CAP_SWITCH) { 
    842         pjmedia_vid_dev_factory *f; 
    843         unsigned local_idx; 
    844         pj_status_t status; 
    845         pjmedia_vid_dev_switch_param p = *(pjmedia_vid_dev_switch_param*)value; 
    846  
    847         status = lookup_dev(p.target_id, &f, &local_idx); 
    848         if (status != PJ_SUCCESS) 
    849             return status; 
    850  
    851         /* Make sure that current & target devices share the same factory */ 
    852         if (f->sys.drv_idx != strm->sys.drv_idx) 
    853             return PJMEDIA_EVID_INVDEV; 
    854  
    855         p.target_id = local_idx; 
    856         return strm->op->set_cap(strm, cap, &p); 
    857     } 
    858  
    859     return strm->op->set_cap(strm, cap, value); 
    860 } 
    861  
    862 /* API: Start the stream. */ 
    863 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm) 
    864 { 
    865     pj_status_t status; 
    866  
    867     if (pjmedia_vid_dev_stream_is_running(strm)) 
    868         return PJ_SUCCESS; 
    869  
    870     status = strm->op->start(strm); 
    871     if (status == PJ_SUCCESS) 
    872         strm->sys.is_running = PJ_TRUE; 
    873     return status; 
    874 } 
    875  
    876 /* API: has it been started? */ 
    877 PJ_DEF(pj_bool_t) 
    878 pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm) 
    879 { 
    880     return strm->sys.is_running; 
    881 } 
    882  
    883 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_frame( 
    884                                             pjmedia_vid_dev_stream *strm, 
    885                                             pjmedia_frame *frame) 
    886 { 
    887     pj_assert(strm->op->get_frame); 
    888     return strm->op->get_frame(strm, frame); 
    889 } 
    890  
    891 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_put_frame( 
    892                                             pjmedia_vid_dev_stream *strm, 
    893                                             const pjmedia_frame *frame) 
    894 { 
    895     pj_assert(strm->op->put_frame); 
    896     return strm->op->put_frame(strm, frame); 
    897 } 
    898  
    899 /* API: Stop the stream. */ 
    900 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_stop(pjmedia_vid_dev_stream *strm) 
    901 { 
    902     strm->sys.is_running = PJ_FALSE; 
    903     return strm->op->stop(strm); 
    904 } 
    905  
    906 /* API: Destroy the stream. */ 
    907 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_destroy( 
    908                                                 pjmedia_vid_dev_stream *strm) 
    909 { 
    910     strm->sys.is_running = PJ_FALSE; 
    911     return strm->op->destroy(strm); 
    912 } 
    913  
    914237 
    915238#endif /* PJMEDIA_HAS_VIDEO */ 
Note: See TracChangeset for help on using the changeset viewer.