[asterisk-commits] kharwell: branch group/pimp_my_sip r384736 - in /team/group/pimp_my_sip: chan...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 4 10:54:30 CDT 2013


Author: kharwell
Date: Thu Apr  4 10:54:27 2013
New Revision: 384736

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384736
Log:
SIP video support.

Adding in video support and capabilities.  This addition handles negotiation
of video streams, including attribute negotiation, and also the video source
update control frame (initiates a fast video update request - RFC 5168).

Since there was similar functionality between the audio and video these
modifications also merged the handling of the two media types into a single
file, res_sip_sdp_rtp.c

(issue ASTERISK-21077)

Added:
    team/group/pimp_my_sip/res/res_sip_sdp_rtp.c
      - copied unchanged from r384734, team/kharwell/pimp_sip_video/res/res_sip_sdp_rtp.c
Removed:
    team/group/pimp_my_sip/res/res_sip_sdp_audio.c
Modified:
    team/group/pimp_my_sip/channels/chan_gulp.c
    team/group/pimp_my_sip/include/asterisk/res_sip_session.h
    team/group/pimp_my_sip/res/res_sip_session.c

Modified: team/group/pimp_my_sip/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/channels/chan_gulp.c?view=diff&rev=384736&r1=384735&r2=384736
==============================================================================
--- team/group/pimp_my_sip/channels/chan_gulp.c (original)
+++ team/group/pimp_my_sip/channels/chan_gulp.c Thu Apr  4 10:54:27 2013
@@ -268,6 +268,21 @@
 	return AST_RTP_GLUE_RESULT_LOCAL;
 }
 
+/*! \brief Function called by RTP engine to get local video RTP peer */
+static enum ast_rtp_glue_result gulp_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
+{
+	struct gulp_pvt *pvt = ast_channel_tech_pvt(chan);
+
+	if (!pvt || !pvt->session || !pvt->media[SIP_MEDIA_VIDEO]->rtp) {
+		return AST_RTP_GLUE_RESULT_FORBID;
+	}
+
+	*instance = pvt->media[SIP_MEDIA_VIDEO]->rtp;
+	ao2_ref(*instance, +1);
+
+	return AST_RTP_GLUE_RESULT_LOCAL;
+}
+
 /*! \brief Function called by RTP engine to get peer capabilities */
 static void gulp_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
 {
@@ -384,6 +399,7 @@
 static struct ast_rtp_glue gulp_rtp_glue = {
 	.type = "Gulp",
 	.get_rtp_info = gulp_get_rtp_peer,
+	.get_vrtp_info = gulp_get_vrtp_peer,
 	.get_codec = gulp_get_codec,
 	.update_peer = gulp_set_rtp_peer,
 };
@@ -416,9 +432,13 @@
 	pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY);
 	ast_channel_tech_pvt_set(chan, pvt);
 
-	ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->codecs);
-	ast_codec_choose(&session->endpoint->prefs, session->endpoint->codecs, 1, &fmt);
-
+	if (ast_format_cap_is_empty(session->req_caps)) {
+		ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->codecs);
+	} else {
+		ast_format_cap_copy(ast_channel_nativeformats(chan), session->req_caps);
+	}
+
+	ast_codec_choose(&session->endpoint->prefs, ast_channel_nativeformats(chan), 1, &fmt);
 	ast_format_copy(ast_channel_writeformat(chan), &fmt);
 	ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
 	ast_format_copy(ast_channel_readformat(chan), &fmt);
@@ -477,22 +497,32 @@
 {
 	struct gulp_pvt *pvt = ast_channel_tech_pvt(ast);
 	struct ast_frame *f;
-	struct ast_sip_session_media *media = pvt->media[SIP_MEDIA_AUDIO];
-
-	if (!media) {
+	struct ast_sip_session_media *media = NULL;
+	int rtcp = 0;
+	int fdno = ast_channel_fdno(ast);
+
+	switch (fdno) {
+	case 0:
+		media = pvt->media[SIP_MEDIA_AUDIO];
+		break;
+	case 1:
+		media = pvt->media[SIP_MEDIA_AUDIO];
+		rtcp = 1;
+		break;
+	case 2:
+		media = pvt->media[SIP_MEDIA_VIDEO];
+		break;
+	case 3:
+		media = pvt->media[SIP_MEDIA_VIDEO];
+		rtcp = 1;
+		break;
+	}
+
+	if (!media || !media->rtp) {
 		return &ast_null_frame;
 	}
 
-	switch (ast_channel_fdno(ast)) {
-	case 0:
-		f = ast_rtp_instance_read(media->rtp, 0);
-		break;
-	case 1:
-		f = ast_rtp_instance_read(media->rtp, 1);
-		break;
-	default:
-		f = &ast_null_frame;
-	}
+	f = ast_rtp_instance_read(media->rtp, rtcp);
 
 	if (f && f->frametype == AST_FRAME_VOICE) {
 		if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &f->subclass.format))) {
@@ -535,6 +565,11 @@
 			res = ast_rtp_instance_write(media->rtp, frame);
 		}
 		break;
+	case AST_FRAME_VIDEO:
+		if ((media = pvt->media[SIP_MEDIA_VIDEO]) && media->rtp) {
+			res = ast_rtp_instance_write(media->rtp, frame);
+		}
+		break;
 	default:
 		ast_log(LOG_WARNING, "Can't send %d type frames with Gulp\n", frame->frametype);
 		break;
@@ -627,12 +662,40 @@
 	return 0;
 }
 
+/*! \brief Send SIP INFO with video update request */
+static int transmit_info_with_vidupdate(void *data)
+{
+	const char * xml =
+		"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
+		" <media_control>\r\n"
+		"  <vc_primitive>\r\n"
+		"   <to_encoder>\r\n"
+		"    <picture_fast_update/>\r\n"
+		"   </to_encoder>\r\n"
+		"  </vc_primitive>\r\n"
+		" </media_control>\r\n";
+
+	const struct ast_sip_body body = {
+		.type = "application",
+		.subtype = "media_control+xml",
+		.body_text = xml
+	};
+
+	struct ast_sip_session *session = data;
+	if (ast_sip_send_request("INFO", &body, session->inv_session->dlg, NULL) != PJ_SUCCESS) {
+		ast_log(LOG_ERROR, "Could not send text video update INFO request\n");
+	}
+
+	return 0;
+}
+
 /*! \brief Function called by core to ask the channel to indicate some sort of condition */
 static int gulp_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
 {
 	int res = 0;
 	struct gulp_pvt *pvt = ast_channel_tech_pvt(ast);
 	struct ast_sip_session *session = pvt->session;
+	struct ast_sip_session_media *media;
 	int response_code = 0;
 
 	switch (condition) {
@@ -679,6 +742,12 @@
 		}
 		break;
 	case AST_CONTROL_VIDUPDATE:
+		media = pvt->media[SIP_MEDIA_VIDEO];
+		if (media && media->rtp) {
+			ast_sip_push_task(session->serializer, transmit_info_with_vidupdate, session);
+		} else
+			res = -1;
+		break;
 	case AST_CONTROL_UPDATE_RTP_PEER:
 	case AST_CONTROL_PVT_CAUSE_CODE:
 		break;
@@ -930,6 +999,7 @@
 
 struct request_data {
 	struct ast_sip_session *session;
+	struct ast_format_cap *caps;
 	const char *dest;
 	int cause;
 };
@@ -970,12 +1040,13 @@
 		return -1;
 	}
 
-	if (!(session = ast_sip_session_create_outgoing(endpoint, args.aor, request_user))) {
+	if (!(session = ast_sip_session_create_outgoing(endpoint, args.aor, request_user, req_data->caps))) {
 		req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
 		return -1;
 	}
 
 	req_data->session = session;
+
 	return 0;
 }
 
@@ -985,6 +1056,7 @@
 	struct request_data req_data;
 	struct ast_sip_session *session;
 
+	req_data.caps = cap;
 	req_data.dest = data;
 
 	if (ast_sip_push_task_synchronous(NULL, request, &req_data)) {

Modified: team/group/pimp_my_sip/include/asterisk/res_sip_session.h
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/include/asterisk/res_sip_session.h?view=diff&rev=384736&r1=384735&r2=384736
==============================================================================
--- team/group/pimp_my_sip/include/asterisk/res_sip_session.h (original)
+++ team/group/pimp_my_sip/include/asterisk/res_sip_session.h Thu Apr  4 10:54:27 2013
@@ -97,6 +97,8 @@
 	pj_timer_entry rescheduled_reinvite;
 	/* Format capabilities pertaining to direct media */
 	struct ast_format_cap *direct_media_cap;
+	/* Requested capabilities */
+	struct ast_format_cap *req_caps;
 };
 
 typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
@@ -266,8 +268,9 @@
  * \param endpoint The endpoint that this session uses for settings
  * \param location Optional name of the location to call, be it named location or explicit URI
  * \param request_user Optional request user to place in the request URI if permitted
- */
-struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint, const char *location, const char *request_user);
+ * \param req_caps The requested capabilities
+ */
+struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint, const char *location, const char *request_user, struct ast_format_cap *req_caps);
 
 /*!
  * \brief Register an SDP handler

Modified: team/group/pimp_my_sip/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/group/pimp_my_sip/res/res_sip_session.c?view=diff&rev=384736&r1=384735&r2=384736
==============================================================================
--- team/group/pimp_my_sip/res/res_sip_session.c (original)
+++ team/group/pimp_my_sip/res/res_sip_session.c Thu Apr  4 10:54:27 2013
@@ -871,6 +871,7 @@
 		ast_free(delay);
 	}
 	ao2_cleanup(session->endpoint);
+	ast_format_cap_destroy(session->req_caps);
 }
 
 static int add_supplements(struct ast_sip_session *session)
@@ -933,6 +934,8 @@
 	inv_session->mod_data[session_module.id] = session;
 	session->endpoint = endpoint;
 	session->inv_session = inv_session;
+	session->req_caps = ast_format_cap_alloc_nolock();
+
 	if (add_supplements(session)) {
 		return NULL;
 	}
@@ -953,7 +956,7 @@
 	return CMP_MATCH | CMP_STOP;
 }
 
-struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint, const char *location, const char *request_user)
+struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint, const char *location, const char *request_user, struct ast_format_cap *req_caps)
 {
 	char *aor_name, *rest;
 	const char *uri = NULL;
@@ -1011,9 +1014,14 @@
 	timer.sess_expires = endpoint->sess_expires;
 	pjsip_timer_init_session(inv_session, &timer);
 
-	if (!(session = ast_sip_session_alloc(endpoint, inv_session)) ||
-		(pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) ||
-		!(offer = create_local_sdp(inv_session, session, NULL))) {
+	if (!(session = ast_sip_session_alloc(endpoint, inv_session))) {
+		pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
+		return NULL;
+	}
+
+	ast_format_cap_copy(session->req_caps, req_caps);
+	if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) ||
+	    !(offer = create_local_sdp(inv_session, session, NULL))) {
 		pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
 		return NULL;
 	}
@@ -1194,6 +1202,19 @@
 	ast_sip_session_send_response(session, tdata);
 
 	handle_incoming_request(session, rdata);
+}
+
+static int has_supplement(struct ast_sip_session *session, pjsip_rx_data *rdata)
+{
+	struct ast_sip_session_supplement *supplement;
+	struct pjsip_method *method = &rdata->msg_info.msg->line.req.method;
+
+	AST_LIST_TRAVERSE(&session->supplements, supplement, next) {
+		if (!supplement->method || !pj_strcmp2(&method->name, supplement->method)) {
+			return PJ_TRUE;
+		}
+	}
+	return PJ_FALSE;
 }
 /*!
  * \brief Called when a new SIP request comes into PJSIP
@@ -1212,9 +1233,10 @@
  *    them into the threadpool).
  */
 static pj_bool_t session_on_rx_request(pjsip_rx_data *rdata)
-{ 
+{
 	pj_status_t handled = PJ_FALSE;
 	pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
+	pjsip_inv_session *inv_session;
 
 	switch (rdata->msg_info.msg->line.req.method.id) {
 	case PJSIP_INVITE_METHOD:
@@ -1225,10 +1247,10 @@
 		handled = PJ_TRUE;
 		handle_new_invite_request(rdata);
 		break;
-	case PJSIP_OTHER_METHOD:
-		/* Area for INFO and REFER, possibly other methods */
-		break;
 	default:
+		/* Handle other in-dialog methods if their supplements have been registered */
+		handled = dlg && (inv_session = pjsip_dlg_get_inv_session(dlg)) &&
+			has_supplement(inv_session->mod_data[session_module.id], rdata);
 		break;
 	}
 
@@ -1519,6 +1541,10 @@
 					ast_sip_session_send_request(session, tdata);
 				}
 			}
+		} else {
+			if (tsx->role == PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING) {
+				handle_incoming_request(session, e->body.tsx_state.src.rdata);
+			}
 		}
 		if (tsx->mod_data[session_module.id]) {
 			ast_sip_session_response_cb cb = tsx->mod_data[session_module.id];




More information about the asterisk-commits mailing list