Ignore:
Timestamp:
Jul 13, 2011 8:51:10 AM (13 years ago)
Author:
nanang
Message:

Re #1263:

  • Renamed API pjsua_call_set_vid_out() with pjsua_call_set_vid_strm().
  • Implemented initial version of the function, features covered:
    • add, remove video media stream during the call
    • change which device to use during the call
    • start/stop video stream transmission
Location:
pjproject/branches/projects/2.0-dev
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjsip-apps/src/pjsua/pjsua_app.c

    r3632 r3634  
    14521452            cur_acc->vid_in_auto_show = PJ_TRUE; 
    14531453            cur_acc->vid_out_auto_transmit = PJ_TRUE; 
    1454             PJ_TODO(implement_pjsua_option_for_vid_auto_show_transmit); 
     1454            PJ_TODO(implement_pjsua_option_for_vid_auto_show_and_transmit); 
    14551455            break; 
    14561456        case OPT_EXTRA_AUDIO: 
     
    33163316    puts("| vid call rx on|off        Enable/disable incoming video for current call    |"); 
    33173317    puts("| vid call tx on|off        Enable/disable video tx for current call          |"); 
     3318    puts("| vid call add              Add video stream for current call                 |"); 
     3319    puts("| vid call remove [idx]     Remove video stream #idx for current call         |"); 
    33183320    puts("| vid dev list              List all video devices                            |"); 
    33193321    puts("| vid dev refresh           Refresh video device list                         |"); 
     
    37543756        vid_show_help(); 
    37553757    } else if (strcmp(argv[1], "call")==0) { 
     3758        pjsua_call_vid_strm_op_param param; 
    37563759        pj_bool_t tx = (strcmp(argv[2], "tx") == 0); 
    3757         pj_bool_t on = (strcmp(argv[3], "on") == 0); 
    3758  
     3760        if (tx) { 
     3761            pj_bool_t on = (strcmp(argv[3], "on") == 0); 
     3762        } 
     3763 
     3764        if (strcmp(argv[2], "add")==0) { 
     3765            pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_ADD, NULL); 
     3766        } 
     3767        if (strcmp(argv[2], "remove")==0) { 
     3768            param.med_idx = argc >= 4? atoi(argv[3]) : -1; 
     3769            pjsua_call_set_vid_strm(current_call, PJSUA_CALL_VID_STRM_REMOVE, &param); 
     3770        } 
    37593771        PJ_TODO(vid_enable_disable_video_on_call); 
    37603772        PJ_LOG(1,(THIS_FILE, "Not implemented")); 
  • pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua.h

    r3632 r3634  
    368368 
    369369} pjsua_state; 
     370 
     371 
     372/** 
     373 * This enumeration represents video stream operation on a call. 
     374 * See also #pjsua_call_vid_strm_op_param for further info. 
     375 */ 
     376typedef enum pjsua_call_vid_strm_op 
     377{ 
     378    /** 
     379     * Add a new video stream. 
     380     */ 
     381    PJSUA_CALL_VID_STRM_ADD, 
     382 
     383    /** 
     384     * Remove an existing video stream. 
     385     */ 
     386    PJSUA_CALL_VID_STRM_REMOVE, 
     387 
     388    /** 
     389     * Modify an existing video stream, such as changing the capture device. 
     390     */ 
     391    PJSUA_CALL_VID_STRM_MODIFY, 
     392 
     393    /** 
     394     * Start transmitting video stream. 
     395     */ 
     396    PJSUA_CALL_VID_STRM_START_TRANSMIT, 
     397 
     398    /** 
     399     * Stop transmitting video stream. 
     400     */ 
     401    PJSUA_CALL_VID_STRM_STOP_TRANSMIT, 
     402 
     403} pjsua_call_vid_strm_op; 
     404 
     405 
     406/** 
     407 * Parameters for video stream operation on a call. 
     408 */ 
     409typedef struct pjsua_call_vid_strm_op_param 
     410{ 
     411    /** 
     412     * Specify the media stream index. This can be set to -1 to denote 
     413     * the default video stream in the call, which is the first active 
     414     * video stream or any first video stream if none is active. 
     415     * 
     416     * This field is valid for all video stream operations, except 
     417     * PJSUA_CALL_VID_STRM_ADD. 
     418     */ 
     419    int med_idx; 
     420  
     421    /** 
     422     * Specify the video capture device ID. This can be set to 
     423     * PJMEDIA_VID_DEFAULT_CAPTURE_DEV to specify the default capture 
     424     * device as configured in the account. 
     425     * 
     426     * This field is valid for the following video stream operations: 
     427     * PJSUA_CALL_VID_STRM_ADD, PJSUA_CALL_VID_STRM_MODIFY, and 
     428     * PJSUA_CALL_VID_STRM_START_TRANSMIT. 
     429     */ 
     430    pjmedia_vid_dev_index cap_dev; 
     431 
     432} pjsua_call_vid_strm_op_param; 
    370433 
    371434 
     
    36813744PJ_DECL(int) pjsua_call_get_vid_stream_idx(pjsua_call_id call_id); 
    36823745 
    3683 /** 
    3684  * Start, stop, and/or manipulate video transmission for the specified 
    3685  * call. This would trigger a re-INVITE or UPDATE to be sent for the 
    3686  * call. This function may add, remove, or modify existing video media 
    3687  * stream, depending on the media index specified (the \a med_idx argument). 
    3688  * 
    3689  * To add a new or edit existing video stream (for transmission), specify 
    3690  * a valid video capture device ID or PJMEDIA_VID_DEFAULT_CAPTURE_DEV in 
    3691  * the \a cap_dev argument. If \a med_idx is set to default stream (-1), 
    3692  * then the function will modify existing video stream if one exists, or 
    3693  * add a new one if it doesn't. If \a med_idx is set to a specific stream 
    3694  * index, the function will modify that video stream. Otherwise if \a med_idx 
    3695  * is set to value larger than the current media count, a new video stream 
    3696  * will be added to the call. 
    3697  * 
    3698  * To remove an existing video stream, specify PJMEDIA_VID_INVALID_DEV in 
    3699  * \a cap_dev argument. If \a med_idx is set to default stream (-1), this 
    3700  * will remove the default/first video stream in the call, otherwise 
    3701  * application can put a specific value to request removal of that particular 
    3702  * video stream. 
     3746 
     3747/** 
     3748 * Add, remove, modify, and/or manipulate video media stream for the 
     3749 * specified call. This may trigger a re-INVITE or UPDATE to be sent 
     3750 * for the call. 
    37033751 * 
    37043752 * @param call_id       Call identification. 
    3705  * @param med_idx       The media stream index. Currently the value MUST 
    3706  *                      be -1 to denote the default video stream in the 
    3707  *                      call. 
    3708  * @param cap_dev       To add or modify existing video media stream, 
    3709  *                      specify PJMEDIA_VID_DEFAULT_CAPTURE_DEV to use 
    3710  *                      the default capture device as configured in the 
    3711  *                      account, or specify a specific capture device ID. 
    3712  *                      To disable an existing video stream, specify 
    3713  *                      PJMEDIA_VID_INVALID_DEV for this parameter. 
     3753 * @param op            The video stream operation to be performed, 
     3754 *                      possible values are #pjsua_call_vid_strm_op. 
     3755 * @param param         The parameters for the video stream operation. 
    37143756 * 
    37153757 * @return              PJ_SUCCESS on success or the appropriate error. 
    37163758 */ 
    3717 PJ_DECL(pj_status_t) pjsua_call_set_vid_out(pjsua_call_id call_id, 
    3718                                             int med_idx, 
    3719                                             pjmedia_vid_dev_index cap_dev); 
     3759PJ_DECL(pj_status_t) pjsua_call_set_vid_strm ( 
     3760                                pjsua_call_id call_id, 
     3761                                pjsua_call_vid_strm_op op, 
     3762                                const pjsua_call_vid_strm_op_param *param); 
     3763 
    37203764 
    37213765/** 
  • pjproject/branches/projects/2.0-dev/pjsip/include/pjsua-lib/pjsua_internal.h

    r3632 r3634  
    7575            pjsua_vid_win_id     cap_win_id;/**< The video capture window   */ 
    7676            pjsua_vid_win_id     rdr_win_id;/**< The video render window    */ 
     77            pjmedia_vid_dev_index cap_dev;  /**< The video capture device   */ 
     78            pjmedia_vid_dev_index rdr_dev;  /**< The video-in render device */ 
    7779        } v; 
    7880 
  • pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_media.c

    r3632 r3634  
    13141314 
    13151315/* Initialize the media line */ 
    1316 static pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, 
    1317                                          pjmedia_type type, 
    1318                                         const pjsua_transport_config *tcfg, 
    1319                                         int security_level, 
    1320                                         int *sip_err_code) 
     1316pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, 
     1317                                  pjmedia_type type, 
     1318                                  const pjsua_transport_config *tcfg, 
     1319                                  int security_level, 
     1320                                  int *sip_err_code) 
    13211321{ 
    13221322    pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 
     
    13431343         
    13441344        call_med->tp_st = PJSUA_MED_TP_IDLE; 
     1345 
     1346        /* While in initial call, set default video devices */ 
     1347        if (type == PJMEDIA_TYPE_VIDEO) { 
     1348            call_med->strm.v.rdr_dev = acc->cfg.vid_rend_dev; 
     1349            call_med->strm.v.cap_dev = acc->cfg.vid_cap_dev; 
     1350            if (call_med->strm.v.rdr_dev == PJMEDIA_VID_DEFAULT_RENDER_DEV) { 
     1351                pjmedia_vid_dev_info info; 
     1352                pjmedia_vid_dev_get_info(call_med->strm.v.rdr_dev, &info); 
     1353                call_med->strm.v.rdr_dev = info.id; 
     1354            } 
     1355            if (call_med->strm.v.cap_dev == PJMEDIA_VID_DEFAULT_CAPTURE_DEV) { 
     1356                pjmedia_vid_dev_info info; 
     1357                pjmedia_vid_dev_get_info(call_med->strm.v.cap_dev, &info); 
     1358                call_med->strm.v.cap_dev = info.id; 
     1359            } 
     1360        } 
    13451361    } else if (call_med->tp_st == PJSUA_MED_TP_DISABLED) { 
    13461362        /* Media is being reenabled. */ 
  • pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_vid.c

    r3629 r3634  
    608608 
    609609        /* Setup decoding direction */ 
    610         if (si->dir & PJMEDIA_DIR_DECODING) { 
     610        if (si->dir & PJMEDIA_DIR_DECODING) 
     611        { 
    611612            pjsua_vid_win_id wid; 
    612613            pjsua_vid_win *w; 
     
    621622            status = create_vid_win(PJSUA_WND_TYPE_STREAM, 
    622623                                    &media_port->info.fmt, 
    623                                     acc->cfg.vid_rend_dev, 
     624                                    call_med->strm.v.rdr_dev, 
     625                                    //acc->cfg.vid_rend_dev, 
    624626                                    PJSUA_INVALID_ID, 
    625627                                    acc->cfg.vid_in_auto_show, 
     
    647649 
    648650        /* Setup encoding direction */ 
    649         if (si->dir & PJMEDIA_DIR_ENCODING && !call->local_hold && 
    650             acc->cfg.vid_out_auto_transmit) 
     651        if (si->dir & PJMEDIA_DIR_ENCODING && !call->local_hold) 
    651652        { 
    652653            pjsua_vid_win *w; 
     
    662663            status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
    663664                                    &media_port->info.fmt, 
    664                                     acc->cfg.vid_rend_dev, 
    665                                     acc->cfg.vid_cap_dev, 
     665                                    call_med->strm.v.rdr_dev, 
     666                                    call_med->strm.v.cap_dev, 
     667                                    //acc->cfg.vid_rend_dev, 
     668                                    //acc->cfg.vid_cap_dev, 
    666669                                    PJ_FALSE, 
    667670                                    &wid); 
     
    737740    } 
    738741 
     742    if (acc->cfg.vid_out_auto_transmit) { 
     743        status = pjmedia_vid_stream_pause(call_med->strm.v.stream, 
     744                                          PJMEDIA_DIR_ENCODING); 
     745        if (status != PJ_SUCCESS) 
     746            return status; 
     747    } 
     748 
    739749    return PJ_SUCCESS; 
    740750} 
     
    10071017 
    10081018 
     1019static void call_get_vid_strm_info(pjsua_call *call, 
     1020                                   int *first_active, 
     1021                                   int *first_inactive, 
     1022                                   unsigned *active_cnt, 
     1023                                   unsigned *cnt) 
     1024{ 
     1025    unsigned i, var_cnt = 0; 
     1026 
     1027    if (first_active && ++var_cnt) 
     1028        *first_active = -1; 
     1029    if (first_inactive && ++var_cnt) 
     1030        *first_inactive = -1; 
     1031    if (active_cnt && ++var_cnt) 
     1032        *active_cnt = 0; 
     1033    if (cnt && ++var_cnt) 
     1034        *cnt = 0; 
     1035 
     1036    for (i = 0; i < call->med_cnt && var_cnt; ++i) { 
     1037        if (call->media[i].type == PJMEDIA_TYPE_VIDEO) { 
     1038            if (call->media[i].dir != PJMEDIA_DIR_NONE) 
     1039            { 
     1040                if (first_active && *first_active == -1) { 
     1041                    *first_active = i; 
     1042                    --var_cnt; 
     1043                } 
     1044                if (active_cnt) 
     1045                    ++(*active_cnt); 
     1046            } else if (first_inactive && *first_inactive == -1) { 
     1047                *first_inactive = i; 
     1048                --var_cnt; 
     1049            } 
     1050            if (cnt) 
     1051                ++(*cnt); 
     1052        } 
     1053    } 
     1054} 
     1055 
     1056 
     1057/* Send SDP reoffer. */ 
     1058static pj_status_t call_reoffer_sdp(pjsua_call_id call_id, 
     1059                                    const pjmedia_sdp_session *sdp) 
     1060{ 
     1061    pjsua_call *call; 
     1062    pjsip_tx_data *tdata; 
     1063    pjsip_dialog *dlg; 
     1064    pj_status_t status; 
     1065 
     1066    status = acquire_call("call_reoffer_sdp()", call_id, &call, &dlg); 
     1067    if (status != PJ_SUCCESS) 
     1068        return status; 
     1069 
     1070    if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     1071        PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 
     1072        pjsip_dlg_dec_lock(dlg); 
     1073        return PJSIP_ESESSIONSTATE; 
     1074    } 
     1075 
     1076    /* Create re-INVITE with new offer */ 
     1077    status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
     1078    if (status != PJ_SUCCESS) { 
     1079        pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
     1080        pjsip_dlg_dec_lock(dlg); 
     1081        return status; 
     1082    } 
     1083 
     1084    /* Send the request */ 
     1085    status = pjsip_inv_send_msg( call->inv, tdata); 
     1086    if (status != PJ_SUCCESS) { 
     1087        pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
     1088        pjsip_dlg_dec_lock(dlg); 
     1089        return status; 
     1090    } 
     1091 
     1092    pjsip_dlg_dec_lock(dlg); 
     1093 
     1094    return PJ_SUCCESS; 
     1095} 
     1096 
     1097 
     1098pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, 
     1099                                  pjmedia_type type, 
     1100                                  const pjsua_transport_config *tcfg, 
     1101                                  int security_level, 
     1102                                  int *sip_err_code); 
     1103 
     1104 
     1105/* Add a new video stream into a call */ 
     1106static pj_status_t call_add_video(pjsua_call *call, 
     1107                                  pjmedia_vid_dev_index cap_dev) 
     1108{ 
     1109    pj_pool_t *pool = call->inv->pool_prov; 
     1110    pjsua_acc_config *acc_cfg = &pjsua_var.acc[call->acc_id].cfg; 
     1111    pjsua_call_media *call_med; 
     1112    pjmedia_sdp_session *sdp; 
     1113    pjmedia_sdp_media *sdp_m; 
     1114    pjmedia_transport_info tpinfo; 
     1115    pjmedia_vid_dev_info vinfo; 
     1116    unsigned active_cnt; 
     1117    pj_status_t status; 
     1118 
     1119    /* Verify media slot availability */ 
     1120    if (call->med_cnt == PJSUA_MAX_CALL_MEDIA) 
     1121        return PJ_ETOOMANY; 
     1122 
     1123    call_get_vid_strm_info(call, NULL, NULL, &active_cnt, NULL); 
     1124    if (active_cnt == acc_cfg->max_video_cnt) 
     1125        return PJ_ETOOMANY; 
     1126 
     1127    /* Verify the capture device */ 
     1128    status = pjmedia_vid_dev_get_info(cap_dev, &vinfo); 
     1129    if (status != PJ_SUCCESS) 
     1130        return status; 
     1131 
     1132    if (vinfo.dir != PJMEDIA_DIR_CAPTURE) 
     1133        return PJ_EINVAL; 
     1134 
     1135    cap_dev = vinfo.id; 
     1136 
     1137    /* Get active local SDP */ 
     1138    status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); 
     1139    if (status != PJ_SUCCESS) 
     1140        return status; 
     1141 
     1142    /* Initialize call media */ 
     1143    call_med = &call->media[call->med_cnt++]; 
     1144 
     1145    status = pjsua_call_media_init(call_med, PJMEDIA_TYPE_VIDEO, 
     1146                                   &acc_cfg->rtp_cfg, call->secure_level, 
     1147                                   NULL); 
     1148    if (status != PJ_SUCCESS) 
     1149        goto on_error; 
     1150 
     1151    /* Override default capture device setting */ 
     1152    call_med->strm.v.cap_dev = cap_dev; 
     1153 
     1154    /* Init transport media */ 
     1155    status = pjmedia_transport_media_create(call_med->tp, pool, 0, 
     1156                                            NULL, call_med->idx); 
     1157    if (status != PJ_SUCCESS) 
     1158        goto on_error; 
     1159 
     1160    call_med->tp_st = PJSUA_MED_TP_INIT; 
     1161 
     1162    /* Get transport address info */ 
     1163    pjmedia_transport_info_init(&tpinfo); 
     1164    pjmedia_transport_get_info(call_med->tp, &tpinfo); 
     1165 
     1166    /* Create SDP media line */ 
     1167    status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool, 
     1168                                            &tpinfo.sock_info, 0, &sdp_m); 
     1169    if (status != PJ_SUCCESS) 
     1170        goto on_error; 
     1171 
     1172    sdp->media[sdp->media_count++] = sdp_m; 
     1173 
     1174    /* Update SDP media line by media transport */ 
     1175    status = pjmedia_transport_encode_sdp(call_med->tp, pool, 
     1176                                          sdp, NULL, call_med->idx); 
     1177    if (status != PJ_SUCCESS) 
     1178        goto on_error; 
     1179 
     1180    status = call_reoffer_sdp(call->index, sdp); 
     1181    if (status != PJ_SUCCESS) 
     1182        goto on_error; 
     1183 
     1184    return PJ_SUCCESS; 
     1185 
     1186on_error: 
     1187    if (call_med->tp) { 
     1188        pjmedia_transport_close(call_med->tp); 
     1189        call_med->tp = call_med->tp_orig = NULL; 
     1190    } 
     1191 
     1192    return status; 
     1193} 
     1194 
     1195 
     1196/* Remove a video stream from a call */ 
     1197static pj_status_t call_remove_video(pjsua_call *call, 
     1198                                     int med_idx) 
     1199{ 
     1200    pjsua_call_media *call_med; 
     1201    pjmedia_sdp_session *sdp; 
     1202    pj_status_t status; 
     1203 
     1204    /* Verify and normalize media index */ 
     1205    if (med_idx == -1) { 
     1206        int first_active; 
     1207         
     1208        call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL); 
     1209        if (first_active == -1) 
     1210            return PJ_ENOTFOUND; 
     1211 
     1212        med_idx = first_active; 
     1213    } 
     1214 
     1215    call_med = &call->media[med_idx]; 
     1216 
     1217    /* Verify if the stream media type is video */ 
     1218    if (call_med->type != PJMEDIA_TYPE_VIDEO) 
     1219        return PJ_EINVAL; 
     1220 
     1221    /* Verify if the stream already disabled */ 
     1222    if (call_med->dir != PJMEDIA_DIR_NONE) 
     1223        return PJ_SUCCESS; 
     1224 
     1225    /* Mark media transport to disabled */ 
     1226    // Don't close this here, as SDP negotiation has not been 
     1227    // done and stream may be still active. 
     1228    call_med->tp_st = PJSUA_MED_TP_DISABLED; 
     1229 
     1230    /* Get active local SDP */ 
     1231    status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); 
     1232    if (status != PJ_SUCCESS) 
     1233        return status; 
     1234 
     1235    pj_assert(med_idx < (int)sdp->media_count); 
     1236    sdp->media[med_idx]->desc.port = 0; 
     1237 
     1238    status = call_reoffer_sdp(call->index, sdp); 
     1239    if (status != PJ_SUCCESS) 
     1240        return status; 
     1241 
     1242    return PJ_SUCCESS; 
     1243} 
     1244 
     1245 
     1246/* Modify a video stream in a call */ 
     1247static pj_status_t call_modify_video(pjsua_call *call, 
     1248                                     int med_idx, 
     1249                                     pjmedia_vid_dev_index cap_dev) 
     1250{ 
     1251    pjsua_call_media *call_med; 
     1252    pjmedia_vid_dev_info info; 
     1253    pjsua_vid_win *w, *new_w = NULL; 
     1254    pjsua_vid_win_id wid, new_wid; 
     1255    pjmedia_port *media_port; 
     1256    pj_status_t status; 
     1257 
     1258    /* Verify and normalize media index */ 
     1259    if (med_idx == -1) { 
     1260        int first_active; 
     1261         
     1262        call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL); 
     1263        if (first_active == -1) 
     1264            return PJ_ENOTFOUND; 
     1265 
     1266        med_idx = first_active; 
     1267    } 
     1268 
     1269    call_med = &call->media[med_idx]; 
     1270 
     1271    /* Verify if the stream media type is video */ 
     1272    if (call_med->type != PJMEDIA_TYPE_VIDEO) 
     1273        return PJ_EINVAL; 
     1274 
     1275    /* Verify the capture device */ 
     1276    status = pjmedia_vid_dev_get_info(cap_dev, &info); 
     1277    if (status != PJ_SUCCESS) 
     1278        return status; 
     1279 
     1280    if (info.dir != PJMEDIA_DIR_CAPTURE) 
     1281        return PJ_EINVAL; 
     1282 
     1283    cap_dev = info.id; 
     1284 
     1285    /* The specified capture device is being used already */ 
     1286    if (call_med->strm.v.cap_dev == cap_dev) 
     1287        return PJ_SUCCESS; 
     1288 
     1289    /* == Apply the new capture device == */ 
     1290 
     1291    wid = call_med->strm.v.cap_win_id; 
     1292    w = &pjsua_var.win[wid]; 
     1293    pj_assert(w->type == PJSUA_WND_TYPE_PREVIEW && w->vp_cap); 
     1294 
     1295    status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 
     1296                                         PJMEDIA_DIR_ENCODING, &media_port); 
     1297    if (status != PJ_SUCCESS) 
     1298        return status; 
     1299     
     1300    /* = Detach stream port from the old capture device = */ 
     1301    status = pjmedia_vid_port_disconnect(w->vp_cap); 
     1302    if (status != PJ_SUCCESS) 
     1303        return status; 
     1304 
     1305    status = pjmedia_vid_tee_remove_dst_port(w->tee, media_port); 
     1306    if (status != PJ_SUCCESS) { 
     1307        /* Connect back the old capturer */ 
     1308        pjmedia_vid_port_connect(w->vp_cap, media_port, PJ_FALSE); 
     1309        return status; 
     1310    } 
     1311 
     1312    /* = Attach stream port to the new capture device = */ 
     1313 
     1314    /* Create preview video window */ 
     1315    status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
     1316                            &media_port->info.fmt, 
     1317                            call_med->strm.v.rdr_dev, 
     1318                            cap_dev, 
     1319                            PJ_FALSE, 
     1320                            &new_wid); 
     1321    if (status != PJ_SUCCESS) 
     1322        goto on_error; 
     1323 
     1324    inc_vid_win(new_wid); 
     1325    new_w = &pjsua_var.win[new_wid]; 
     1326     
     1327    /* Connect stream to capturer (via video window tee) */ 
     1328    status = pjmedia_vid_tee_add_dst_port2(new_w->tee, 0, media_port); 
     1329    if (status != PJ_SUCCESS) 
     1330        goto on_error; 
     1331 
     1332    /* Connect capturer to tee */ 
     1333    status = pjmedia_vid_port_connect(new_w->vp_cap, new_w->tee, PJ_FALSE); 
     1334    if (status != PJ_SUCCESS) 
     1335        return status; 
     1336 
     1337    /* Start renderer */ 
     1338    status = pjmedia_vid_port_start(new_w->vp_rend); 
     1339    if (status != PJ_SUCCESS) 
     1340        goto on_error; 
     1341 
     1342    /* Start capturer */ 
     1343    status = pjmedia_vid_port_start(new_w->vp_cap); 
     1344    if (status != PJ_SUCCESS) 
     1345        goto on_error; 
     1346 
     1347    /* Finally */ 
     1348    call_med->strm.v.cap_dev = cap_dev; 
     1349    call_med->strm.v.cap_win_id = new_wid; 
     1350    dec_vid_win(wid); 
     1351 
     1352    return PJ_SUCCESS; 
     1353 
     1354on_error: 
     1355    if (new_w) { 
     1356        /* Disconnect media port from the new capturer */ 
     1357        pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port); 
     1358        /* Release the new capturer */ 
     1359        dec_vid_win(new_wid); 
     1360    } 
     1361 
     1362    /* Revert back to the old capturer */ 
     1363    status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port); 
     1364    if (status != PJ_SUCCESS) 
     1365        return status; 
     1366 
     1367    status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 
     1368    if (status != PJ_SUCCESS) 
     1369        return status; 
     1370 
     1371    return status; 
     1372} 
     1373 
     1374 
     1375/* Start transmitting video stream in a call */ 
     1376static pj_status_t call_start_tx_video(pjsua_call *call, 
     1377                                       int med_idx, 
     1378                                       pjmedia_vid_dev_index cap_dev) 
     1379{ 
     1380    pjsua_call_media *call_med; 
     1381    pj_status_t status; 
     1382 
     1383    /* Verify and normalize media index */ 
     1384    if (med_idx == -1) { 
     1385        int first_active; 
     1386         
     1387        call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL); 
     1388        if (first_active == -1) 
     1389            return PJ_ENOTFOUND; 
     1390 
     1391        med_idx = first_active; 
     1392    } 
     1393 
     1394    call_med = &call->media[med_idx]; 
     1395 
     1396    /* Verify if the stream is transmitting video */ 
     1397    if (call_med->type != PJMEDIA_TYPE_VIDEO ||  
     1398        (call_med->dir & PJMEDIA_DIR_ENCODING) == 0) 
     1399    { 
     1400        return PJ_EINVAL; 
     1401    } 
     1402 
     1403    /* Apply the new capture device */ 
     1404    status = call_modify_video(call, med_idx, cap_dev); 
     1405    if (status != PJ_SUCCESS) 
     1406        return status; 
     1407 
     1408    /* Start stream in encoding direction */ 
     1409    status = pjmedia_vid_stream_resume(call_med->strm.v.stream, 
     1410                                       PJMEDIA_DIR_ENCODING); 
     1411    if (status != PJ_SUCCESS) 
     1412        return status; 
     1413 
     1414    return PJ_SUCCESS; 
     1415} 
     1416 
     1417 
     1418/* Stop transmitting video stream in a call */ 
     1419static pj_status_t call_stop_tx_video(pjsua_call *call, 
     1420                                      int med_idx) 
     1421{ 
     1422    pjsua_call_media *call_med; 
     1423    pj_status_t status; 
     1424 
     1425    /* Verify and normalize media index */ 
     1426    if (med_idx == -1) { 
     1427        int first_active; 
     1428         
     1429        call_get_vid_strm_info(call, &first_active, NULL, NULL, NULL); 
     1430        if (first_active == -1) 
     1431            return PJ_ENOTFOUND; 
     1432 
     1433        med_idx = first_active; 
     1434    } 
     1435 
     1436    call_med = &call->media[med_idx]; 
     1437 
     1438    /* Verify if the stream is transmitting video */ 
     1439    if (call_med->type != PJMEDIA_TYPE_VIDEO ||  
     1440        (call_med->dir & PJMEDIA_DIR_ENCODING) == 0) 
     1441    { 
     1442        return PJ_EINVAL; 
     1443    } 
     1444 
     1445    /* Pause stream in encoding direction */ 
     1446    status = pjmedia_vid_stream_pause( call_med->strm.v.stream, 
     1447                                       PJMEDIA_DIR_ENCODING); 
     1448    if (status != PJ_SUCCESS) 
     1449        return status; 
     1450 
     1451    return PJ_SUCCESS; 
     1452} 
     1453 
     1454 
     1455/* 
     1456 * Start, stop, and/or manipulate video transmission for the specified call. 
     1457 */ 
     1458PJ_DEF(pj_status_t) pjsua_call_set_vid_strm ( 
     1459                                pjsua_call_id call_id, 
     1460                                pjsua_call_vid_strm_op op, 
     1461                                const pjsua_call_vid_strm_op_param *param) 
     1462{ 
     1463    pjsua_call *call; 
     1464    pjsua_call_vid_strm_op_param param_; 
     1465    pj_status_t status; 
     1466 
     1467    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1468                     PJ_EINVAL); 
     1469 
     1470    PJSUA_LOCK(); 
     1471 
     1472    call = &pjsua_var.calls[call_id]; 
     1473 
     1474    if (param) { 
     1475        param_ = *param; 
     1476    } else { 
     1477        param_.med_idx = -1; 
     1478        param_.cap_dev = PJMEDIA_VID_DEFAULT_CAPTURE_DEV; 
     1479    } 
     1480 
     1481    /* Get real capture ID, if set to PJMEDIA_VID_DEFAULT_CAPTURE_DEV */ 
     1482    if (param_.cap_dev == PJMEDIA_VID_DEFAULT_CAPTURE_DEV) { 
     1483        pjmedia_vid_dev_info info; 
     1484        pjmedia_vid_dev_get_info(param_.cap_dev, &info); 
     1485        param_.cap_dev = info.id; 
     1486    } 
     1487 
     1488    switch (op) { 
     1489    case PJSUA_CALL_VID_STRM_ADD: 
     1490        status = call_add_video(call, param_.cap_dev); 
     1491        break; 
     1492    case PJSUA_CALL_VID_STRM_REMOVE: 
     1493        status = call_remove_video(call, param_.med_idx); 
     1494        break; 
     1495    case PJSUA_CALL_VID_STRM_MODIFY: 
     1496        status = call_modify_video(call, param_.med_idx, param_.cap_dev); 
     1497        break; 
     1498    case PJSUA_CALL_VID_STRM_START_TRANSMIT: 
     1499        status = call_start_tx_video(call, param_.med_idx, param_.cap_dev); 
     1500        break; 
     1501    case PJSUA_CALL_VID_STRM_STOP_TRANSMIT: 
     1502        status = call_stop_tx_video(call, param_.med_idx); 
     1503        break; 
     1504    default: 
     1505        status = PJ_EINVALIDOP; 
     1506        break; 
     1507    } 
     1508 
     1509    PJSUA_UNLOCK(); 
     1510 
     1511    return status; 
     1512} 
     1513 
    10091514 
    10101515#endif /* PJSUA_HAS_VIDEO */ 
Note: See TracChangeset for help on using the changeset viewer.