diff --git a/CHANGES b/CHANGES index 608a4a4b33b3176baddd114bee3227dc3f4afc7e..e799f71ef8b378fb22e4d0aa9eaa0141304f9a36 100644 --- a/CHANGES +++ b/CHANGES @@ -135,6 +135,32 @@ chan_iax2 seconds. Setting this to a higher value may help in lagged networks or those experiencing high packet loss. +chan_rtp (was chan_multicast_rtp) +------------------ + * Added unicast RTP support and renamed chan_multicast_rtp to chan_rtp. + + * The format for dialing a unicast RTP channel is: + UnicastRTP/<destination-addr>[/[<options>]] + Where <destination-addr> is something like '127.0.0.1:5060'. + Where <options> are in standard Asterisk flag options format: + c(<codec>) - Specify which codec/format to use such as 'ulaw'. + e(<engine>) - Specify which RTP engine to use such as 'asterisk'. + + * New options were added for a multicast RTP channel. The format for + dialing a multicast RTP channel is: + MulticastRTP/<type>/<destination-addr>[/[<control-addr>][/[<options>]]] + Where <type> can be either 'basic' or 'linksys'. + Where <destination-addr> is something like '224.0.0.3:5060'. + Where <control-addr> is something like '127.0.0.1:5060'. + Where <options> are in standard Asterisk flag options format: + c(<codec>) - Specify which codec/format to use such as 'ulaw'. + i(<address>) - Specify the interface address from which multicast RTP + is sent. + l(<enable>) - Set whether packets are looped back to the sender. The + enable value can be 0 to set looping to off and non-zero to set + looping on. + t(<ttl>) - Set the time-to-live (TTL) value for multicast packets. + chan_sip ------------------ * New 'rtpbindaddr' global setting. This allows a user to define which diff --git a/channels/chan_rtp.c b/channels/chan_rtp.c index 093602823d4d865ec4ff45114b9ceb32f3541773..0fe66bd2092a0e121770c606c35a98bf5e5345ef 100644 --- a/channels/chan_rtp.c +++ b/channels/chan_rtp.c @@ -176,7 +176,7 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo fmt = ast_format_cap_get_format(cap, 0); } if (!fmt) { - ast_log(LOG_ERROR, "No format available for sending RTP to '%s'\n", + ast_log(LOG_ERROR, "No codec available for sending RTP to '%s'\n", args.destination); goto failure; } @@ -230,6 +230,25 @@ failure: return NULL; } +enum { + OPT_RTP_CODEC = (1 << 0), + OPT_RTP_ENGINE = (1 << 1), +}; + +enum { + OPT_ARG_RTP_CODEC, + OPT_ARG_RTP_ENGINE, + /* note: this entry _MUST_ be the last one in the enum */ + OPT_ARG_ARRAY_SIZE +}; + +AST_APP_OPTIONS(unicast_rtp_options, BEGIN_OPTIONS + /*! Set the codec to be used for unicast RTP */ + AST_APP_OPTION_ARG('c', OPT_RTP_CODEC, OPT_ARG_RTP_CODEC), + /*! Set the RTP engine to use for unicast RTP */ + AST_APP_OPTION_ARG('e', OPT_RTP_ENGINE, OPT_ARG_RTP_ENGINE), +END_OPTIONS ); + /*! \brief Function called when we should prepare to call the unicast destination */ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause) { @@ -240,11 +259,13 @@ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_form struct ast_channel *chan; struct ast_format_cap *caps = NULL; struct ast_format *fmt = NULL; + const char *engine_name; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(destination); - AST_APP_ARG(engine); - AST_APP_ARG(format); + AST_APP_ARG(options); ); + struct ast_flags opts = { 0, }; + char *opt_args[OPT_ARG_ARRAY_SIZE]; if (ast_strlen_zero(data)) { ast_log(LOG_ERROR, "Destination is required for the 'UnicastRTP' channel\n"); @@ -262,17 +283,26 @@ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_form goto failure; } - if (!ast_strlen_zero(args.format)) { - fmt = ast_format_cache_get(args.format); + if (!ast_strlen_zero(args.options) + && ast_app_parse_options(unicast_rtp_options, &opts, opt_args, + ast_strdupa(args.options))) { + ast_log(LOG_ERROR, "'UnicastRTP' channel options '%s' parse error\n", + args.options); + goto failure; + } + + if (ast_test_flag(&opts, OPT_RTP_CODEC) + && !ast_strlen_zero(opt_args[OPT_ARG_RTP_CODEC])) { + fmt = ast_format_cache_get(opt_args[OPT_ARG_RTP_CODEC]); if (!fmt) { - ast_log(LOG_ERROR, "Format '%s' not found for sending RTP to '%s'\n", - args.format, args.destination); + ast_log(LOG_ERROR, "Codec '%s' not found for sending RTP to '%s'\n", + opt_args[OPT_ARG_RTP_CODEC], args.destination); goto failure; } } else { fmt = ast_format_cap_get_format(cap, 0); if (!fmt) { - ast_log(LOG_ERROR, "No format available for sending RTP to '%s'\n", + ast_log(LOG_ERROR, "No codec available for sending RTP to '%s'\n", args.destination); goto failure; } @@ -283,12 +313,15 @@ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_form goto failure; } + engine_name = S_COR(ast_test_flag(&opts, OPT_RTP_ENGINE), + opt_args[OPT_ARG_RTP_ENGINE], NULL); + ast_ouraddrfor(&address, &local_address); - instance = ast_rtp_instance_new(args.engine, NULL, &local_address, NULL); + instance = ast_rtp_instance_new(engine_name, NULL, &local_address, NULL); if (!instance) { ast_log(LOG_ERROR, "Could not create %s RTP instance for sending media to '%s'\n", - S_OR(args.engine, "default"), args.destination); + S_OR(engine_name, "default"), args.destination); goto failure; }