/* * Initialize session info from SDP session descriptors. */ PJ_DEF(pj_status_t) pjmedia_session_info_from_sdp( pj_pool_t *pool, pjmedia_endpt *endpt, unsigned max_streams, pjmedia_session_info *si, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote) { unsigned i; PJ_ASSERT_RETURN(pool && endpt && si && local && remote, PJ_EINVAL); si->stream_cnt = max_streams; if (si->stream_cnt > local->media_count) si->stream_cnt = local->media_count; for (i=0; i<si->stream_cnt; ++i) { pj_status_t status; status = pjmedia_stream_info_from_sdp( &si->stream_info[i], pool, endpt, local, remote, i); if (status != PJ_SUCCESS) return status; } return PJ_SUCCESS; }
/* * Callback when SDP negotiation has completed. * We are interested with this callback because we want to start media * as soon as SDP negotiation is completed. */ static void call_on_media_update( pjsip_inv_session *inv, pj_status_t status) { pjmedia_stream_info stream_info; const pjmedia_sdp_session *local_sdp; const pjmedia_sdp_session *remote_sdp; pjmedia_port *media_port; if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "SDP negotiation has failed", status); /* Here we should disconnect call if we're not in the middle * of initializing an UAS dialog and if this is not a re-INVITE. */ return; } /* Get local and remote SDP. * We need both SDPs to create a media session. */ status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp); status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp); /* Create stream info based on the media audio SDP. */ status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool, g_med_endpt, local_sdp, remote_sdp, 0); if (status != PJ_SUCCESS) { app_perror(THIS_FILE,"Unable to create audio stream info",status); return; } /* If required, we can also change some settings in the stream info, * (such as jitter buffer settings, codec settings, etc) before we * create the stream. */ /* Create new audio media stream, passing the stream info, and also the * media socket that we created earlier. */ status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info, g_med_transport[0], NULL, &g_med_stream); if (status != PJ_SUCCESS) { app_perror( THIS_FILE, "Unable to create audio stream", status); return; } /* Start the audio stream */ status = pjmedia_stream_start(g_med_stream); if (status != PJ_SUCCESS) { app_perror( THIS_FILE, "Unable to start audio stream", status); return; } /* Get the media port interface of the audio stream. * Media port interface is basicly a struct containing get_frame() and * put_frame() function. With this media port interface, we can attach * the port interface to conference bridge, or directly to a sound * player/recorder device. */ pjmedia_stream_get_port(g_med_stream, &media_port); /* Create sound port */ pjmedia_snd_port_create(inv->pool, PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV, PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */ PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */ PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/ PJMEDIA_PIA_BITS(&media_port->info),/* bits per sample */ 0, &g_snd_port); if (status != PJ_SUCCESS) { app_perror( THIS_FILE, "Unable to create sound port", status); PJ_LOG(3,(THIS_FILE, "%d %d %d %d", PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */ PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */ PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/ PJMEDIA_PIA_BITS(&media_port->info) /* bits per sample */ )); return; } status = pjmedia_snd_port_connect(g_snd_port, media_port); /* Get the media port interface of the second stream in the session, * which is video stream. With this media port interface, we can attach * the port directly to a renderer/capture video device. */ #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) if (local_sdp->media_count > 1) { pjmedia_vid_stream_info vstream_info; pjmedia_vid_port_param vport_param; pjmedia_vid_port_param_default(&vport_param); /* Create stream info based on the media video SDP. */ status = pjmedia_vid_stream_info_from_sdp(&vstream_info, inv->dlg->pool, g_med_endpt, local_sdp, remote_sdp, 1); if (status != PJ_SUCCESS) { app_perror(THIS_FILE,"Unable to create video stream info",status); return; } /* If required, we can also change some settings in the stream info, * (such as jitter buffer settings, codec settings, etc) before we * create the video stream. */ /* Create new video media stream, passing the stream info, and also the * media socket that we created earlier. */ status = pjmedia_vid_stream_create(g_med_endpt, NULL, &vstream_info, g_med_transport[1], NULL, &g_med_vstream); if (status != PJ_SUCCESS) { app_perror( THIS_FILE, "Unable to create video stream", status); return; } /* Start the video stream */ status = pjmedia_vid_stream_start(g_med_vstream); if (status != PJ_SUCCESS) { app_perror( THIS_FILE, "Unable to start video stream", status); return; } if (vstream_info.dir & PJMEDIA_DIR_DECODING) { status = pjmedia_vid_dev_default_param( inv->pool, PJMEDIA_VID_DEFAULT_RENDER_DEV, &vport_param.vidparam); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to get default param of video " "renderer device", status); return; } /* Get video stream port for decoding direction */ pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_DECODING, &media_port); /* Set format */ pjmedia_format_copy(&vport_param.vidparam.fmt, &media_port->info.fmt); vport_param.vidparam.dir = PJMEDIA_DIR_RENDER; vport_param.active = PJ_TRUE; /* Create renderer */ status = pjmedia_vid_port_create(inv->pool, &vport_param, &g_vid_renderer); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create video renderer device", status); return; } /* Connect renderer to media_port */ status = pjmedia_vid_port_connect(g_vid_renderer, media_port, PJ_FALSE); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to connect renderer to stream", status); return; } } /* Create capturer */ if (vstream_info.dir & PJMEDIA_DIR_ENCODING) { status = pjmedia_vid_dev_default_param( inv->pool, PJMEDIA_VID_DEFAULT_CAPTURE_DEV, &vport_param.vidparam); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to get default param of video " "capture device", status); return; } /* Get video stream port for decoding direction */ pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_ENCODING, &media_port); /* Get capturer format from stream info */ pjmedia_format_copy(&vport_param.vidparam.fmt, &media_port->info.fmt); vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; vport_param.active = PJ_TRUE; /* Create capturer */ status = pjmedia_vid_port_create(inv->pool, &vport_param, &g_vid_capturer); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create video capture device", status); return; } /* Connect capturer to media_port */ status = pjmedia_vid_port_connect(g_vid_capturer, media_port, PJ_FALSE); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to connect capturer to stream", status); return; } } /* Start streaming */ if (g_vid_renderer) { status = pjmedia_vid_port_start(g_vid_renderer); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to start video renderer", status); return; } } if (g_vid_capturer) { status = pjmedia_vid_port_start(g_vid_capturer); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to start video capturer", status); return; } } } #endif /* PJMEDIA_HAS_VIDEO */ /* Done with media. */ }