Media Exchange Module


Table of Contents

1. Admin Guide
1.1. Overview
1.2. Dependencies
1.2.1. OpenSIPS Modules
1.2.2. External Libraries or Applications
1.3. Exported Functions
1.3.1. media_fork_to_uri(URI[, leg[, headers[, medianum]]])
1.3.2. media_fork_from_call(callid[, leg[, medianum]])
1.3.3. media_fork_pause([leg[, medianum]])
1.3.4. media_fork_resume([leg[, medianum]])
1.3.5. media_exchange_from_uri(URI[, leg[, body[, headers[, nohold]]]])
1.3.6. media_exchange_to_call(callid[, leg[, nohold]])
1.3.7. media_terminate([leg[, nohold]])
1.3.8. media_handle_indialog()
1.4. Exported MI Functions
1.4.1. media_fork_from_call_to_uri
1.4.2. media_exchange_from_call_to_uri
1.4.3. media_exchange_from_call_to_uri_body
1.4.4. media_terminate
2. Contributors
2.1. By Commit Statistics
2.2. By Commit Activity
3. Documentation
3.1. Contributors

List of Tables

2.1. Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
2.2. Most recently active contributors(1) to this module

List of Examples

1.1. Use media_fork_to_uri() function to fork media to a Media Server
1.2. Use media_fork_from_call() function to fork all media streams of a call
1.3. Use media_fork_from_call() function to fork only the first caller's stream
1.4. Use media_fork_pause() function to temporarily stop the entire media stream of the call
1.5. Use media_fork_resume() function to resume a forking previously stopped
1.6. Use media_exchange_from_uri() function to fetch media from a Media Server's call
1.7. Use media_exchange_to_call() function to make an announcement
1.8. Use media_terminate() function to terminate an announcement
1.9. Use media_terminate() function to terminate an announcement

Chapter 1. Admin Guide

1.1. Overview

This module provides the means to exchange media SDP between different SIP proxied calls, and calls started or received from a Media Server. The module itself does not have any media capabilities, it simply exposes primitives to exchange the SDP body between two or more different calls.

The module can both originate calls, pushing an existing SDP to a media server, to playback, or simply record an existing RTP, as well as take the SDP of a new call and inject the SDP into an existing, proxied sip call. In order to manipulate the new calls, either generated, or terminated, the module behaves as a back-to-back user agent with the aim of the OpenSIPS B2B entities module.

In terms of the SDP media exchanged, the module can have two different modes:

  • Two way Media - in this mode, the media of a new call will be pushed towards one of the legs of an existing call. This will result in a party of the call talking with the Media Server. By default, the other participant of the call will be put on hold, but this behavior can be tuned when the new leg is originated.

  • Fork Media - the new B2B call, either originated or terminated, will just have a copy of the RTP forked by RTPProxy. In this mode, the proxied call should have had RTPProxy already engaged in the media path before the forked call starts. One can fork only one media leg, or both legs. NOTE: RTPProxy currently does not support stopping media streaming, therefore if the streaming call terminates, RTPProxy will continue streaming, even if there is no one listening on the other end.

This module can provide different functionalities and can be used in various use cases, such as:

  • Call Recording - similar to the OpenSIPS SIPREC module, it can be used to fork the RTP media to a new SIP destination, but without the SIPREC payload.

  • Call Listening - one might want to call into OpenSIPS and start listening an existing call.

  • Call Announcements - inject an announcement from a Media Server to the participants of an ongoing call.

1.2. Dependencies

1.2.1. OpenSIPS Modules

The following modules must be loaded before this module:

  • TM - Transaction module.

  • Dialog - Dialog module for keeping track of the proxied calls.

  • RTPProxy - optional, the RTPProxy module is only used when running in media forking mode.

  • B2B_ENTITIES - Back-2-Back module used form manipulating calls with the Media Server.

1.2.2. External Libraries or Applications

The following libraries or applications must be installed before running OpenSIPS with this module loaded:

  • None.

1.3. Exported Functions

1.3.1.  media_fork_to_uri(URI[, leg[, headers[, medianum]]])

Behaves as a B2B user agent client to initiate a call to a SIP URI and then stream the media to the SDP received in the 200 OK response.

Parameters:

  • URI (string) - destination where to push the current call's media

  • leg (string, optional) - the leg that will be streamed. Possible values are caller, callee and both. If missing, the direction of the indialog request is used.

  • headers (string, optional) - optional headers added to the generated request.

  • medianum (integer, optional) - the media stream that will be forked within the call. First index is 0. If missing, all media streams of that leg(s) are streamed.

This function can be used from any route.

Example 1.1. Use media_fork_to_uri() function to fork media to a Media Server

...
if (!has_totag() && is_method("INVITE"))
	media_fork_to_uri("sip:record@127.0.0.1:5080");
...
	

1.3.2.  media_fork_from_call(callid[, leg[, medianum]])

Starts streaming the media of an existing proxied call, identified by the callid parameter to the SDP in the request's body.

Parameters:

  • callid (string) - the identifier of the callid to stream/fork media from

  • leg (string, optional) - the leg that will be streamed. Possible values are caller, callee and both. If missing, both legs will be streamed.

  • medianum (integer, optional) - the media stream that will be forked within the call. First index is 0. If missing, all media streams of that leg(s) are streamed, as long as the body has enough streams.

    Note: RTPProxy does not do any media mixing, therefore you need to make sure that the INVITE has enough SDP streams to handle all the media streams selected to fork.

This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, FAILURE_ROUTE and ONREPLY_ROUTE.

NOTE: the request of this call is completely handled by the B2B engine. Therefore, after running this function, please make sure you do not relay the message further, otherwise you will run into an unexpected behavior. Best thing to do is to exit the processing after running the function.

Example 1.2. Use media_fork_from_call() function to fork all media streams of a call

...
if (!has_totag() && is_method("INVITE") && $hdr(X-CallID) != NULL)
	media_fork_from_call($hdr(X-CallID));
...
	

Example 1.3. Use media_fork_from_call() function to fork only the first caller's stream

...
if (!has_totag() && is_method("INVITE") && $hdr(X-CallID) != NULL)
	media_fork_from_call($hdr(X-CallID), "caller", 0);
...
	

1.3.3.  media_fork_pause([leg[, medianum]])

Pauses an existing RTP media streaming session. This function does not terminate the forking call, but only stops sending the RTP. It also re-invites the Media Server to inform about the change.

Parameters:

  • leg (string, optional) - the leg that will be paused. Possible values are caller, callee and both. If missing, all ongoing media sessions will be paused.

  • medianum (integer, optional) - the media stream to be paused. First index is 0. If missing, all ongoing media streams associated to the selected leg will be paused.

This function can be used from any route.

Example 1.4. Use media_fork_pause() function to temporarily stop the entire media stream of the call

...
if (has_totag() && is_method("INVITE"))
	media_fork_pause();
...
	

1.3.4.  media_fork_resume([leg[, medianum]])

Resumes the RTP media stream of an existing session/call. This function relies on the fact that a media fork session has been previously started.

Parameters:

  • leg (string, optional) - the leg that will be resumed. Possible values are caller, callee and both. If missing, all existing media legs that are stopped will be started.

  • medianum (integer, optional) - the media stream to be paused. First index is 0. If missing, all ongoing media streams associated to the selected leg will be paused.

This function can be used from any route.

Example 1.5. Use media_fork_resume() function to resume a forking previously stopped

...
if (has_totag() && is_method("INVITE"))
	media_fork_resume();
...
	

1.3.5.  media_exchange_from_uri(URI[, leg[, body[, headers[, nohold]]]])

Originates a call to the specified URI. The SDP in the response is fetched and pushed towards one of the call's legs, resulting in two way audio between the participant of the ongoing call, and the new call. By default, the other participant leg is put on hold.

Can be called for an in-dialog request, such as a re-INVITE (for example when putting an entity on hold), or for an INFO request (triggered for example by a DTMF).

Parameters:

  • URI (string) - destination used to originate the new call.

  • leg (string, optional) - the leg where the new media SDP will be pushed. Possible values are caller and callee. If missing, the module considers it is an hold re-INVITE, and exchanges the media SDP of the other leg.

  • body (string, optional) - custom body used for the generated INVITE. If missing, the body stored in the dialog associated with the involved leg will be used.

  • headers (string, optional) - optional headers added to the generated request.

  • nohold (integer, optional) - if set to true, the other participant will not be put on hold. This is useful when a new call will be generated for the other leg as well.

This function can be used from any route.

Example 1.6. Use media_exchange_from_uri() function to fetch media from a Media Server's call

...
if (has_totag() && is_method("INVITE") && is_audio_on_hold())
	media_exchange_from_uri("sip:moh@127.0.0.1:5080");
...
	

1.3.6.  media_exchange_to_call(callid[, leg[, nohold]])

Pushes the SDP of a new call received in an existing proxied call, resulting in two-way audio between a Media Server that originated the call, and the existing participant of the ongoing proxied call.

Parameters:

  • callid (string) - the identifier of the callid to exchange media.

  • leg (string) - the leg that will be streamed. Possible values are caller and callee.

  • nohold (integer, optional) - if set to true, the other participant will not be put on hold. This is useful when a new call will be generated for the other leg as well.

This function can be used from REQUEST_ROUTE, BRANCH_ROUTE, FAILURE_ROUTE and ONREPLY_ROUTE.

NOTE: the request of this call is completely handled by the B2B engine. Therefore, after running this function, please make sure you do not relay the message further, otherwise you will run into an unexpected behavior. Best thing to do is to exit the processing after running the function.

Example 1.7. Use media_exchange_to_call() function to make an announcement

...
if (!has_totag() && is_method("INVITE") && $hdr(X-CallID) != NULL)
	media_exchange_to_call($hdr(X-CallID), "caller");
...
	

1.3.7.  media_terminate([leg[, nohold]])

Terminates an ongoing media session exchange, whether the media is only streamed, or two way audio is flowing. If the participant leg is involved in a different media exchange, the current leg is put on hold.

Parameters:

  • leg (string, optional) - the leg to terminate the media exchange. Possible values are caller and callee. If missing, the direction of the indialog request is used.

  • nohold (integer, optional) - if set to true, and the other participant is involved in a different media exchange, the current leg is no longer put on hold. Note: if the request that terminates the media exchange is a re-INVITE within the dialog, this function will not un-hold the other leg, as the re-INVITE itself should be relayed further to do that. This behavior can be changed by explicitly setting the nohold parameter

This function can be used from any route.

Example 1.8. Use media_terminate() function to terminate an announcement

...
if (has_totag() && is_method("INVITE") && !is_audio_on_hold())
	media_terminate();
...
	

1.3.8.  media_handle_indialog()

Searches for an existing media session started for any leg, and if there is ongoing session found, it performs additional logic for handling that request. For example, if media has been started in forking mode, and the INVITE is for activating on-hold, then the function will also pause the forked stream.

Depending on the return code of this function, one has to perform additional logic in the script. Possible return codes are:

  • 1 - indicates that the message has been handled, but there's no additional tasks to be performed in the script.

  • -1 - indicates that there is no ongoing media exchange or fork happening for that call, or that there was no additional logic to do for that request.

  • -2 - indicates that all additional handling of the request was performed, and that the request should not be forwarded to the user agent, but instead it should be dropped.

  • -3 - signals an internal error.

This function can be used from REQUEST_ROUTE, BRANCH_ROUTE and ONREPLY_ROUTE.

Example 1.9. Use media_terminate() function to terminate an announcement

...
if (has_totag() && loose_route()) {
	# handling sequential
	media_handle_indialog();
	switch ($rc) {
	case -2:
		drop;
	case -1:
		xlog("no ongoing media session for $ci!\n");
	case 1:
		break;
}
...
	

1.4. Exported MI Functions

1.4.1.  media_fork_from_call_to_uri

MI command that has the same behavior as media_fork_to_uri(), only that the triggering is not script driven, but exterior driven. Useful for starting listening a call.

Name: media_fork_from_call_to_uri

Parameters

  • callid (string) - the callid of the dialog that will have its RTP streamed to the new call towards the Media Server

  • uri (string) - the destination URI of the new call

  • leg (string, optional) - indicates the participant leg that will have its RTP streamed in the new call. Possible values are caller, callee or both. If missing, both media streams are forked

  • headers (string, optional) - extra headers to add to the outgoing request

  • medianum (integer, optional) - the media stream that will be forked within the call. First index is 0. If missing, all media streams of that leg(s) are streamed.

MI FIFO Command Format:

# start streaming a callid to record media server
opensips-cli -x mi media_fork_from_call_to_uri \
	callid=c6fdb0f9-47dc-495d-8d38-0f37e836a531 \
	uri=sip:record@127.0.0.1:5080
		

1.4.2.  media_exchange_from_call_to_uri

MI command that has the same behavior as media_exchange_from_uri(), only that the triggering is not script driven, but exterior driven. Useful for injecting media announcements during a call.

Name: media_exchange_from_call_to_uri

Parameters

  • callid (string) - the callid of the dialog that will have it's leg mixed with the new call to the Media Server

  • uri (string) - the destination URI of the new call

  • leg (string) - indicates the participant that will have its media pined into the new call. Possible values are caller and callee.

  • headers (string, optional) - extra headers to add to the outgoing request

  • nohold (integer, optional) - if set to a non-zero value, the module avoids putting the other participant on hold when the media exchanging starts

MI FIFO Command Format:

# start playing back an annoucement to caller
opensips-cli -x mi media_exchange_from_call_to_uri \
	callid=c6fdb0f9-47dc-495d-8d38-0f37e836a531 \
	uri=sip:announcement@127.0.0.1:5080 \
	leg=caller
		

1.4.3.  media_exchange_from_call_to_uri_body

MI command that does the same thing as the media_exchange_from_call_to_uri MI function, but also allows you to specify a custom body in the outgoing request. The body has to be specified in the mandatory body parameter, all the other parameters being the same as the ones of media_exchange_from_call_to_uri.

1.4.4.  media_terminate

MI command to terminate an ongoing media exchange.

Name: media_terminate

Parameters

  • callid (string) - the callid of the dialog that will have the media exchange terminated.

  • leg (string, optional) - the leg for whom to terminate the media exchange. Accepted values are caller, callee and both. If missing, all media sessions are terminated.

  • nohold (integer, optional) - if specified and has a non-zero value, the leg that is being terminated is not put on hold if the other participant still has an ongoing media session.

MI FIFO Command Format:

# terminate a caller announcement
opensips-cli -x mi media_terminate \
	callid=c6fdb0f9-47dc-495d-8d38-0f37e836a531 \
	leg=caller
		

Chapter 2. Contributors

2.1. By Commit Statistics

Table 2.1. Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)

 NameDevScoreCommitsLines ++Lines --
1. Razvan Crainea (@razvancrainea)1175156421189
2. Vlad Patrascu (@rvlad-patrascu)641911
3. Zero King (@l2dy)3111

(1) DevScore = author_commits + author_lines_added / (project_lines_added / project_commits) + author_lines_deleted / (project_lines_deleted / project_commits)

(2) including any documentation-related commits, excluding merge commits. Regarding imported patches/code, we do our best to count the work on behalf of the proper owner, as per the "fix_authors" and "mod_renames" arrays in opensips/doc/build-contrib.sh. If you identify any patches/commits which do not get properly attributed to you, please submit a pull request which extends "fix_authors" and/or "mod_renames".

(3) ignoring whitespace edits, renamed files and auto-generated files

2.2. By Commit Activity

Table 2.2. Most recently active contributors(1) to this module

 NameCommit Activity
1. Razvan Crainea (@razvancrainea)Feb 2020 - Feb 2023
2. Vlad Patrascu (@rvlad-patrascu)Mar 2020 - Jul 2021
3. Zero King (@l2dy)Mar 2020 - Mar 2020

(1) including any documentation-related commits, excluding merge commits

Chapter 3. Documentation

3.1. Contributors

Last edited by: Razvan Crainea (@razvancrainea).

Documentation Copyrights:

Copyright © 2020 www.opensips-solutions.com