Changeset 3756 for pjproject


Ignore:
Timestamp:
Sep 19, 2011 8:26:35 AM (13 years ago)
Author:
bennylp
Message:

Implemented native video preview support. This closes #1340

Location:
pjproject/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev.h

    r3715 r3756  
    150150 
    151151    /** 
    152      * The application can provide a window for the renderer to 
    153      * display the video. 
     152     * Support for returning the native window handle of the video window. 
     153     * For renderer, this means the window handle of the renderer window, 
     154     * while for capture, this means the window handle of the native preview, 
     155     * only if the device supports  PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW 
     156     * capability. 
     157     * 
     158     * The value of this capability is pointer to pjmedia_vid_dev_hwnd 
     159     * structure. 
    154160     */ 
    155161    PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW = 4, 
     
    176182 
    177183    /** 
    178      * End of capability 
     184     * Support for native preview capability in capture devices. Value is 
     185     * pj_bool_t. With native preview, capture device can be instructed to 
     186     * show or hide a preview window showing video directly from the camera 
     187     * by setting this capability to PJ_TRUE or PJ_FALSE. Once the preview 
     188     * is started, application may use PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW 
     189     * capability to query the vidow window. 
     190     * 
     191     * The value of this capability is a pj_bool_t containing boolean 
     192     * PJ_TRUE or PJ_FALSE. 
     193     */ 
     194    PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW = 64, 
     195 
     196    /** 
     197     * End of standard capability 
    179198     */ 
    180199    PJMEDIA_VID_DEV_CAP_MAX = 16384 
     
    338357    pj_bool_t window_hide; 
    339358 
     359    /** 
     360     * Enable built-in preview. This setting is optional and is only used 
     361     * if PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW capability is supported and 
     362     * set in the flags. 
     363     */ 
     364    pj_bool_t native_preview; 
     365 
    340366} pjmedia_vid_dev_param; 
    341367 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c

    r3715 r3756  
    4141    DEFINE_CAP("format",        "Video format"), 
    4242    DEFINE_CAP("scale",         "Input dimension"), 
    43     DEFINE_CAP("window",        "Renderer window"), 
     43    DEFINE_CAP("window",        "Window handle"), 
    4444    DEFINE_CAP("resize",        "Renderer resize"), 
    4545    DEFINE_CAP("position",      "Renderer position"), 
    4646    DEFINE_CAP("hide",          "Renderer hide"), 
     47    DEFINE_CAP("preview",       "Input preview"), 
    4748}; 
    4849 
     
    176177        FIELD_INFO(window_hide); 
    177178        break; 
     179    case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW: 
     180        FIELD_INFO(native_preview); 
     181        break; 
    178182    default: 
    179183        return PJMEDIA_EVID_INVCAP; 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_tee.c

    r3725 r3756  
    3131#define TEE_PORT_SIGN   PJMEDIA_SIG_PORT_VID_TEE 
    3232 
     33#define THIS_FILE       "vid_tee.c" 
    3334 
    3435typedef struct vid_tee_dst_port 
     
    317318                                               frame, &frame_); 
    318319            if (status != PJ_SUCCESS) { 
    319                 PJ_LOG(3, ("", "Failed to convert frame for destination" 
    320                                "port %d (%.*s)", i, 
     320                PJ_LOG(3, (THIS_FILE, 
     321                               "Failed to convert frame for destination" 
     322                               " port %d (%.*s)", i, 
    321323                               tee->dst_ports[i].dst->info.name.slen, 
    322324                               tee->dst_ports[i].dst->info.name.ptr)); 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3724 r3756  
    46924692     */ 
    46934693    int                 snd_auto_close_time; 
     4694 
     4695    /** 
     4696     * Specify whether built-in/native preview should be used if available. 
     4697     * In some systems, video input devices have built-in capability to show 
     4698     * preview window of the device. Using this built-in preview is preferable 
     4699     * as it consumes less CPU power. If built-in preview is not available, 
     4700     * the library will perform software rendering of the input. If this 
     4701     * field is set to PJ_FALSE, software preview will always be used. 
     4702     * 
     4703     * Default: PJ_TRUE 
     4704     */ 
     4705    pj_bool_t vid_preview_enable_native; 
    46944706}; 
    46954707 
     
    54375449    /** 
    54385450     * Device ID for the video renderer to be used for rendering the 
    5439      * capture stream for preview. 
     5451     * capture stream for preview. This parameter is ignored if native 
     5452     * preview is being used. 
    54405453     * 
    54415454     * Default: PJMEDIA_VID_DEFAULT_RENDER_DEV 
     
    54595472 */ 
    54605473PJ_DECL(void) pjsua_vid_preview_param_default(pjsua_vid_preview_param *p); 
     5474 
     5475/** 
     5476 * Determine if the specified video input device has built-in native 
     5477 * preview capability. This is a convenience function that is equal to 
     5478 * querying device's capability for PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW 
     5479 * capability. 
     5480 * 
     5481 * @param id            The capture device ID. 
     5482 * 
     5483 * @return              PJ_TRUE if it has. 
     5484 */ 
     5485PJ_DECL(pj_bool_t) pjsua_vid_preview_has_native(pjmedia_vid_dev_index id); 
    54615486 
    54625487/** 
     
    55045529{ 
    55055530    /** 
     5531     * Flag to indicate whether this window is a native window, 
     5532     * such as created by built-in preview device. If this field is 
     5533     * PJ_TRUE, only the native window handle field of this 
     5534     * structure is valid. 
     5535     */ 
     5536    pj_bool_t is_native; 
     5537 
     5538    /** 
     5539     * Native window handle. 
     5540     */ 
     5541    pjmedia_vid_dev_hwnd hwnd; 
     5542 
     5543    /** 
    55065544     * Renderer device ID. 
    55075545     */ 
    55085546    pjmedia_vid_dev_index rdr_dev; 
    5509  
    5510     /** 
    5511      * Native window handle. 
    5512      */ 
    5513     pjmedia_vid_dev_hwnd hwnd; 
    55145547 
    55155548    /** 
     
    55575590 
    55585591/** 
    5559  * Show or hide window. 
     5592 * Show or hide window. This operation is not valid for native windows 
     5593 * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API 
     5594 * must be used instead. 
    55605595 * 
    55615596 * @param wid           The video window ID. 
     
    55695604 
    55705605/** 
    5571  * Set video window position. 
     5606 * Set video window position. This operation is not valid for native windows 
     5607 * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API 
     5608 * must be used instead. 
    55725609 * 
    55735610 * @param wid           The video window ID. 
     
    55805617 
    55815618/** 
    5582  * Resize window. 
     5619 * Resize window. This operation is not valid for native windows 
     5620 * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API 
     5621 * must be used instead. 
    55835622 * 
    55845623 * @param wid           The video window ID. 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r3666 r3756  
    308308} pjsua_stun_resolve; 
    309309 
     310/* See also pjsua_vid_win_type_name() */ 
    310311typedef enum pjsua_vid_win_type 
    311312{ 
     
    323324    pjmedia_vid_port            *vp_rend;       /**< Renderer vidport   */ 
    324325    pjmedia_port                *tee;           /**< Video tee          */ 
    325     pjmedia_vid_dev_index        preview_cap_id;/* Capture dev id       */ 
     326    pjmedia_vid_dev_index        preview_cap_id;/**< Capture dev id     */ 
     327    pj_bool_t                    is_native;     /**< Preview is by dev  */ 
    326328} pjsua_vid_win; 
    327329 
     
    676678pj_status_t pjsua_vid_subsys_destroy(void); 
    677679 
    678 PJ_INLINE(void) pjsua_vid_win_reset(pjsua_vid_win_id wid) 
    679 { 
    680680#if PJSUA_HAS_VIDEO 
    681     pjsua_vid_win *w = &pjsua_var.win[wid]; 
    682     pj_pool_t *pool = w->pool; 
    683  
    684     pj_bzero(w, sizeof(*w)); 
    685     if (pool) pj_pool_reset(pool); 
    686     w->ref_cnt = 0; 
    687     w->pool = pool; 
    688     w->preview_cap_id = PJMEDIA_VID_INVALID_DEV; 
     681PJ_DECL(void) pjsua_vid_win_reset(pjsua_vid_win_id wid); 
    689682#else 
    690     PJ_UNUSED_ARG(wid); 
     683#  define pjsua_vid_win_reset(wid) 
    691684#endif 
    692 } 
    693685 
    694686 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3753 r3756  
    229229 
    230230    cfg->turn_conn_type = PJ_TURN_TP_UDP; 
     231    cfg->vid_preview_enable_native = PJ_TRUE; 
    231232} 
    232233 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r3753 r3756  
    2424#if PJSUA_HAS_VIDEO 
    2525 
    26 #define ENABLE_EVENT        0 
    27 #define VID_TEE_MAX_PORT    (PJSUA_MAX_CALLS + 1) 
     26#define ENABLE_EVENT            0 
     27#define VID_TEE_MAX_PORT        (PJSUA_MAX_CALLS + 1) 
     28 
     29#define PJSUA_SHOW_WINDOW       1 
     30#define PJSUA_HIDE_WINDOW       0 
     31 
    2832 
    2933static void free_vid_win(pjsua_vid_win_id wid); 
     
    125129} 
    126130 
     131PJ_DEF(const char*) pjsua_vid_win_type_name(pjsua_vid_win_type wt) 
     132{ 
     133    const char *win_type_names[] = { 
     134         "none", 
     135         "preview", 
     136         "stream" 
     137    }; 
     138 
     139    return (wt < PJ_ARRAY_SIZE(win_type_names)) ? win_type_names[wt] : "??"; 
     140} 
     141 
    127142PJ_DEF(void) 
    128143pjsua_call_vid_strm_op_param_default(pjsua_call_vid_strm_op_param *param) 
     
    338353} 
    339354 
     355PJ_DEF(void) pjsua_vid_win_reset(pjsua_vid_win_id wid) 
     356{ 
     357    pjsua_vid_win *w = &pjsua_var.win[wid]; 
     358    pj_pool_t *pool = w->pool; 
     359 
     360    pj_bzero(w, sizeof(*w)); 
     361    if (pool) pj_pool_reset(pool); 
     362    w->ref_cnt = 0; 
     363    w->pool = pool; 
     364    w->preview_cap_id = PJMEDIA_VID_INVALID_DEV; 
     365} 
    340366 
    341367/* Allocate and initialize pjsua video window: 
     
    351377                                  pjsua_vid_win_id *id) 
    352378{ 
     379    pj_bool_t enable_native_preview; 
    353380    pjsua_vid_win_id wid = PJSUA_INVALID_ID; 
    354381    pjsua_vid_win *w = NULL; 
     
    358385    unsigned i; 
    359386 
    360     PJ_LOG(4,(THIS_FILE, "Creating window, type=%d, cap_dev=%d, rend_dev=%d", 
    361               type, cap_id, rend_id)); 
     387    enable_native_preview = pjsua_var.media_cfg.vid_preview_enable_native; 
     388 
     389    PJ_LOG(4,(THIS_FILE, 
     390              "Creating video window: type=%s, cap_id=%d, rend_id=%d", 
     391              pjsua_vid_win_type_name(type), cap_id, rend_id)); 
    362392    pj_log_push_indent(); 
    363393 
     
    368398            /* Yes, it exists */ 
    369399            /* Show/hide window */ 
    370             pjmedia_vid_dev_stream *rdr; 
     400            pjmedia_vid_dev_stream *strm; 
    371401            pj_bool_t hide = !show; 
    372402 
    373             rdr = pjmedia_vid_port_get_stream(pjsua_var.win[wid].vp_rend); 
    374             pj_assert(rdr); 
     403            w = &pjsua_var.win[wid]; 
     404 
     405            PJ_LOG(4,(THIS_FILE, 
     406                      "Window already exists for cap_dev=%d, returning wid=%d", 
     407                      cap_id, wid)); 
     408 
     409 
     410            if (w->is_native) { 
     411                strm = pjmedia_vid_port_get_stream(w->vp_cap); 
     412            } else { 
     413                strm = pjmedia_vid_port_get_stream(w->vp_rend); 
     414            } 
     415 
     416            pj_assert(strm); 
    375417            status = pjmedia_vid_dev_stream_set_cap( 
    376                                     rdr, PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, 
     418                                    strm, PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, 
    377419                                    &hide); 
    378420 
     
    403445 
    404446    if (w->type == PJSUA_WND_TYPE_PREVIEW) { 
     447        pjmedia_vid_dev_info vdi; 
     448 
     449        /* 
     450         * Determine if the device supports native preview. 
     451         */ 
     452        status = pjmedia_vid_dev_get_info(cap_id, &vdi); 
     453        if (status != PJ_SUCCESS) 
     454            goto on_error; 
     455 
     456        if (enable_native_preview && 
     457             (vdi.caps & PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW)) 
     458        { 
     459            /* Device supports native preview! */ 
     460            w->is_native = PJ_TRUE; 
     461        } 
     462 
    405463        status = pjmedia_vid_dev_default_param(w->pool, cap_id, 
    406464                                               &vp_param.vidparam); 
    407465        if (status != PJ_SUCCESS) 
    408466            goto on_error; 
     467 
     468        if (w->is_native) { 
     469            vp_param.vidparam.flags |= PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE; 
     470            vp_param.vidparam.window_hide = !show; 
     471        } 
    409472 
    410473        /* Normalize capture ID, in case it was set to 
     
    435498        if (status != PJ_SUCCESS) 
    436499            goto on_error; 
    437     } 
    438  
    439     /* Create renderer video port */ 
    440     status = pjmedia_vid_dev_default_param(w->pool, rend_id, 
    441                                            &vp_param.vidparam); 
    442     if (status != PJ_SUCCESS) 
    443         goto on_error; 
    444  
    445     vp_param.active = (w->type == PJSUA_WND_TYPE_STREAM); 
    446     vp_param.vidparam.dir = PJMEDIA_DIR_RENDER; 
    447     vp_param.vidparam.fmt = *fmt; 
    448     vp_param.vidparam.disp_size = fmt->det.vid.size; 
    449     vp_param.vidparam.flags |= PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE; 
    450     vp_param.vidparam.window_hide = !show; 
    451  
    452     status = pjmedia_vid_port_create(w->pool, &vp_param, &w->vp_rend); 
    453     if (status != PJ_SUCCESS) 
    454         goto on_error; 
    455  
    456     /* For preview window, connect capturer & renderer (via tee) */ 
    457     if (w->type == PJSUA_WND_TYPE_PREVIEW) { 
    458         pjmedia_port *rend_port; 
    459  
    460         status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 
     500 
     501        /* If device supports native preview, enable it */ 
     502        if (w->is_native) { 
     503            pjmedia_vid_dev_stream *cap_dev; 
     504            pj_bool_t enabled = PJ_TRUE; 
     505 
     506            cap_dev = pjmedia_vid_port_get_stream(w->vp_cap); 
     507            status = pjmedia_vid_dev_stream_set_cap( 
     508                            cap_dev, PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW, 
     509                            &enabled); 
     510            if (status != PJ_SUCCESS) { 
     511                PJ_PERROR(1,(THIS_FILE, status, 
     512                             "Error activating native preview, falling back " 
     513                             "to software preview..")); 
     514                w->is_native = PJ_FALSE; 
     515            } 
     516        } 
     517    } 
     518 
     519    /* Create renderer video port, only if it's not a native preview */ 
     520    if (!w->is_native) { 
     521        status = pjmedia_vid_dev_default_param(w->pool, rend_id, 
     522                                               &vp_param.vidparam); 
    461523        if (status != PJ_SUCCESS) 
    462524            goto on_error; 
    463525 
    464         rend_port = pjmedia_vid_port_get_passive_port(w->vp_rend); 
    465         status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, rend_port); 
     526        vp_param.active = (w->type == PJSUA_WND_TYPE_STREAM); 
     527        vp_param.vidparam.dir = PJMEDIA_DIR_RENDER; 
     528        vp_param.vidparam.fmt = *fmt; 
     529        vp_param.vidparam.disp_size = fmt->det.vid.size; 
     530        vp_param.vidparam.flags |= PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE; 
     531        vp_param.vidparam.window_hide = !show; 
     532 
     533        status = pjmedia_vid_port_create(w->pool, &vp_param, &w->vp_rend); 
    466534        if (status != PJ_SUCCESS) 
    467535            goto on_error; 
    468     } 
     536 
     537        /* For preview window, connect capturer & renderer (via tee) */ 
     538        if (w->type == PJSUA_WND_TYPE_PREVIEW) { 
     539            pjmedia_port *rend_port; 
     540 
     541            status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 
     542            if (status != PJ_SUCCESS) 
     543                goto on_error; 
     544 
     545            rend_port = pjmedia_vid_port_get_passive_port(w->vp_rend); 
     546            status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, rend_port); 
     547            if (status != PJ_SUCCESS) 
     548                goto on_error; 
     549        } 
     550 
     551        PJ_LOG(4,(THIS_FILE, 
     552                  "%s window id %d created for cap_dev=%d rend_dev=%d", 
     553                  pjsua_vid_win_type_name(type), wid, cap_id, rend_id)); 
     554    } else { 
     555        PJ_LOG(4,(THIS_FILE, 
     556                  "Preview window id %d created for cap_dev %d, " 
     557                  "using built-in preview!", 
     558                  wid, cap_id)); 
     559    } 
     560 
    469561 
    470562    /* Done */ 
     
    734826            } 
    735827 
    736             /* Create preview video window */ 
    737             status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
    738                                     &media_port->info.fmt, 
    739                                     call_med->strm.v.rdr_dev, 
    740                                     call_med->strm.v.cap_dev, 
    741                                     //acc->cfg.vid_rend_dev, 
    742                                     //acc->cfg.vid_cap_dev, 
    743                                     PJ_FALSE, 
    744                                     &wid); 
    745             if (status != PJ_SUCCESS) { 
     828            wid = pjsua_vid_preview_get_win(call_med->strm.v.cap_dev); 
     829            if (wid == PJSUA_INVALID_ID) { 
     830                /* Create preview video window */ 
     831                status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
     832                                        &media_port->info.fmt, 
     833                                        call_med->strm.v.rdr_dev, 
     834                                        call_med->strm.v.cap_dev, 
     835                                        //acc->cfg.vid_rend_dev, 
     836                                        //acc->cfg.vid_cap_dev, 
     837                                        PJSUA_HIDE_WINDOW, 
     838                                        &wid); 
     839                if (status != PJ_SUCCESS) { 
    746840                pj_log_pop_indent(); 
    747                 goto on_error; 
     841                    return status; 
     842                } 
    748843            } 
    749844 
     
    903998} 
    904999 
     1000/* 
     1001 * Does it have built-in preview support. 
     1002 */ 
     1003PJ_DEF(pj_bool_t) pjsua_vid_preview_has_native(pjmedia_vid_dev_index id) 
     1004{ 
     1005    pjmedia_vid_dev_info vdi; 
     1006 
     1007    return (pjmedia_vid_dev_get_info(id, &vdi)==PJ_SUCCESS) ? 
     1008            ((vdi.caps & PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW)!=0) : PJ_FALSE; 
     1009} 
    9051010 
    9061011/* 
     
    9391044    w = &pjsua_var.win[wid]; 
    9401045 
     1046    /* Start renderer, unless it's native preview */ 
     1047    if (!w->is_native) { 
     1048        status = pjmedia_vid_port_start(w->vp_rend); 
     1049        if (status != PJ_SUCCESS) { 
     1050            PJSUA_UNLOCK(); 
     1051            pj_log_pop_indent(); 
     1052            return status; 
     1053        } 
     1054    } 
     1055 
    9411056    /* Start capturer */ 
    942     status = pjmedia_vid_port_start(w->vp_rend); 
    943     if (status != PJ_SUCCESS) { 
    944         PJSUA_UNLOCK(); 
    945         pj_log_pop_indent(); 
    946         return status; 
    947     } 
    948  
    949     /* Start renderer */ 
    9501057    status = pjmedia_vid_port_start(w->vp_cap); 
    9511058    if (status != PJ_SUCCESS) { 
     
    10291136    PJ_ASSERT_RETURN(wid >= 0 && wid < PJSUA_MAX_VID_WINS && wi, PJ_EINVAL); 
    10301137 
     1138    pj_bzero(wi, sizeof(*wi)); 
     1139 
    10311140    PJSUA_LOCK(); 
    10321141    w = &pjsua_var.win[wid]; 
     1142 
     1143    wi->is_native = w->is_native; 
     1144 
     1145    if (w->is_native) { 
     1146        pjmedia_vid_dev_stream *cap_strm; 
     1147        pjmedia_vid_dev_cap cap = PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW; 
     1148 
     1149        cap_strm = pjmedia_vid_port_get_stream(w->vp_cap); 
     1150        if (!cap_strm) { 
     1151            status = PJ_EINVAL; 
     1152        } else { 
     1153            status = pjmedia_vid_dev_stream_get_cap(cap_strm, cap, &wi->hwnd); 
     1154        } 
     1155 
     1156        PJSUA_UNLOCK(); 
     1157        return status; 
     1158    } 
     1159 
    10331160    if (w->vp_rend == NULL) { 
    10341161        PJSUA_UNLOCK(); 
     
    10751202    w = &pjsua_var.win[wid]; 
    10761203    if (w->vp_rend == NULL) { 
     1204        /* Native window */ 
    10771205        PJSUA_UNLOCK(); 
    10781206        return PJ_EINVAL; 
     
    11091237    w = &pjsua_var.win[wid]; 
    11101238    if (w->vp_rend == NULL) { 
     1239        /* Native window */ 
    11111240        PJSUA_UNLOCK(); 
    11121241        return PJ_EINVAL; 
     
    11421271    w = &pjsua_var.win[wid]; 
    11431272    if (w->vp_rend == NULL) { 
     1273        /* Native window */ 
    11441274        PJSUA_UNLOCK(); 
    11451275        return PJ_EINVAL; 
     
    12471377    pjsua_acc_config *acc_cfg = &pjsua_var.acc[call->acc_id].cfg; 
    12481378    pjsua_call_media *call_med; 
     1379    const pjmedia_sdp_session *current_sdp; 
    12491380    pjmedia_sdp_session *sdp; 
    12501381    pjmedia_sdp_media *sdp_m; 
     
    12611392        return PJ_ETOOMANY; 
    12621393 
    1263     /* Get active local SDP */ 
    1264     status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); 
     1394    /* Get active local SDP and clone it */ 
     1395    status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &current_sdp); 
    12651396    if (status != PJ_SUCCESS) 
    12661397        return status; 
     1398 
     1399    sdp = pjmedia_sdp_session_clone(call->inv->pool_prov, current_sdp); 
    12671400 
    12681401    /* Initialize call media */ 
     
    13461479{ 
    13471480    pjsua_call_media *call_med; 
     1481    const pjmedia_sdp_session *current_sdp; 
    13481482    pjmedia_sdp_session *sdp; 
    13491483    pj_status_t status; 
     
    13741508    } 
    13751509 
    1376     /* Get active local SDP */ 
    1377     status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &sdp); 
     1510    /* Get active local SDP and clone it */ 
     1511    status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &current_sdp); 
    13781512    if (status != PJ_SUCCESS) 
    13791513        return status; 
     1514 
     1515    sdp = pjmedia_sdp_session_clone(call->inv->pool_prov, current_sdp); 
    13801516 
    13811517    pj_assert(med_idx < (int)sdp->media_count); 
     
    15381674    /* = Attach stream port to the new capture device = */ 
    15391675 
    1540     /* Create preview video window */ 
    1541     status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
    1542                             &media_port->info.fmt, 
    1543                             call_med->strm.v.rdr_dev, 
    1544                             cap_dev, 
    1545                             PJ_FALSE, 
    1546                             &new_wid); 
    1547     if (status != PJ_SUCCESS) 
    1548         goto on_error; 
     1676    new_wid = pjsua_vid_preview_get_win(cap_dev); 
     1677    if (new_wid == PJSUA_INVALID_ID) { 
     1678        /* Create preview video window */ 
     1679        status = create_vid_win(PJSUA_WND_TYPE_PREVIEW, 
     1680                                &media_port->info.fmt, 
     1681                                call_med->strm.v.rdr_dev, 
     1682                                cap_dev, 
     1683                                PJSUA_HIDE_WINDOW, 
     1684                                &new_wid); 
     1685        if (status != PJ_SUCCESS) 
     1686            goto on_error; 
     1687    } 
    15491688 
    15501689    inc_vid_win(new_wid); 
     
    15611700        return status; 
    15621701 
     1702    if (w->vp_rend) { 
    15631703#if ENABLE_EVENT 
    1564     pjmedia_event_subscribe( 
    1565             pjmedia_vid_port_get_event_publisher(w->vp_rend), 
    1566             &call_med->esub_cap); 
     1704        pjmedia_event_subscribe( 
     1705                pjmedia_vid_port_get_event_publisher(w->vp_rend), 
     1706                &call_med->esub_cap); 
    15671707#endif 
    15681708 
    1569     /* Start renderer */ 
    1570     status = pjmedia_vid_port_start(new_w->vp_rend); 
    1571     if (status != PJ_SUCCESS) 
    1572         goto on_error; 
     1709        /* Start renderer */ 
     1710        status = pjmedia_vid_port_start(new_w->vp_rend); 
     1711        if (status != PJ_SUCCESS) 
     1712            goto on_error; 
     1713    } 
    15731714 
    15741715    /* Start capturer */ 
Note: See TracChangeset for help on using the changeset viewer.