[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