Ignore:
Timestamp:
Mar 25, 2011 8:38:26 AM (11 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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.