[asterisk-commits] kharwell: branch kharwell/pimp_sip_video r383498 - in /team/kharwell/pimp_sip...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 20 16:54:47 CDT 2013


Author: kharwell
Date: Wed Mar 20 16:54:46 2013
New Revision: 383498

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383498
Log:
video for chan_gulp - initial review

Modified:
    team/kharwell/pimp_sip_video/channels/chan_gulp.c
    team/kharwell/pimp_sip_video/res/res_sip_sdp_video.c

Modified: team/kharwell/pimp_sip_video/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_video/channels/chan_gulp.c?view=diff&rev=383498&r1=383497&r2=383498
==============================================================================
--- team/kharwell/pimp_sip_video/channels/chan_gulp.c (original)
+++ team/kharwell/pimp_sip_video/channels/chan_gulp.c Wed Mar 20 16:54:46 2013
@@ -314,7 +314,7 @@
 	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->caps); /* session->endpoint->codecs); */
+	ast_format_cap_copy(ast_channel_nativeformats(chan), session->caps);
 	ast_codec_choose(&session->endpoint->prefs, session->endpoint->codecs, 1, &fmt);
 
 	ast_format_copy(ast_channel_writeformat(chan), &fmt);
@@ -560,7 +560,6 @@
 	}
 
 	packet->msg->body = pjsip_msg_body_create(packet->pool, &type, &subtype, &xml);
-        /* ast_sip_session_send_request(session, packet); */
 	return 0;
 }
 

Modified: team/kharwell/pimp_sip_video/res/res_sip_sdp_video.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_video/res/res_sip_sdp_video.c?view=diff&rev=383498&r1=383497&r2=383498
==============================================================================
--- team/kharwell/pimp_sip_video/res/res_sip_sdp_video.c (original)
+++ team/kharwell/pimp_sip_video/res/res_sip_sdp_video.c Wed Mar 20 16:54:46 2013
@@ -16,13 +16,6 @@
  * at the top of the source tree.
  */
 
-/*! \file
- *
- * \author Kevin Harwell <kharwell at digium.com>
- *
- * \brief SIP SDP 'video' media stream handling
- */
-
 /*** MODULEINFO
 	<depend>res_sip</depend>
 	<depend>res_sip_session</depend>
@@ -55,21 +48,6 @@
 /*! \brief Scheduler for RTCP purposes */
 static struct ast_sched_context *sched;
 
-/*! \brief Forward declarations for SDP handler functions */
-static int video_negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream);
-static int video_create_outgoing_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp);
-static int video_apply_negotiated_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream);
-static void video_stream_destroy(struct ast_sip_session_media *session_media);
-
-/*! \brief SDP handler for 'video' media stream */
-static struct ast_sip_session_sdp_handler video_sdp_handler = {
-	.id = STR_VIDEO,
-	.negotiate_incoming_sdp_stream = video_negotiate_incoming_sdp_stream,
-	.create_outgoing_sdp_stream = video_create_outgoing_sdp_stream,
-	.apply_negotiated_sdp_stream = video_apply_negotiated_sdp_stream,
-	.stream_destroy = video_stream_destroy,
-};
-
 /*! \brief Internal function which creates an RTP instance */
 static int video_create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6)
 {
@@ -100,7 +78,8 @@
 	return 0;
 }
 
-static void get_peer_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs, const char *type)
+static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream,
+		       struct ast_rtp_codecs* codecs, const char *type)
 {
 	pjmedia_sdp_attr *attr;
 	int i, num = 0;
@@ -136,60 +115,90 @@
 	}
 }
 
-static int get_peer_caps(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, const char *type)
-{
+static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
+		    const struct pjmedia_sdp_media *stream, enum ast_format_type type, const char *type_desc)
+{
+	RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
+	RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
+	RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
 	struct ast_rtp_codecs codecs;
-	RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
+	struct ast_format fmt;
 	int fmts = 0;
 
-	if (!(peer = ast_format_cap_alloc_nolock())) {
-		ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", type);
-		return -1;
-	}
-
-	get_peer_codecs(session, stream, &codecs, type);
+	if (!(caps = ast_format_cap_alloc_nolock()) ||
+	    !(peer = ast_format_cap_alloc_nolock())) {
+		ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", type_desc);
+		return -1;
+	}
+
+	/* get the endpoint capabilities */
+	ast_format_cap_copy(caps, session->endpoint->codecs);
+	ast_format_cap_remove_bytype(caps, AST_FORMAT_TYPE_AUDIO);
+
+	/* get the capabilities on the peer */
+	get_codecs(session, stream, &codecs, type_desc);
 	ast_rtp_codecs_payload_formats(&codecs, peer, &fmts);
 
-	ast_format_cap_append(session->caps, peer);
-	ast_rtp_codecs_payloads_destroy(&codecs);
-
-	return 1;
-}
-
-static struct ast_format_cap* get_joint_caps(struct ast_sip_session *session, const struct ast_format_cap *caps, 
-					     const char *type, enum ast_format_type remove_fmt)
-{
-	RAII_VAR(struct ast_format_cap *, conf, NULL, ast_format_cap_destroy);
-	RAII_VAR(struct ast_format_cap *, peer, NULL, ast_format_cap_destroy);
-	struct ast_format_cap *joint;
-
-	if (!(conf = ast_format_cap_alloc_nolock()) ||
-	    !(peer = ast_format_cap_alloc_nolock())) {
-		ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n", type);
-		return NULL;
-	}
-
-	ast_format_cap_copy(conf, session->endpoint->codecs);
-	ast_format_cap_remove_bytype(conf, remove_fmt);
-
-	ast_format_cap_copy(peer, caps);
-	ast_format_cap_remove_bytype(peer, remove_fmt);
-
-	/* ast_format_cap_joint_copy */
-	if (!(joint = ast_format_cap_joint(conf, peer))) {
+	/* get the joint capabilities between peer and endpoint */
+	if (!(joint = ast_format_cap_joint(caps, peer))) {
 		char usbuf[64], thembuf[64];
 
+		ast_rtp_codecs_payloads_destroy(&codecs);
 		if (session->channel) {
 			ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
 		}
 
-		ast_getformatname_multiple(usbuf, sizeof(usbuf), conf);
+		ast_getformatname_multiple(usbuf, sizeof(usbuf), caps);
 		ast_getformatname_multiple(thembuf, sizeof(thembuf), peer);
 		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
-		return NULL;
-	}
-
-	return joint;
+		return -1;
+	}
+
+	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
+				     session_media->rtp);
+
+	ast_format_cap_copy(caps, session->caps);
+	ast_format_cap_remove_bytype(caps, type);
+	ast_format_cap_append(caps, joint);
+	ast_format_cap_append(session->caps, joint);
+
+	if (session->channel) {
+		/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
+		ast_format_cap_append(ast_channel_nativeformats(session->channel), session->caps);
+		ast_codec_choose(&session->endpoint->prefs, caps, 0, &fmt);
+		ast_format_copy(ast_channel_rawwriteformat(session->channel), &fmt);
+		ast_format_copy(ast_channel_rawreadformat(session->channel), &fmt);
+		ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
+		ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+	}
+
+	ast_rtp_codecs_payloads_destroy(&codecs);
+	return 1;
+}
+
+static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
+{
+	struct ast_str *fmtp0 = ast_str_alloca(256);
+	pj_str_t fmtp1;
+	pjmedia_sdp_attr *attr = NULL;
+	char *tmp;
+
+	ast_format_sdp_generate(format, rtp_code, &fmtp0);
+	if (ast_str_strlen(fmtp0)) {
+		tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
+		/* remove any carriage return line feeds */
+		while (*tmp == '\r' || *tmp == '\n') --tmp;
+		*++tmp = '\0';
+		/* ast...generate gives us everything, just need value */
+		tmp = strchr(ast_str_buffer(fmtp0), ':');
+		if (tmp && tmp+1) {
+			fmtp1 = pj_str(tmp+1);
+		} else {
+			fmtp1 = pj_str(ast_str_buffer(fmtp0));
+		}
+		attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1);
+	}
+	return attr;
 }
 
 /*! \brief Function which negotiates an incoming 'video' stream */
@@ -215,8 +224,9 @@
 	if (!session_media->rtp && video_create_rtp(session, session_media, ast_sockaddr_is_ipv6(addrs))) {
 		return -1;
 	}
+
 	/* pjmedia takes care of the formats and such */
-	return get_peer_caps(session, stream, STR_VIDEO);
+	return set_caps(session, session_media, stream, AST_FORMAT_TYPE_VIDEO, STR_VIDEO);
 }
 
 /*! \brief Function which creates an outgoing 'video' stream */
@@ -231,13 +241,12 @@
 	pj_pool_t *pool = session->inv_session->pool_active;
 	pjmedia_sdp_media *media;
 	struct ast_sockaddr addr;
-
 	int rtp_code0;
 	char rtp_code1[32];
-	struct ast_str *fmtp0 = ast_str_alloca(256);
-	pj_str_t fmtp1;
 	pjmedia_sdp_rtpmap rtpmap;
 	pjmedia_sdp_attr *attr;
+	struct ast_format format;
+	RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
 
 	if (!ast_format_cap_has_type(session->endpoint->codecs, AST_FORMAT_TYPE_VIDEO)) {
 		/* If no video formats are configured don't add a stream */
@@ -265,26 +274,22 @@
 	media->desc.port = (pj_uint16_t) ast_sockaddr_port(&addr);
 	media->desc.port_count = 1;
 
-	struct ast_format format;
-	RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
-
-	if (!ast_format_cap_is_empty(session->caps)) {
-		joint = get_joint_caps(session, session->caps, "video", AST_FORMAT_TYPE_AUDIO);
-	}
-	
-	if (!joint) {
-		if (!(joint = ast_format_cap_alloc_nolock())) {
-			ast_log(LOG_ERROR, "Failed to allocate video capabilities\n");
-			return -1;
-		}
+	if (!(joint = ast_format_cap_alloc_nolock())) {
+		ast_log(LOG_ERROR, "Failed to allocate video capabilities\n");
+		return -1;
+	}
+	if (ast_format_cap_is_empty(session->caps)) {
 		ast_format_cap_copy(joint, session->endpoint->codecs);
+	} else {
+		ast_format_cap_copy(joint, session->caps);
 	}
 
 	ast_format_cap_iter_start(joint);
 	while (!(ast_format_cap_iter_next(joint, &format))) {
-		/* if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) { */
-		/* 	continue; */
-		/* } */
+		if (AST_FORMAT_GET_TYPE(format.id) != AST_FORMAT_TYPE_VIDEO) {
+			continue;
+		}
+
 		if ((rtp_code0 = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, &format, 0)) == -1) {
 			return -1;
 		}
@@ -299,12 +304,8 @@
 		pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
 		media->attr[media->attr_count++] = attr;
 
-		ast_format_sdp_generate(&format, rtp_code0, &fmtp0);
-		if (ast_str_strlen(fmtp0)) {
-			fmtp1 = pj_str(ast_str_buffer(fmtp0));
-			if ((attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1))) {
-				media->attr[media->attr_count++] = attr;
-			}
+		if ((attr = generate_fmtp_attr(pool, &format, rtp_code0))) {
+			media->attr[media->attr_count++] = attr;
 		}
 	}
 	ast_format_cap_iter_end(joint);
@@ -323,15 +324,10 @@
 /*! \brief Function which applies a negotiated SDP stream */
 static int video_apply_negotiated_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_media *local_stream, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
 {
-	int format, othercapability = 0;
 	char host[NI_MAXHOST];
 	RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
-	struct ast_rtp_codecs codecs;
-	const pjmedia_sdp_attr *attr;
-	RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
-	RAII_VAR(struct ast_format_cap *, jointcap, NULL, ast_format_cap_destroy);
-	RAII_VAR(struct ast_format_cap *, peercap, NULL, ast_format_cap_destroy);
-	struct ast_format fmt;
+
+	RAII_VAR(struct ast_format_cap *, joint, NULL, ast_format_cap_destroy);
 
 	/* Create an RTP instance if need be */
 	if (!session_media->rtp && video_create_rtp(session, session_media, session->endpoint->rtp_ipv6)) {
@@ -346,77 +342,17 @@
 		return -1;
 	}
 
-	/* To properly apply formats to the channel we need to keep track of capabilities */
-	if (!(cap = ast_format_cap_alloc_nolock()) ||
-	    !(peercap = ast_format_cap_alloc_nolock())) {
-		ast_log(LOG_ERROR, "Failed to allocate video capabilities\n");
-		return -1;
-	}
-
 	/* Apply connection information to the RTP instance */
 	ast_sockaddr_set_port(addrs, remote_stream->desc.port);
 	ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
 
-	ast_rtp_codecs_payloads_initialize(&codecs);
-
-	/* Iterate through provided formats */
-	for (format = 0; format < local_stream->desc.fmt_count; format++) {
-		/* The payload is kept as a string for things like t38 but for video it is always numerical */
-		ast_rtp_codecs_payloads_set_m_type(&codecs, NULL, pj_strtoul(&local_stream->desc.fmt[format]));
-
-		/* Look for the optional rtpmap attribute */
-		if ((attr = pjmedia_sdp_media_find_attr2(local_stream, "rtpmap", &local_stream->desc.fmt[format]))) {
-			pjmedia_sdp_rtpmap *rtpmap;
-
-			/* Interpret the attribute as an rtpmap */
-			if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_active, attr, &rtpmap)) == PJ_SUCCESS) {
-				char name[32];
-
-				ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name));
-				ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, pj_strtoul(&local_stream->desc.fmt[format]),
-									     "video", name, 0, rtpmap->clock_rate);
-			}
-		}
-	}
-
-	ast_rtp_codecs_payload_formats(&codecs, peercap, &othercapability);
-
-	/* Using the configured codecs and the codecs in this SDP we determine the joint formats for *video only* */
-	ast_format_cap_copy(cap, session->endpoint->codecs);
-	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_AUDIO);
-
-	if (!(jointcap = ast_format_cap_joint(cap, peercap))) {
-		char usbuf[64], thembuf[64];
-
-		ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
-		ast_getformatname_multiple(usbuf, sizeof(usbuf), cap);
-		ast_getformatname_multiple(thembuf, sizeof(thembuf), peercap);
-		ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", usbuf, thembuf);
-
-		ast_rtp_codecs_payloads_destroy(&codecs);
-		return -1;
-	}
-
-	ast_rtp_codecs_payloads_copy(&codecs, ast_rtp_instance_get_codecs(session_media->rtp),
-				     session_media->rtp);
-
-	/* Now that we have joint formats for video remove the existing ones from the channel and add the new ones */
-	ast_format_cap_copy(cap, ast_channel_nativeformats(session->channel));
-	ast_format_cap_remove_bytype(cap, AST_FORMAT_TYPE_AUDIO);
-	ast_format_cap_append(cap, jointcap);
-
-	/* Apply the new formats to the channel, potentially changing read/write formats while doing so */
-	ast_format_cap_append(ast_channel_nativeformats(session->channel), cap);
-	ast_codec_choose(&session->endpoint->prefs, cap, 0, &fmt);
-	ast_format_copy(ast_channel_rawwriteformat(session->channel), &fmt);
-	ast_format_copy(ast_channel_rawreadformat(session->channel), &fmt);
-	ast_set_read_format(session->channel, ast_channel_readformat(session->channel));
-	ast_set_write_format(session->channel, ast_channel_writeformat(session->channel));
+	if (set_caps(session, session_media, local_stream, AST_FORMAT_TYPE_VIDEO, STR_VIDEO) < 1) {
+		return -1;
+	}
 
 	ast_channel_set_fd(session->channel, 2, ast_rtp_instance_fd(session_media->rtp, 0));
 	ast_channel_set_fd(session->channel, 3, ast_rtp_instance_fd(session_media->rtp, 1));
 
-	ast_rtp_codecs_payloads_destroy(&codecs);
 	return 1;
 }
 
@@ -430,6 +366,15 @@
 	ast_rtp_instance_stop(session_media->rtp);
 	ast_rtp_instance_destroy(session_media->rtp);
 }
+
+/*! \brief SDP handler for 'video' media stream */
+static struct ast_sip_session_sdp_handler video_sdp_handler = {
+	.id = STR_VIDEO,
+	.negotiate_incoming_sdp_stream = video_negotiate_incoming_sdp_stream,
+	.create_outgoing_sdp_stream = video_create_outgoing_sdp_stream,
+	.apply_negotiated_sdp_stream = video_apply_negotiated_sdp_stream,
+	.stream_destroy = video_stream_destroy,
+};
 
 static int incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 {
@@ -468,7 +413,7 @@
 		goto end;
 	}
 
-	if (ast_sip_session_register_sdp_handler(&video_sdp_handler, "video")) {
+	if (ast_sip_session_register_sdp_handler(&video_sdp_handler, STR_VIDEO)) {
 		ast_log(LOG_ERROR, "Unable to register SDP handler for 'video' stream type\n");
 		goto end;
 	}
@@ -488,7 +433,7 @@
 static int unload_module(void)
 {
 	ast_sip_session_unregister_supplement(&info_supplement);
-	ast_sip_session_unregister_sdp_handler(&video_sdp_handler, "video");
+	ast_sip_session_unregister_sdp_handler(&video_sdp_handler, STR_VIDEO);
 	ast_sched_context_destroy(sched);
 	return 0;
 }




More information about the asterisk-commits mailing list