Changeset 3489


Ignore:
Timestamp:
Mar 25, 2011 8:38:26 AM (9 years ago)
Author:
bennylp
Message:

Re #1213 (Video devices):

  • Video device now opens in "best effort" mode, i.e. it may open with different size and fps than requested. The actual size and fps will be reflected in the "param" upon return. The vidport must check this against any differences, and create converter accordingly.
  • Removed const for param argument in vid_create_stream() API
  • Currently converter in vidport will not work if vidport is opened in bidir. Converter for renderer is untested
Location:
pjproject/branches/projects/2.0-dev/pjmedia
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia-videodev/videodev.h

    r3431 r3489  
    472472 
    473473/** 
    474  * Open video stream object using the specified parameters. 
     474 * Open video stream object using the specified parameters. If stream is 
     475 * created successfully, this function will return PJ_SUCCESS and the 
     476 * stream pointer will be returned in the p_strm argument. 
     477 * 
     478 * The opened stream may have been opened with different size and fps 
     479 * than the requested values in the \a param argument. Application should 
     480 * check the actual size and fps that the stream was opened with by inspecting 
     481 * the values in the \a param argument and see if they have changed. Also 
     482 * if the device ID in the \a param specifies default device, it may be 
     483 * replaced with the actual device ID upon return. 
    475484 * 
    476485 * @param param         Sound device parameters to be used for the stream. 
     
    485494 */ 
    486495PJ_DECL(pj_status_t) pjmedia_vid_dev_stream_create( 
    487                                             const pjmedia_vid_param *param, 
     496                                            pjmedia_vid_param *param, 
    488497                                            const pjmedia_vid_cb *cb, 
    489498                                            void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia-videodev/videodev_imp.h

    r3420 r3489  
    8787     */ 
    8888    pj_status_t (*create_stream)(pjmedia_vid_dev_factory *f, 
    89                                  const pjmedia_vid_param *param, 
     89                                 pjmedia_vid_param *param, 
    9090                                 const pjmedia_vid_cb *cb, 
    9191                                 void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/colorbar_dev.c

    r3459 r3489  
    110110static pj_status_t cbar_factory_create_stream( 
    111111                                        pjmedia_vid_dev_factory *f, 
    112                                         const pjmedia_vid_param *param, 
     112                                        pjmedia_vid_param *param, 
    113113                                        const pjmedia_vid_cb *cb, 
    114114                                        void *user_data, 
     
    363363static pj_status_t cbar_factory_create_stream( 
    364364                                        pjmedia_vid_dev_factory *f, 
    365                                         const pjmedia_vid_param *param, 
     365                                        pjmedia_vid_param *param, 
    366366                                        const pjmedia_vid_cb *cb, 
    367367                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/dshow_dev.c

    r3470 r3489  
    133133static pj_status_t dshow_factory_create_stream( 
    134134                                        pjmedia_vid_dev_factory *f, 
    135                                         const pjmedia_vid_param *param, 
     135                                        pjmedia_vid_param *param, 
    136136                                        const pjmedia_vid_cb *cb, 
    137137                                        void *user_data, 
     
    711711static pj_status_t dshow_factory_create_stream( 
    712712                                        pjmedia_vid_dev_factory *f, 
    713                                         const pjmedia_vid_param *param, 
     713                                        pjmedia_vid_param *param, 
    714714                                        const pjmedia_vid_cb *cb, 
    715715                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c

    r3420 r3489  
    8989static pj_status_t ffmpeg_factory_create_stream( 
    9090                                        pjmedia_vid_dev_factory *f, 
    91                                         const pjmedia_vid_param *param, 
     91                                        pjmedia_vid_param *param, 
    9292                                        const pjmedia_vid_cb *cb, 
    9393                                        void *user_data, 
     
    337337static pj_status_t ffmpeg_factory_create_stream( 
    338338                                        pjmedia_vid_dev_factory *f, 
    339                                         const pjmedia_vid_param *param, 
     339                                        pjmedia_vid_param *param, 
    340340                                        const pjmedia_vid_cb *cb, 
    341341                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/ios_dev.m

    r3467 r3489  
    112112static pj_status_t ios_factory_create_stream( 
    113113                                        pjmedia_vid_dev_factory *f, 
    114                                         const pjmedia_vid_param *param, 
     114                                        pjmedia_vid_param *param, 
    115115                                        const pjmedia_vid_cb *cb, 
    116116                                        void *user_data, 
     
    385385static pj_status_t ios_factory_create_stream( 
    386386                                        pjmedia_vid_dev_factory *f, 
    387                                         const pjmedia_vid_param *param, 
     387                                        pjmedia_vid_param *param, 
    388388                                        const pjmedia_vid_cb *cb, 
    389389                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/qt_dev.m

    r3484 r3489  
    103103static pj_status_t qt_factory_create_stream( 
    104104                                        pjmedia_vid_dev_factory *f, 
    105                                         const pjmedia_vid_param *param, 
     105                                        pjmedia_vid_param *param, 
    106106                                        const pjmedia_vid_cb *cb, 
    107107                                        void *user_data, 
     
    349349static pj_status_t qt_factory_create_stream( 
    350350                                        pjmedia_vid_dev_factory *f, 
    351                                         const pjmedia_vid_param *param, 
     351                                        pjmedia_vid_param *param, 
    352352                                        const pjmedia_vid_cb *cb, 
    353353                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c

    r3435 r3489  
    131131static pj_status_t sdl_factory_create_stream( 
    132132                                        pjmedia_vid_dev_factory *f, 
    133                                         const pjmedia_vid_param *param, 
     133                                        pjmedia_vid_param *param, 
    134134                                        const pjmedia_vid_cb *cb, 
    135135                                        void *user_data, 
     
    579579static pj_status_t sdl_factory_create_stream( 
    580580                                        pjmedia_vid_dev_factory *f, 
    581                                         const pjmedia_vid_param *param, 
     581                                        pjmedia_vid_param *param, 
    582582                                        const pjmedia_vid_cb *cb, 
    583583                                        void *user_data, 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/v4l2_dev.c

    r3459 r3489  
    129129                                                 pjmedia_vid_param *param); 
    130130static pj_status_t vid4lin_factory_create_stream(pjmedia_vid_dev_factory *f, 
    131                                                  const pjmedia_vid_param *prm, 
     131                                                 pjmedia_vid_param *prm, 
    132132                                                 const pjmedia_vid_cb *cb, 
    133133                                                 void *user_data, 
     
    412412                                        pj_uint32_t pix_fmt) 
    413413{ 
    414     const pjmedia_video_format_detail *vfd; 
     414    pjmedia_video_format_detail *vfd; 
    415415    struct v4l2_format v4l2_fmt; 
    416416    pj_status_t status; 
     
    438438        (v4l2_fmt.fmt.pix.height != vfd->size.h)) 
    439439    { 
    440         status = PJMEDIA_EVID_BADSIZE; 
    441         return status; 
     440        /* Size has changed */ 
     441        vfd->size.w = v4l2_fmt.fmt.pix.width; 
     442        vfd->size.h = v4l2_fmt.fmt.pix.height; 
    442443    } 
    443444 
     
    514515/* API: create stream */ 
    515516static pj_status_t vid4lin_factory_create_stream(pjmedia_vid_dev_factory *f, 
    516                                       const pjmedia_vid_param *param, 
     517                                      pjmedia_vid_param *param, 
    517518                                      const pjmedia_vid_cb *cb, 
    518519                                      void *user_data, 
     
    525526    const vid4lin_fmt_map *fmt_map; 
    526527    const pjmedia_video_format_info *fmt_info; 
     528    pjmedia_video_format_detail *vfd; 
    527529    pj_status_t status = PJ_SUCCESS; 
     530 
    528531 
    529532    PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL); 
     
    539542 
    540543    vdi = &cf->dev_info[param->cap_id]; 
     544    vfd = pjmedia_format_get_video_format_detail(&param->fmt, PJ_TRUE); 
    541545 
    542546    /* Create and Initialize stream descriptor */ 
     
    552556    stream->user_data = user_data; 
    553557    stream->fd = INVALID_FD; 
    554  
    555     PJ_LOG(4,(THIS_FILE, "Opening video4linux2 device %s: format=%s..", 
    556               stream->name, fmt_info->name)); 
    557558 
    558559    stream->fd = v4l2_open(vdi->dev_name, O_RDWR | O_NONBLOCK, 0); 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/videodev.c

    r3420 r3489  
    610610/* API: Open video stream object using the specified parameters. */ 
    611611PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create( 
    612                                         const pjmedia_vid_param *prm, 
     612                                        pjmedia_vid_param *prm, 
    613613                                        const pjmedia_vid_cb *cb, 
    614614                                        void *user_data, 
     
    616616{ 
    617617    pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL; 
    618     pjmedia_vid_param param; 
    619618    pj_status_t status; 
    620619 
     
    626625                     PJ_EINVAL); 
    627626 
    628     /* Must make copy of param because we're changing device ID */ 
    629     pj_memcpy(&param, prm, sizeof(param)); 
    630  
    631627    /* Normalize cap_id */ 
    632     if (param.dir & PJMEDIA_DIR_CAPTURE) { 
     628    if (prm->dir & PJMEDIA_DIR_CAPTURE) { 
    633629        unsigned index; 
    634630 
    635         if (param.cap_id < 0) 
    636             param.cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
    637  
    638         status = lookup_dev(param.cap_id, &cap_f, &index); 
     631        if (prm->cap_id < 0) 
     632            prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
     633 
     634        status = lookup_dev(prm->cap_id, &cap_f, &index); 
    639635        if (status != PJ_SUCCESS) 
    640636            return status; 
    641637 
    642         param.cap_id = index; 
     638        prm->cap_id = index; 
    643639        f = cap_f; 
    644640    } 
    645641 
    646642    /* Normalize rend_id */ 
    647     if (param.dir & PJMEDIA_DIR_RENDER) { 
     643    if (prm->dir & PJMEDIA_DIR_RENDER) { 
    648644        unsigned index; 
    649645 
    650         if (param.rend_id < 0) 
    651             param.rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV; 
    652  
    653         status = lookup_dev(param.rend_id, &rend_f, &index); 
     646        if (prm->rend_id < 0) 
     647            prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV; 
     648 
     649        status = lookup_dev(prm->rend_id, &rend_f, &index); 
    654650        if (status != PJ_SUCCESS) 
    655651            return status; 
    656652 
    657         param.rend_id = index; 
     653        prm->rend_id = index; 
    658654        f = rend_f; 
    659655    } 
     
    662658 
    663659    /* For now, cap_id and rend_id must belong to the same factory */ 
    664     PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_RENDER) ||  
     660    PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) || 
    665661                     (cap_f == rend_f), 
    666662                     PJMEDIA_EVID_INVDEV); 
    667663 
    668664    /* Create the stream */ 
    669     status = f->op->create_stream(f, &param, cb, 
     665    status = f->op->create_stream(f, prm, cb, 
    670666                                  user_data, p_vid_strm); 
    671667    if (status != PJ_SUCCESS) 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c

    r3470 r3489  
    110110} 
    111111 
     112static const char *vid_dir_name(pjmedia_dir dir) 
     113{ 
     114    switch (dir) { 
     115    case PJMEDIA_DIR_CAPTURE: 
     116        return "capture"; 
     117    case PJMEDIA_DIR_RENDER: 
     118        return "render"; 
     119    case PJMEDIA_DIR_CAPTURE_RENDER: 
     120        return "capture and render"; 
     121    default: 
     122        return "??"; 
     123    } 
     124} 
     125 
    112126PJ_DEF(pj_status_t) pjmedia_vid_port_create( pj_pool_t *pool, 
    113127                                             const pjmedia_vid_port_param *prm, 
     
    115129{ 
    116130    pjmedia_vid_port *vp; 
    117     pjmedia_vid_dev_index dev_id = PJMEDIA_VID_INVALID_DEV; 
    118     pjmedia_vid_dev_info di; 
    119131    const pjmedia_video_format_detail *vfd; 
     132    char cap_dev_name[64], rend_dev_name[64]; 
    120133    pjmedia_vid_cb vid_cb; 
    121134    pj_bool_t need_frame_buf = PJ_FALSE; 
     
    125138 
    126139    PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL); 
    127     PJ_ASSERT_RETURN(prm->vidparam.fmt.type == PJMEDIA_TYPE_VIDEO, 
     140    PJ_ASSERT_RETURN(prm->vidparam.fmt.type == PJMEDIA_TYPE_VIDEO && 
     141                     prm->vidparam.dir != PJMEDIA_DIR_NONE, 
    128142                     PJ_EINVAL); 
    129143 
     
    134148 
    135149    PJ_ASSERT_RETURN(vfd->fps.num, PJ_EINVAL); 
    136  
    137150 
    138151    /* Allocate videoport */ 
     
    142155    vp->cap_size = vfd->size; 
    143156 
    144     /* Determine the device id to get the video device info */ 
    145     if ((vp->dir & PJMEDIA_DIR_CAPTURE) && 
    146         prm->vidparam.cap_id != PJMEDIA_VID_INVALID_DEV) 
    147     { 
    148         dev_id = prm->vidparam.cap_id; 
    149     } else if ((vp->dir & PJMEDIA_DIR_RENDER) && 
    150                prm->vidparam.rend_id != PJMEDIA_VID_INVALID_DEV) 
    151     { 
    152         dev_id = prm->vidparam.rend_id; 
    153     } else 
    154         return PJ_EINVAL; 
    155  
    156     /* Get device info */ 
    157     status = pjmedia_vid_dev_get_info(dev_id, &di); 
    158     if (status != PJ_SUCCESS) 
    159         return status; 
    160  
    161157    vparam = prm->vidparam; 
    162  
    163     /* Check if we need converter */ 
     158    cap_dev_name[0] = rend_dev_name[0] = '\0'; 
     159 
    164160    if (vp->dir & PJMEDIA_DIR_CAPTURE) { 
     161        pjmedia_vid_dev_info di; 
    165162        unsigned i; 
     163 
     164        /* Get device info */ 
     165        status = pjmedia_vid_dev_get_info(prm->vidparam.cap_id, &di); 
     166        if (status != PJ_SUCCESS) 
     167            return status; 
     168 
     169        pj_ansi_snprintf(cap_dev_name, sizeof(cap_dev_name), "%s [%s]", 
     170                         di.name, di.driver); 
    166171 
    167172        for (i = 0; i < di.fmt_cnt; ++i) { 
     
    171176 
    172177        if (i == di.fmt_cnt) { 
    173             /* Yes, we need converter */ 
    174             pjmedia_conversion_param conv_param; 
    175             const pjmedia_video_format_info *vfi; 
    176             pjmedia_video_apply_fmt_param vafp; 
    177  
    178             pjmedia_format_copy(&conv_param.src, &prm->vidparam.fmt); 
    179             pjmedia_format_copy(&conv_param.dst, &prm->vidparam.fmt); 
    180             for (i = 0; i < di.fmt_cnt; ++i) { 
    181                 conv_param.src.id = di.fmt[i].id; 
    182                 status = pjmedia_converter_create(NULL, pool, &conv_param,  
    183                                                   &vp->cap_conv); 
    184                 if (status == PJ_SUCCESS) 
    185                     break; 
    186             } 
    187             if (status != PJ_SUCCESS) 
    188                 return status; 
    189  
    190             /* Update format ID for the capture device */ 
    191             vparam.fmt.id = conv_param.src.id; 
    192  
    193             /* Allocate buffer for conversion */ 
    194             vfi = pjmedia_get_video_format_info(NULL, conv_param.dst.id); 
    195             if (!vfi) 
    196                 return PJMEDIA_EBADFMT; 
    197  
    198             pj_bzero(&vafp, sizeof(vafp)); 
    199             vafp.size = vfd->size; 
    200             status = vfi->apply_fmt(vfi, &vafp); 
    201             if (status != PJ_SUCCESS) 
    202                 return PJMEDIA_EBADFMT; 
    203  
    204             vp->cap_conv_buf = pj_pool_alloc(pool, vafp.framebytes); 
    205             vp->cap_conv_buf_size = vafp.framebytes; 
    206         } 
    207     } 
    208  
    209     PJ_LOG(4,(THIS_FILE, "Opening %s..", di.name)); 
    210  
    211     pj_strdup2_with_null(pool, &vp->dev_name, di.name); 
    212     vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE; 
     178            /* The device has no no matching format. Pick one from 
     179             * the supported formats, and later use converter to 
     180             * convert it to the required format. 
     181             */ 
     182            pj_assert(di.fmt_cnt != 0); 
     183            vparam.fmt.id = di.fmt[0].id; 
     184        } 
     185 
     186        pj_strdup2_with_null(pool, &vp->dev_name, di.name); 
     187        vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE; 
     188    } 
     189 
     190    if (vp->dir & PJMEDIA_DIR_RENDER) { 
     191        pjmedia_vid_dev_info di; 
     192        unsigned i; 
     193 
     194        /* Get device info */ 
     195        status = pjmedia_vid_dev_get_info(prm->vidparam.rend_id, &di); 
     196        if (status != PJ_SUCCESS) 
     197            return status; 
     198 
     199        pj_ansi_snprintf(rend_dev_name, sizeof(rend_dev_name), "and %s [%s]", 
     200                         di.name, di.driver); 
     201 
     202        for (i = 0; i < di.fmt_cnt; ++i) { 
     203            if (prm->vidparam.fmt.id == di.fmt[i].id) 
     204                break; 
     205        } 
     206 
     207        if (i == di.fmt_cnt) { 
     208            /* The device has no no matching format. Pick one from 
     209             * the supported formats, and later use converter to 
     210             * convert it to the required format. 
     211             */ 
     212            pj_assert(di.fmt_cnt != 0); 
     213            vparam.fmt.id = di.fmt[0].id; 
     214        } 
     215 
     216        pj_strdup2_with_null(pool, &vp->dev_name, di.name); 
     217        vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE; 
     218    } 
     219 
     220    PJ_LOG(4,(THIS_FILE, 
     221              "Opening device %s%s for %s: format=%s, size=%dx%d @%d:%d fps", 
     222              cap_dev_name, rend_dev_name, 
     223              vid_dir_name(prm->vidparam.dir), 
     224              pjmedia_get_video_format_info(NULL, vparam.fmt.id)->name, 
     225              vfd->size.w, vfd->size.h, 
     226              vfd->fps.num, vfd->fps.denum)); 
    213227 
    214228    ptime_usec = PJMEDIA_PTIME(&vfd->fps); 
     
    235249        goto on_error; 
    236250 
     251    PJ_LOG(4,(THIS_FILE, 
     252              "Device %s%s opened: format=%s, size=%dx%d @%d:%d fps", 
     253              cap_dev_name, rend_dev_name, 
     254              pjmedia_get_video_format_info(NULL, vparam.fmt.id)->name, 
     255              vparam.fmt.det.vid.size.w, vparam.fmt.det.vid.size.h, 
     256              vparam.fmt.det.vid.fps.num, vparam.fmt.det.vid.fps.denum)); 
     257 
     258    /* Instantiate converter if necessary */ 
     259    if (vparam.fmt.id != prm->vidparam.fmt.id || 
     260        vparam.fmt.det.vid.size.w != prm->vidparam.fmt.det.vid.size.w || 
     261        vparam.fmt.det.vid.size.h != prm->vidparam.fmt.det.vid.size.h /*|| 
     262        vparam.fmt.det.vid.fps.num != prm->vidparam.fmt.det.vid.fps.num || 
     263        vparam.fmt.det.vid.fps.denum != prm->vidparam.fmt.det.vid.fps.denum*/) 
     264    { 
     265        /* Yes, we need converter */ 
     266        pjmedia_conversion_param conv_param; 
     267        const pjmedia_video_format_info *vfi; 
     268        pjmedia_video_apply_fmt_param vafp; 
     269 
     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 
     284        if (status != PJ_SUCCESS) { 
     285            PJ_PERROR(4,(THIS_FILE, status, "Error creating converter")); 
     286            goto on_error; 
     287        } 
     288 
     289        /* Allocate buffer for conversion */ 
     290        vfi = pjmedia_get_video_format_info(NULL, prm->vidparam.fmt.id); 
     291        if (!vfi) 
     292            return PJMEDIA_EBADFMT; 
     293 
     294        pj_bzero(&vafp, sizeof(vafp)); 
     295        vafp.size = prm->vidparam.fmt.det.vid.size; 
     296        status = vfi->apply_fmt(vfi, &vafp); 
     297        if (status != PJ_SUCCESS) 
     298            return PJMEDIA_EBADFMT; 
     299 
     300        vp->cap_conv_buf = pj_pool_alloc(pool, vafp.framebytes); 
     301        vp->cap_conv_buf_size = vafp.framebytes; 
     302    } 
     303 
    237304    if (vp->role==ROLE_ACTIVE && vp->stream_role==ROLE_PASSIVE) { 
    238305        /* Active role is wanted, but our device is passive, so create 
     
    293360 
    294361        pj_bzero(&vafp, sizeof(vafp)); 
    295         vafp.size = vfd->size; 
     362        vafp.size = vparam.fmt.det.vid.size; 
    296363        status = vfi->apply_fmt(vfi, &vafp); 
    297364        if (status != PJ_SUCCESS) 
Note: See TracChangeset for help on using the changeset viewer.