2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2008, Digium, Inc.
6 * Joshua Colp <jcolp@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Pluggable RTP Architecture
23 * \author Joshua Colp <jcolp@digium.com>
27 <support_level>core</support_level>
31 <managerEvent language="en_US" name="RTCPSent">
32 <managerEventInstance class="EVENT_FLAG_REPORTING">
33 <synopsis>Raised when an RTCP packet is sent.</synopsis>
36 <parameter name="SSRC">
37 <para>The SSRC identifier for our stream</para>
40 <para>The type of packet for this RTCP report.</para>
42 <enum name="200(SR)"/>
43 <enum name="201(RR)"/>
47 <para>The address the report is sent to.</para>
49 <parameter name="ReportCount">
50 <para>The number of reports that were sent.</para>
51 <para>The report count determines the number of ReportX headers in
52 the message. The X for each set of report headers will range from 0 to
53 <literal>ReportCount - 1</literal>.</para>
55 <parameter name="SentNTP" required="false">
56 <para>The time the sender generated the report. Only valid when
57 PT is <literal>200(SR)</literal>.</para>
59 <parameter name="SentRTP" required="false">
60 <para>The sender's last RTP timestamp. Only valid when PT is
61 <literal>200(SR)</literal>.</para>
63 <parameter name="SentPackets" required="false">
64 <para>The number of packets the sender has sent. Only valid when PT
65 is <literal>200(SR)</literal>.</para>
67 <parameter name="SentOctets" required="false">
68 <para>The number of bytes the sender has sent. Only valid when PT is
69 <literal>200(SR)</literal>.</para>
71 <parameter name="ReportXSourceSSRC">
72 <para>The SSRC for the source of this report block.</para>
74 <parameter name="ReportXFractionLost">
75 <para>The fraction of RTP data packets from <literal>ReportXSourceSSRC</literal>
76 lost since the previous SR or RR report was sent.</para>
78 <parameter name="ReportXCumulativeLost">
79 <para>The total number of RTP data packets from <literal>ReportXSourceSSRC</literal>
80 lost since the beginning of reception.</para>
82 <parameter name="ReportXHighestSequence">
83 <para>The highest sequence number received in an RTP data packet from
84 <literal>ReportXSourceSSRC</literal>.</para>
86 <parameter name="ReportXSequenceNumberCycles">
87 <para>The number of sequence number cycles seen for the RTP data
88 received from <literal>ReportXSourceSSRC</literal>.</para>
90 <parameter name="ReportXIAJitter">
91 <para>An estimate of the statistical variance of the RTP data packet
92 interarrival time, measured in timestamp units.</para>
94 <parameter name="ReportXLSR">
95 <para>The last SR timestamp received from <literal>ReportXSourceSSRC</literal>.
96 If no SR has been received from <literal>ReportXSourceSSRC</literal>,
99 <parameter name="ReportXDLSR">
100 <para>The delay, expressed in units of 1/65536 seconds, between
101 receiving the last SR packet from <literal>ReportXSourceSSRC</literal>
102 and sending this report.</para>
105 </managerEventInstance>
107 <managerEvent language="en_US" name="RTCPReceived">
108 <managerEventInstance class="EVENT_FLAG_REPORTING">
109 <synopsis>Raised when an RTCP packet is received.</synopsis>
112 <parameter name="SSRC">
113 <para>The SSRC identifier for the remote system</para>
115 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='PT'])" />
116 <parameter name="From">
117 <para>The address the report was received from.</para>
119 <parameter name="RTT">
120 <para>Calculated Round-Trip Time in seconds</para>
122 <parameter name="ReportCount">
123 <para>The number of reports that were received.</para>
124 <para>The report count determines the number of ReportX headers in
125 the message. The X for each set of report headers will range from 0 to
126 <literal>ReportCount - 1</literal>.</para>
128 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentNTP'])" />
129 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentRTP'])" />
130 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentPackets'])" />
131 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[@name='SentOctets'])" />
132 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RTCPSent']/managerEventInstance/syntax/parameter[contains(@name, 'ReportX')])" />
134 </managerEventInstance>
138 #include "asterisk.h"
140 ASTERISK_REGISTER_FILE()
144 #include "asterisk/channel.h"
145 #include "asterisk/frame.h"
146 #include "asterisk/module.h"
147 #include "asterisk/rtp_engine.h"
148 #include "asterisk/manager.h"
149 #include "asterisk/options.h"
150 #include "asterisk/astobj2.h"
151 #include "asterisk/pbx.h"
152 #include "asterisk/translate.h"
153 #include "asterisk/netsock2.h"
154 #include "asterisk/_private.h"
155 #include "asterisk/framehook.h"
156 #include "asterisk/stasis.h"
157 #include "asterisk/json.h"
158 #include "asterisk/stasis_channels.h"
160 struct ast_srtp_res *res_srtp = NULL;
161 struct ast_srtp_policy_res *res_srtp_policy = NULL;
163 /*! Structure that represents an RTP session (instance) */
164 struct ast_rtp_instance {
165 /*! Engine that is handling this RTP instance */
166 struct ast_rtp_engine *engine;
167 /*! Data unique to the RTP engine */
169 /*! RTP properties that have been set and their value */
170 int properties[AST_RTP_PROPERTY_MAX];
171 /*! Address that we are expecting RTP to come in to */
172 struct ast_sockaddr local_address;
173 /*! The original source address */
174 struct ast_sockaddr requested_target_address;
175 /*! Address that we are sending RTP to */
176 struct ast_sockaddr incoming_source_address;
177 /*! Instance that we are bridged to if doing remote or local bridging */
178 struct ast_rtp_instance *bridged;
179 /*! Payload and packetization information */
180 struct ast_rtp_codecs codecs;
181 /*! RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */
183 /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
185 /*! RTP keepalive interval */
187 /*! Glue currently in use */
188 struct ast_rtp_glue *glue;
189 /*! SRTP info associated with the instance */
190 struct ast_srtp *srtp;
191 /*! Channel unique ID */
192 char channel_uniqueid[AST_MAX_UNIQUEID];
195 /*! List of RTP engines that are currently registered */
196 static AST_RWLIST_HEAD_STATIC(engines, ast_rtp_engine);
198 /*! List of RTP glues */
199 static AST_RWLIST_HEAD_STATIC(glues, ast_rtp_glue);
201 #define MAX_RTP_MIME_TYPES 128
203 /*! The following array defines the MIME Media type (and subtype) for each
204 of our codecs, or RTP-specific data type. */
205 static struct ast_rtp_mime_type {
206 /*! \brief A mapping object between the Asterisk codec and this RTP payload */
207 struct ast_rtp_payload_type payload_type;
208 /*! \brief The media type */
210 /*! \brief The format type */
212 /*! \brief Expected sample rate of the /c subtype */
213 unsigned int sample_rate;
214 } ast_rtp_mime_types[128]; /* This will Likely not need to grow any time soon. */
215 static ast_rwlock_t mime_types_lock;
216 static int mime_types_len = 0;
219 * \brief Mapping between Asterisk codecs and rtp payload types
221 * Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
222 * also, our own choices for dynamic payload types. This is our master
223 * table for transmission
225 * See http://www.iana.org/assignments/rtp-parameters for a list of
228 static struct ast_rtp_payload_type static_RTP_PT[AST_RTP_MAX_PT];
229 static ast_rwlock_t static_RTP_PT_lock;
231 /*! \brief \ref stasis topic for RTP related messages */
232 static struct stasis_topic *rtp_topic;
235 /*! \internal \brief Destructor for \c ast_rtp_payload_type */
236 static void rtp_payload_type_dtor(void *obj)
238 struct ast_rtp_payload_type *payload = obj;
240 ao2_cleanup(payload->format);
243 struct ast_rtp_payload_type *ast_rtp_engine_alloc_payload_type(void)
245 struct ast_rtp_payload_type *payload;
247 payload = ao2_alloc(sizeof(*payload), rtp_payload_type_dtor);
252 int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
254 struct ast_rtp_engine *current_engine;
256 /* Perform a sanity check on the engine structure to make sure it has the basics */
257 if (ast_strlen_zero(engine->name) || !engine->new || !engine->destroy || !engine->write || !engine->read) {
258 ast_log(LOG_WARNING, "RTP Engine '%s' failed sanity check so it was not registered.\n", !ast_strlen_zero(engine->name) ? engine->name : "Unknown");
262 /* Link owner module to the RTP engine for reference counting purposes */
263 engine->mod = module;
265 AST_RWLIST_WRLOCK(&engines);
267 /* Ensure that no two modules with the same name are registered at the same time */
268 AST_RWLIST_TRAVERSE(&engines, current_engine, entry) {
269 if (!strcmp(current_engine->name, engine->name)) {
270 ast_log(LOG_WARNING, "An RTP engine with the name '%s' has already been registered.\n", engine->name);
271 AST_RWLIST_UNLOCK(&engines);
276 /* The engine survived our critique. Off to the list it goes to be used */
277 AST_RWLIST_INSERT_TAIL(&engines, engine, entry);
279 AST_RWLIST_UNLOCK(&engines);
281 ast_verb(2, "Registered RTP engine '%s'\n", engine->name);
286 int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
288 struct ast_rtp_engine *current_engine = NULL;
290 AST_RWLIST_WRLOCK(&engines);
292 if ((current_engine = AST_RWLIST_REMOVE(&engines, engine, entry))) {
293 ast_verb(2, "Unregistered RTP engine '%s'\n", engine->name);
296 AST_RWLIST_UNLOCK(&engines);
298 return current_engine ? 0 : -1;
301 int ast_rtp_glue_register2(struct ast_rtp_glue *glue, struct ast_module *module)
303 struct ast_rtp_glue *current_glue = NULL;
305 if (ast_strlen_zero(glue->type)) {
311 AST_RWLIST_WRLOCK(&glues);
313 AST_RWLIST_TRAVERSE(&glues, current_glue, entry) {
314 if (!strcasecmp(current_glue->type, glue->type)) {
315 ast_log(LOG_WARNING, "RTP glue with the name '%s' has already been registered.\n", glue->type);
316 AST_RWLIST_UNLOCK(&glues);
321 AST_RWLIST_INSERT_TAIL(&glues, glue, entry);
323 AST_RWLIST_UNLOCK(&glues);
325 ast_verb(2, "Registered RTP glue '%s'\n", glue->type);
330 int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
332 struct ast_rtp_glue *current_glue = NULL;
334 AST_RWLIST_WRLOCK(&glues);
336 if ((current_glue = AST_RWLIST_REMOVE(&glues, glue, entry))) {
337 ast_verb(2, "Unregistered RTP glue '%s'\n", glue->type);
340 AST_RWLIST_UNLOCK(&glues);
342 return current_glue ? 0 : -1;
345 static void instance_destructor(void *obj)
347 struct ast_rtp_instance *instance = obj;
349 /* Pass us off to the engine to destroy */
350 if (instance->data && instance->engine->destroy(instance)) {
351 ast_debug(1, "Engine '%s' failed to destroy RTP instance '%p'\n", instance->engine->name, instance);
355 if (instance->srtp) {
356 res_srtp->destroy(instance->srtp);
359 ast_rtp_codecs_payloads_destroy(&instance->codecs);
361 /* Drop our engine reference */
362 ast_module_unref(instance->engine->mod);
364 ast_debug(1, "Destroyed RTP instance '%p'\n", instance);
367 int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
369 ao2_ref(instance, -1);
374 struct ast_rtp_instance *ast_rtp_instance_new(const char *engine_name,
375 struct ast_sched_context *sched, const struct ast_sockaddr *sa,
378 struct ast_sockaddr address = {{0,}};
379 struct ast_rtp_instance *instance = NULL;
380 struct ast_rtp_engine *engine = NULL;
382 AST_RWLIST_RDLOCK(&engines);
384 /* If an engine name was specified try to use it or otherwise use the first one registered */
385 if (!ast_strlen_zero(engine_name)) {
386 AST_RWLIST_TRAVERSE(&engines, engine, entry) {
387 if (!strcmp(engine->name, engine_name)) {
392 engine = AST_RWLIST_FIRST(&engines);
395 /* If no engine was actually found bail out now */
397 ast_log(LOG_ERROR, "No RTP engine was found. Do you have one loaded?\n");
398 AST_RWLIST_UNLOCK(&engines);
402 /* Bump up the reference count before we return so the module can not be unloaded */
403 ast_module_ref(engine->mod);
405 AST_RWLIST_UNLOCK(&engines);
407 /* Allocate a new RTP instance */
408 if (!(instance = ao2_alloc(sizeof(*instance), instance_destructor))) {
409 ast_module_unref(engine->mod);
412 instance->engine = engine;
413 ast_sockaddr_copy(&instance->local_address, sa);
414 ast_sockaddr_copy(&address, sa);
416 if (ast_rtp_codecs_payloads_initialize(&instance->codecs)) {
417 ao2_ref(instance, -1);
421 ast_debug(1, "Using engine '%s' for RTP instance '%p'\n", engine->name, instance);
423 /* And pass it off to the engine to setup */
424 if (instance->engine->new(instance, sched, &address, data)) {
425 ast_debug(1, "Engine '%s' failed to setup RTP instance '%p'\n", engine->name, instance);
426 ao2_ref(instance, -1);
430 ast_debug(1, "RTP instance '%p' is setup and ready to go\n", instance);
435 const char *ast_rtp_instance_get_channel_id(struct ast_rtp_instance *instance)
437 return instance->channel_uniqueid;
440 void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
442 ast_copy_string(instance->channel_uniqueid, uniqueid, sizeof(instance->channel_uniqueid));
445 void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
447 instance->data = data;
450 void *ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
452 return instance->data;
455 int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
457 return instance->engine->write(instance, frame);
460 struct ast_frame *ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
462 return instance->engine->read(instance, rtcp);
465 int ast_rtp_instance_set_local_address(struct ast_rtp_instance *instance,
466 const struct ast_sockaddr *address)
468 ast_sockaddr_copy(&instance->local_address, address);
472 int ast_rtp_instance_set_incoming_source_address(struct ast_rtp_instance *instance,
473 const struct ast_sockaddr *address)
475 ast_sockaddr_copy(&instance->incoming_source_address, address);
479 if (instance->engine->remote_address_set) {
480 instance->engine->remote_address_set(instance, &instance->incoming_source_address);
486 int ast_rtp_instance_set_requested_target_address(struct ast_rtp_instance *instance,
487 const struct ast_sockaddr *address)
489 ast_sockaddr_copy(&instance->requested_target_address, address);
491 return ast_rtp_instance_set_incoming_source_address(instance, address);
494 int ast_rtp_instance_get_and_cmp_local_address(struct ast_rtp_instance *instance,
495 struct ast_sockaddr *address)
497 if (ast_sockaddr_cmp(address, &instance->local_address) != 0) {
498 ast_sockaddr_copy(address, &instance->local_address);
505 void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance,
506 struct ast_sockaddr *address)
508 ast_sockaddr_copy(address, &instance->local_address);
511 int ast_rtp_instance_get_and_cmp_requested_target_address(struct ast_rtp_instance *instance,
512 struct ast_sockaddr *address)
514 if (ast_sockaddr_cmp(address, &instance->requested_target_address) != 0) {
515 ast_sockaddr_copy(address, &instance->requested_target_address);
522 void ast_rtp_instance_get_incoming_source_address(struct ast_rtp_instance *instance,
523 struct ast_sockaddr *address)
525 ast_sockaddr_copy(address, &instance->incoming_source_address);
528 void ast_rtp_instance_get_requested_target_address(struct ast_rtp_instance *instance,
529 struct ast_sockaddr *address)
531 ast_sockaddr_copy(address, &instance->requested_target_address);
534 void ast_rtp_instance_set_extended_prop(struct ast_rtp_instance *instance, int property, void *value)
536 if (instance->engine->extended_prop_set) {
537 instance->engine->extended_prop_set(instance, property, value);
541 void *ast_rtp_instance_get_extended_prop(struct ast_rtp_instance *instance, int property)
543 if (instance->engine->extended_prop_get) {
544 return instance->engine->extended_prop_get(instance, property);
550 void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
552 instance->properties[property] = value;
554 if (instance->engine->prop_set) {
555 instance->engine->prop_set(instance, property, value);
559 int ast_rtp_instance_get_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property)
561 return instance->properties[property];
564 struct ast_rtp_codecs *ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
566 return &instance->codecs;
569 int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
574 ast_rwlock_init(&codecs->codecs_lock);
575 res = AST_VECTOR_INIT(&codecs->payloads, AST_RTP_MAX_PT);
580 void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
584 for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
585 struct ast_rtp_payload_type *type;
587 type = AST_VECTOR_GET(&codecs->payloads, i);
588 ao2_t_cleanup(type, "destroying ast_rtp_codec");
590 AST_VECTOR_FREE(&codecs->payloads);
592 ast_rwlock_destroy(&codecs->codecs_lock);
595 void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
597 ast_rtp_codecs_payloads_destroy(codecs);
599 if (instance && instance->engine && instance->engine->payload_set) {
601 for (i = 0; i < AST_RTP_MAX_PT; i++) {
602 instance->engine->payload_set(instance, i, 0, NULL, 0);
606 ast_rtp_codecs_payloads_initialize(codecs);
609 void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
613 ast_rwlock_rdlock(&src->codecs_lock);
614 ast_rwlock_wrlock(&dest->codecs_lock);
616 for (i = 0; i < AST_VECTOR_SIZE(&src->payloads); i++) {
617 struct ast_rtp_payload_type *type;
619 type = AST_VECTOR_GET(&src->payloads, i);
623 if (i < AST_VECTOR_SIZE(&dest->payloads)) {
624 ao2_t_cleanup(AST_VECTOR_GET(&dest->payloads, i), "cleaning up vector element about to be replaced");
626 ast_debug(2, "Copying payload %d (%p) from %p to %p\n", i, type, src, dest);
628 AST_VECTOR_INSERT(&dest->payloads, i, type);
630 if (instance && instance->engine && instance->engine->payload_set) {
631 instance->engine->payload_set(instance, i, type->asterisk_format, type->format, type->rtp_code);
634 dest->framing = src->framing;
635 ast_rwlock_unlock(&dest->codecs_lock);
636 ast_rwlock_unlock(&src->codecs_lock);
639 void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
641 struct ast_rtp_payload_type *new_type;
643 new_type = ast_rtp_engine_alloc_payload_type();
648 ast_rwlock_rdlock(&static_RTP_PT_lock);
649 if (payload < 0 || payload >= AST_RTP_MAX_PT) {
650 ast_rwlock_unlock(&static_RTP_PT_lock);
654 ast_rwlock_wrlock(&codecs->codecs_lock);
655 if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
656 ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, payload), "cleaning up replaced payload type");
659 new_type->asterisk_format = static_RTP_PT[payload].asterisk_format;
660 new_type->rtp_code = static_RTP_PT[payload].rtp_code;
661 new_type->payload = payload;
662 new_type->format = ao2_bump(static_RTP_PT[payload].format);
664 ast_debug(1, "Setting payload %d (%p) based on m type on %p\n", payload, new_type, codecs);
665 AST_VECTOR_INSERT(&codecs->payloads, payload, new_type);
667 if (instance && instance->engine && instance->engine->payload_set) {
668 instance->engine->payload_set(instance, payload, new_type->asterisk_format, new_type->format, new_type->rtp_code);
671 ast_rwlock_unlock(&codecs->codecs_lock);
672 ast_rwlock_unlock(&static_RTP_PT_lock);
675 int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt,
676 char *mimetype, char *mimesubtype,
677 enum ast_rtp_options options,
678 unsigned int sample_rate)
683 ast_rwlock_rdlock(&mime_types_lock);
684 if (pt < 0 || pt >= AST_RTP_MAX_PT) {
685 ast_rwlock_unlock(&mime_types_lock);
686 return -1; /* bogus payload type */
689 ast_rwlock_wrlock(&codecs->codecs_lock);
690 for (i = 0; i < mime_types_len; ++i) {
691 const struct ast_rtp_mime_type *t = &ast_rtp_mime_types[i];
692 struct ast_rtp_payload_type *new_type;
694 if (strcasecmp(mimesubtype, t->subtype)) {
698 if (strcasecmp(mimetype, t->type)) {
702 /* if both sample rates have been supplied, and they don't match,
703 * then this not a match; if one has not been supplied, then the
704 * rates are not compared */
705 if (sample_rate && t->sample_rate &&
706 (sample_rate != t->sample_rate)) {
712 new_type = ast_rtp_engine_alloc_payload_type();
717 if (pt < AST_VECTOR_SIZE(&codecs->payloads)) {
718 ao2_t_cleanup(AST_VECTOR_GET(&codecs->payloads, pt), "cleaning up replaced payload type");
721 new_type->payload = pt;
722 new_type->asterisk_format = t->payload_type.asterisk_format;
723 new_type->rtp_code = t->payload_type.rtp_code;
724 if ((ast_format_cmp(t->payload_type.format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) &&
725 t->payload_type.asterisk_format && (options & AST_RTP_OPT_G726_NONSTANDARD)) {
726 new_type->format = ao2_bump(ast_format_g726_aal2);
728 new_type->format = ao2_bump(t->payload_type.format);
730 AST_VECTOR_INSERT(&codecs->payloads, pt, new_type);
732 if (instance && instance->engine && instance->engine->payload_set) {
733 instance->engine->payload_set(instance, pt, new_type->asterisk_format, new_type->format, new_type->rtp_code);
738 ast_rwlock_unlock(&codecs->codecs_lock);
739 ast_rwlock_unlock(&mime_types_lock);
741 return (found ? 0 : -2);
744 int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
746 return ast_rtp_codecs_payloads_set_rtpmap_type_rate(codecs, instance, payload, mimetype, mimesubtype, options, 0);
749 void ast_rtp_codecs_payloads_unset(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
751 struct ast_rtp_payload_type *type;
753 if (payload < 0 || payload >= AST_RTP_MAX_PT) {
757 ast_debug(2, "Unsetting payload %d on %p\n", payload, codecs);
759 ast_rwlock_wrlock(&codecs->codecs_lock);
760 if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
761 type = AST_VECTOR_GET(&codecs->payloads, payload);
763 AST_VECTOR_INSERT(&codecs->payloads, payload, NULL);
766 if (instance && instance->engine && instance->engine->payload_set) {
767 instance->engine->payload_set(instance, payload, 0, NULL, 0);
770 ast_rwlock_unlock(&codecs->codecs_lock);
773 struct ast_rtp_payload_type *ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
775 struct ast_rtp_payload_type *type = NULL;
777 if (payload < 0 || payload >= AST_RTP_MAX_PT) {
781 ast_rwlock_rdlock(&codecs->codecs_lock);
782 if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
783 type = AST_VECTOR_GET(&codecs->payloads, payload);
786 ast_rwlock_unlock(&codecs->codecs_lock);
789 type = ast_rtp_engine_alloc_payload_type();
793 ast_rwlock_rdlock(&static_RTP_PT_lock);
794 type->asterisk_format = static_RTP_PT[payload].asterisk_format;
795 type->rtp_code = static_RTP_PT[payload].rtp_code;
796 type->payload = payload;
797 type->format = ao2_bump(static_RTP_PT[payload].format);
798 ast_rwlock_unlock(&static_RTP_PT_lock);
804 int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
806 struct ast_rtp_payload_type *type;
808 if (payload < 0 || payload >= AST_RTP_MAX_PT) {
812 ast_rwlock_wrlock(&codecs->codecs_lock);
813 if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
814 type = AST_VECTOR_GET(&codecs->payloads, payload);
815 if (type && type->asterisk_format) {
816 ao2_replace(type->format, format);
819 ast_rwlock_unlock(&codecs->codecs_lock);
824 struct ast_format *ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
826 struct ast_rtp_payload_type *type;
827 struct ast_format *format = NULL;
829 if (payload < 0 || payload >= AST_RTP_MAX_PT) {
833 ast_rwlock_rdlock(&codecs->codecs_lock);
834 if (payload < AST_VECTOR_SIZE(&codecs->payloads)) {
835 type = AST_VECTOR_GET(&codecs->payloads, payload);
836 if (type && type->asterisk_format) {
837 format = ao2_bump(type->format);
840 ast_rwlock_unlock(&codecs->codecs_lock);
845 void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
851 ast_rwlock_wrlock(&codecs->codecs_lock);
852 codecs->framing = framing;
853 ast_rwlock_unlock(&codecs->codecs_lock);
856 unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
858 unsigned int framing;
860 ast_rwlock_rdlock(&codecs->codecs_lock);
861 framing = codecs->framing;
862 ast_rwlock_unlock(&codecs->codecs_lock);
867 void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
871 ast_format_cap_remove_by_type(astformats, AST_MEDIA_TYPE_UNKNOWN);
874 ast_rwlock_rdlock(&codecs->codecs_lock);
875 for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
876 struct ast_rtp_payload_type *type;
878 type = AST_VECTOR_GET(&codecs->payloads, i);
883 if (type->asterisk_format) {
884 ast_format_cap_append(astformats, type->format, 0);
886 *nonastformats |= type->rtp_code;
890 if (codecs->framing) {
891 ast_format_cap_set_framing(astformats, codecs->framing);
894 ast_rwlock_unlock(&codecs->codecs_lock);
897 int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
899 struct ast_rtp_payload_type *type;
903 ast_rwlock_rdlock(&codecs->codecs_lock);
904 for (i = 0; i < AST_VECTOR_SIZE(&codecs->payloads); i++) {
905 type = AST_VECTOR_GET(&codecs->payloads, i);
910 if ((asterisk_format && format && ast_format_cmp(format, type->format) == AST_FORMAT_CMP_EQUAL)
911 || (!asterisk_format && type->rtp_code == code)) {
916 ast_rwlock_unlock(&codecs->codecs_lock);
919 ast_rwlock_rdlock(&static_RTP_PT_lock);
920 for (i = 0; i < AST_RTP_MAX_PT; i++) {
921 if (static_RTP_PT[i].asterisk_format && asterisk_format && format &&
922 (ast_format_cmp(format, static_RTP_PT[i].format) != AST_FORMAT_CMP_NOT_EQUAL)) {
925 } else if (!static_RTP_PT[i].asterisk_format && !asterisk_format &&
926 (static_RTP_PT[i].rtp_code == code)) {
931 ast_rwlock_unlock(&static_RTP_PT_lock);
937 int ast_rtp_codecs_find_payload_code(struct ast_rtp_codecs *codecs, int code)
939 struct ast_rtp_payload_type *type;
942 ast_rwlock_rdlock(&codecs->codecs_lock);
943 if (code < AST_VECTOR_SIZE(&codecs->payloads)) {
944 type = AST_VECTOR_GET(&codecs->payloads, code);
949 ast_rwlock_unlock(&codecs->codecs_lock);
954 const char *ast_rtp_lookup_mime_subtype2(const int asterisk_format, struct ast_format *format, int code, enum ast_rtp_options options)
957 const char *res = "";
959 ast_rwlock_rdlock(&mime_types_lock);
960 for (i = 0; i < mime_types_len; i++) {
961 if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
962 (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
963 if ((ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) &&
964 (options & AST_RTP_OPT_G726_NONSTANDARD)) {
968 res = ast_rtp_mime_types[i].subtype;
971 } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
972 ast_rtp_mime_types[i].payload_type.rtp_code == code) {
974 res = ast_rtp_mime_types[i].subtype;
978 ast_rwlock_unlock(&mime_types_lock);
983 unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, struct ast_format *format, int code)
986 unsigned int res = 0;
988 ast_rwlock_rdlock(&mime_types_lock);
989 for (i = 0; i < mime_types_len; ++i) {
990 if (ast_rtp_mime_types[i].payload_type.asterisk_format && asterisk_format && format &&
991 (ast_format_cmp(format, ast_rtp_mime_types[i].payload_type.format) != AST_FORMAT_CMP_NOT_EQUAL)) {
992 res = ast_rtp_mime_types[i].sample_rate;
994 } else if (!ast_rtp_mime_types[i].payload_type.asterisk_format && !asterisk_format &&
995 ast_rtp_mime_types[i].payload_type.rtp_code == code) {
996 res = ast_rtp_mime_types[i].sample_rate;
1000 ast_rwlock_unlock(&mime_types_lock);
1005 char *ast_rtp_lookup_mime_multiple2(struct ast_str *buf, struct ast_format_cap *ast_format_capability, int rtp_capability, const int asterisk_format, enum ast_rtp_options options)
1014 if (asterisk_format) {
1016 struct ast_format *tmp_fmt;
1017 for (x = 0; x < ast_format_cap_count(ast_format_capability); x++) {
1018 tmp_fmt = ast_format_cap_get_format(ast_format_capability, x);
1019 name = ast_rtp_lookup_mime_subtype2(asterisk_format, tmp_fmt, 0, options);
1020 ao2_ref(tmp_fmt, -1);
1021 ast_str_append(&buf, 0, "%s|", name);
1026 ast_str_append(&buf, 0, "0x%x (", (unsigned int) rtp_capability);
1027 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1028 if (rtp_capability & x) {
1029 name = ast_rtp_lookup_mime_subtype2(asterisk_format, NULL, x, options);
1030 ast_str_append(&buf, 0, "%s|", name);
1036 ast_str_append(&buf, 0, "%s", found ? ")" : "nothing)");
1038 return ast_str_buffer(buf);
1041 int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
1043 return instance->engine->dtmf_begin ? instance->engine->dtmf_begin(instance, digit) : -1;
1046 int ast_rtp_instance_dtmf_end(struct ast_rtp_instance *instance, char digit)
1048 return instance->engine->dtmf_end ? instance->engine->dtmf_end(instance, digit) : -1;
1050 int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
1052 return instance->engine->dtmf_end_with_duration ? instance->engine->dtmf_end_with_duration(instance, digit, duration) : -1;
1055 int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
1057 return (!instance->engine->dtmf_mode_set || instance->engine->dtmf_mode_set(instance, dtmf_mode)) ? -1 : 0;
1060 enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
1062 return instance->engine->dtmf_mode_get ? instance->engine->dtmf_mode_get(instance) : 0;
1065 void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
1067 if (instance->engine->update_source) {
1068 instance->engine->update_source(instance);
1072 void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
1074 if (instance->engine->change_source) {
1075 instance->engine->change_source(instance);
1079 int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
1081 return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
1084 void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
1086 if (instance->engine->stop) {
1087 instance->engine->stop(instance);
1091 int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
1093 return instance->engine->fd ? instance->engine->fd(instance, rtcp) : -1;
1096 struct ast_rtp_glue *ast_rtp_instance_get_glue(const char *type)
1098 struct ast_rtp_glue *glue = NULL;
1100 AST_RWLIST_RDLOCK(&glues);
1102 AST_RWLIST_TRAVERSE(&glues, glue, entry) {
1103 if (!strcasecmp(glue->type, type)) {
1108 AST_RWLIST_UNLOCK(&glues);
1114 * \brief Conditionally unref an rtp instance
1116 static void unref_instance_cond(struct ast_rtp_instance **instance)
1119 ao2_ref(*instance, -1);
1124 struct ast_rtp_instance *ast_rtp_instance_get_bridged(struct ast_rtp_instance *instance)
1126 return instance->bridged;
1129 void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged)
1131 instance->bridged = bridged;
1134 void ast_rtp_instance_early_bridge_make_compatible(struct ast_channel *c_dst, struct ast_channel *c_src)
1136 struct ast_rtp_instance *instance_dst = NULL, *instance_src = NULL,
1137 *vinstance_dst = NULL, *vinstance_src = NULL,
1138 *tinstance_dst = NULL, *tinstance_src = NULL;
1139 struct ast_rtp_glue *glue_dst, *glue_src;
1140 enum ast_rtp_glue_result audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
1141 enum ast_rtp_glue_result audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID, video_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
1142 struct ast_format_cap *cap_dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1143 struct ast_format_cap *cap_src = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1145 /* Lock both channels so we can look for the glue that binds them together */
1146 ast_channel_lock_both(c_dst, c_src);
1148 if (!cap_src || !cap_dst) {
1152 /* Grab glue that binds each channel to something using the RTP engine */
1153 if (!(glue_dst = ast_rtp_instance_get_glue(ast_channel_tech(c_dst)->type)) || !(glue_src = ast_rtp_instance_get_glue(ast_channel_tech(c_src)->type))) {
1154 ast_debug(1, "Can't find native functions for channel '%s'\n", glue_dst ? ast_channel_name(c_src) : ast_channel_name(c_dst));
1158 audio_glue_dst_res = glue_dst->get_rtp_info(c_dst, &instance_dst);
1159 video_glue_dst_res = glue_dst->get_vrtp_info ? glue_dst->get_vrtp_info(c_dst, &vinstance_dst) : AST_RTP_GLUE_RESULT_FORBID;
1161 audio_glue_src_res = glue_src->get_rtp_info(c_src, &instance_src);
1162 video_glue_src_res = glue_src->get_vrtp_info ? glue_src->get_vrtp_info(c_src, &vinstance_src) : AST_RTP_GLUE_RESULT_FORBID;
1164 /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
1165 if (video_glue_dst_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1166 audio_glue_dst_res = AST_RTP_GLUE_RESULT_FORBID;
1168 if (video_glue_src_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1169 audio_glue_src_res = AST_RTP_GLUE_RESULT_FORBID;
1171 if (audio_glue_dst_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue_dst_res == AST_RTP_GLUE_RESULT_FORBID || video_glue_dst_res == AST_RTP_GLUE_RESULT_REMOTE) && glue_dst->get_codec) {
1172 glue_dst->get_codec(c_dst, cap_dst);
1174 if (audio_glue_src_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue_src_res == AST_RTP_GLUE_RESULT_FORBID || video_glue_src_res == AST_RTP_GLUE_RESULT_REMOTE) && glue_src->get_codec) {
1175 glue_src->get_codec(c_src, cap_src);
1178 /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
1179 if (audio_glue_dst_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue_src_res != AST_RTP_GLUE_RESULT_REMOTE) {
1183 /* Make sure we have matching codecs */
1184 if (!ast_format_cap_iscompatible(cap_dst, cap_src)) {
1188 ast_rtp_codecs_payloads_copy(&instance_src->codecs, &instance_dst->codecs, instance_dst);
1190 if (vinstance_dst && vinstance_src) {
1191 ast_rtp_codecs_payloads_copy(&vinstance_src->codecs, &vinstance_dst->codecs, vinstance_dst);
1193 if (tinstance_dst && tinstance_src) {
1194 ast_rtp_codecs_payloads_copy(&tinstance_src->codecs, &tinstance_dst->codecs, tinstance_dst);
1197 if (glue_dst->update_peer(c_dst, instance_src, vinstance_src, tinstance_src, cap_src, 0)) {
1198 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n",
1199 ast_channel_name(c_dst), ast_channel_name(c_src));
1201 ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n",
1202 ast_channel_name(c_dst), ast_channel_name(c_src));
1206 ast_channel_unlock(c_dst);
1207 ast_channel_unlock(c_src);
1209 ao2_cleanup(cap_dst);
1210 ao2_cleanup(cap_src);
1212 unref_instance_cond(&instance_dst);
1213 unref_instance_cond(&instance_src);
1214 unref_instance_cond(&vinstance_dst);
1215 unref_instance_cond(&vinstance_src);
1216 unref_instance_cond(&tinstance_dst);
1217 unref_instance_cond(&tinstance_src);
1220 int ast_rtp_instance_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
1222 struct ast_rtp_instance *instance0 = NULL, *instance1 = NULL,
1223 *vinstance0 = NULL, *vinstance1 = NULL,
1224 *tinstance0 = NULL, *tinstance1 = NULL;
1225 struct ast_rtp_glue *glue0, *glue1;
1226 enum ast_rtp_glue_result audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID, video_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1227 enum ast_rtp_glue_result audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID, video_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1228 struct ast_format_cap *cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1229 struct ast_format_cap *cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1231 /* If there is no second channel just immediately bail out, we are of no use in that scenario */
1232 if (!c1 || !cap1 || !cap0) {
1238 /* Lock both channels so we can look for the glue that binds them together */
1239 ast_channel_lock_both(c0, c1);
1241 /* Grab glue that binds each channel to something using the RTP engine */
1242 if (!(glue0 = ast_rtp_instance_get_glue(ast_channel_tech(c0)->type)) || !(glue1 = ast_rtp_instance_get_glue(ast_channel_tech(c1)->type))) {
1243 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", glue0 ? ast_channel_name(c1) : ast_channel_name(c0));
1247 audio_glue0_res = glue0->get_rtp_info(c0, &instance0);
1248 video_glue0_res = glue0->get_vrtp_info ? glue0->get_vrtp_info(c0, &vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
1250 audio_glue1_res = glue1->get_rtp_info(c1, &instance1);
1251 video_glue1_res = glue1->get_vrtp_info ? glue1->get_vrtp_info(c1, &vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
1253 /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
1254 if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1255 audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
1257 if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
1258 audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
1260 if (audio_glue0_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue0_res == AST_RTP_GLUE_RESULT_FORBID || video_glue0_res == AST_RTP_GLUE_RESULT_REMOTE) && glue0->get_codec) {
1261 glue0->get_codec(c0, cap0);
1263 if (audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE && (video_glue1_res == AST_RTP_GLUE_RESULT_FORBID || video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) && glue1->get_codec) {
1264 glue1->get_codec(c1, cap1);
1267 /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
1268 if (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE || audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE) {
1272 /* Make sure we have matching codecs */
1273 if (!ast_format_cap_iscompatible(cap0, cap1)) {
1277 /* Bridge media early */
1278 if (glue0->update_peer(c0, instance1, vinstance1, tinstance1, cap1, 0)) {
1279 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", ast_channel_name(c0), c1 ? ast_channel_name(c1) : "<unspecified>");
1283 ast_channel_unlock(c0);
1284 ast_channel_unlock(c1);
1289 unref_instance_cond(&instance0);
1290 unref_instance_cond(&instance1);
1291 unref_instance_cond(&vinstance0);
1292 unref_instance_cond(&vinstance1);
1293 unref_instance_cond(&tinstance0);
1294 unref_instance_cond(&tinstance1);
1296 ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", ast_channel_name(c0), c1 ? ast_channel_name(c1) : "<unspecified>");
1301 int ast_rtp_red_init(struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
1303 return instance->engine->red_init ? instance->engine->red_init(instance, buffer_time, payloads, generations) : -1;
1306 int ast_rtp_red_buffer(struct ast_rtp_instance *instance, struct ast_frame *frame)
1308 return instance->engine->red_buffer ? instance->engine->red_buffer(instance, frame) : -1;
1311 int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
1313 return instance->engine->get_stat ? instance->engine->get_stat(instance, stats, stat) : -1;
1316 char *ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
1318 struct ast_rtp_instance_stats stats = { 0, };
1319 enum ast_rtp_instance_stat stat;
1321 /* Determine what statistics we will need to retrieve based on field passed in */
1322 if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
1323 stat = AST_RTP_INSTANCE_STAT_ALL;
1324 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
1325 stat = AST_RTP_INSTANCE_STAT_COMBINED_JITTER;
1326 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
1327 stat = AST_RTP_INSTANCE_STAT_COMBINED_LOSS;
1328 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
1329 stat = AST_RTP_INSTANCE_STAT_COMBINED_RTT;
1334 /* Attempt to actually retrieve the statistics we need to generate the quality string */
1335 if (ast_rtp_instance_get_stats(instance, &stats, stat)) {
1339 /* Now actually fill the buffer with the good information */
1340 if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY) {
1341 snprintf(buf, size, "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
1342 stats.local_ssrc, stats.remote_ssrc, stats.rxploss, stats.rxjitter, stats.rxcount, stats.txjitter, stats.txcount, stats.txploss, stats.rtt);
1343 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER) {
1344 snprintf(buf, size, "minrxjitter=%f;maxrxjitter=%f;avgrxjitter=%f;stdevrxjitter=%f;reported_minjitter=%f;reported_maxjitter=%f;reported_avgjitter=%f;reported_stdevjitter=%f;",
1345 stats.local_minjitter, stats.local_maxjitter, stats.local_normdevjitter, sqrt(stats.local_stdevjitter), stats.remote_minjitter, stats.remote_maxjitter, stats.remote_normdevjitter, sqrt(stats.remote_stdevjitter));
1346 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS) {
1347 snprintf(buf, size, "minrxlost=%f;maxrxlost=%f;avgrxlost=%f;stdevrxlost=%f;reported_minlost=%f;reported_maxlost=%f;reported_avglost=%f;reported_stdevlost=%f;",
1348 stats.local_minrxploss, stats.local_maxrxploss, stats.local_normdevrxploss, sqrt(stats.local_stdevrxploss), stats.remote_minrxploss, stats.remote_maxrxploss, stats.remote_normdevrxploss, sqrt(stats.remote_stdevrxploss));
1349 } else if (field == AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT) {
1350 snprintf(buf, size, "minrtt=%f;maxrtt=%f;avgrtt=%f;stdevrtt=%f;", stats.minrtt, stats.maxrtt, stats.normdevrtt, stats.stdevrtt);
1356 void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
1358 char quality_buf[AST_MAX_USER_FIELD];
1360 struct ast_channel *bridge = ast_channel_bridge_peer(chan);
1362 ast_channel_lock(chan);
1363 ast_channel_stage_snapshot(chan);
1364 ast_channel_unlock(chan);
1366 ast_channel_lock(bridge);
1367 ast_channel_stage_snapshot(bridge);
1368 ast_channel_unlock(bridge);
1371 quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY,
1372 quality_buf, sizeof(quality_buf));
1374 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", quality);
1376 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", quality);
1380 quality = ast_rtp_instance_get_quality(instance,
1381 AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf));
1383 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", quality);
1385 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", quality);
1389 quality = ast_rtp_instance_get_quality(instance,
1390 AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf));
1392 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", quality);
1394 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", quality);
1398 quality = ast_rtp_instance_get_quality(instance,
1399 AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf));
1401 pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", quality);
1403 pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", quality);
1407 ast_channel_lock(chan);
1408 ast_channel_stage_snapshot_done(chan);
1409 ast_channel_unlock(chan);
1411 ast_channel_lock(bridge);
1412 ast_channel_stage_snapshot_done(bridge);
1413 ast_channel_unlock(bridge);
1414 ast_channel_unref(bridge);
1418 int ast_rtp_instance_set_read_format(struct ast_rtp_instance *instance, struct ast_format *format)
1420 return instance->engine->set_read_format ? instance->engine->set_read_format(instance, format) : -1;
1423 int ast_rtp_instance_set_write_format(struct ast_rtp_instance *instance, struct ast_format *format)
1425 return instance->engine->set_write_format ? instance->engine->set_write_format(instance, format) : -1;
1428 int ast_rtp_instance_make_compatible(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_channel *peer)
1430 struct ast_rtp_glue *glue;
1431 struct ast_rtp_instance *peer_instance = NULL;
1434 if (!instance->engine->make_compatible) {
1438 ast_channel_lock(peer);
1440 if (!(glue = ast_rtp_instance_get_glue(ast_channel_tech(peer)->type))) {
1441 ast_channel_unlock(peer);
1445 glue->get_rtp_info(peer, &peer_instance);
1446 if (!peer_instance) {
1447 ast_log(LOG_ERROR, "Unable to get_rtp_info for peer type %s\n", glue->type);
1448 ast_channel_unlock(peer);
1451 if (peer_instance->engine != instance->engine) {
1452 ast_log(LOG_ERROR, "Peer engine mismatch for type %s\n", glue->type);
1453 ast_channel_unlock(peer);
1454 ao2_ref(peer_instance, -1);
1458 res = instance->engine->make_compatible(chan, instance, peer, peer_instance);
1460 ast_channel_unlock(peer);
1462 ao2_ref(peer_instance, -1);
1463 peer_instance = NULL;
1468 void ast_rtp_instance_available_formats(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result)
1470 if (instance->engine->available_formats) {
1471 instance->engine->available_formats(instance, to_endpoint, to_asterisk, result);
1472 if (ast_format_cap_count(result)) {
1477 ast_translate_available_formats(to_endpoint, to_asterisk, result);
1480 int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
1482 return instance->engine->activate ? instance->engine->activate(instance) : 0;
1485 void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance,
1486 struct ast_sockaddr *suggestion,
1487 const char *username)
1489 if (instance->engine->stun_request) {
1490 instance->engine->stun_request(instance, suggestion, username);
1494 void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
1496 instance->timeout = timeout;
1499 void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout)
1501 instance->holdtimeout = timeout;
1504 void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int interval)
1506 instance->keepalive = interval;
1509 int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
1511 return instance->timeout;
1514 int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance)
1516 return instance->holdtimeout;
1519 int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
1521 return instance->keepalive;
1524 struct ast_rtp_engine *ast_rtp_instance_get_engine(struct ast_rtp_instance *instance)
1526 return instance->engine;
1529 struct ast_rtp_glue *ast_rtp_instance_get_active_glue(struct ast_rtp_instance *instance)
1531 return instance->glue;
1534 int ast_rtp_engine_register_srtp(struct ast_srtp_res *srtp_res, struct ast_srtp_policy_res *policy_res)
1536 if (res_srtp || res_srtp_policy) {
1539 if (!srtp_res || !policy_res) {
1543 res_srtp = srtp_res;
1544 res_srtp_policy = policy_res;
1549 void ast_rtp_engine_unregister_srtp(void)
1552 res_srtp_policy = NULL;
1555 int ast_rtp_engine_srtp_is_registered(void)
1557 return res_srtp && res_srtp_policy;
1560 int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *remote_policy, struct ast_srtp_policy *local_policy)
1568 if (!instance->srtp) {
1569 res = res_srtp->create(&instance->srtp, instance, remote_policy);
1571 res = res_srtp->replace(&instance->srtp, instance, remote_policy);
1574 res = res_srtp->add_stream(instance->srtp, local_policy);
1580 struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance)
1582 return instance->srtp;
1585 int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
1587 if (instance->engine->sendcng) {
1588 return instance->engine->sendcng(instance, level);
1594 struct ast_rtp_engine_ice *ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
1596 return instance->engine->ice;
1599 struct ast_rtp_engine_dtls *ast_rtp_instance_get_dtls(struct ast_rtp_instance *instance)
1601 return instance->engine->dtls;
1604 int ast_rtp_dtls_cfg_parse(struct ast_rtp_dtls_cfg *dtls_cfg, const char *name, const char *value)
1606 if (!strcasecmp(name, "dtlsenable")) {
1607 dtls_cfg->enabled = ast_true(value) ? 1 : 0;
1608 } else if (!strcasecmp(name, "dtlsverify")) {
1609 if (!strcasecmp(value, "yes")) {
1610 dtls_cfg->verify = AST_RTP_DTLS_VERIFY_FINGERPRINT | AST_RTP_DTLS_VERIFY_CERTIFICATE;
1611 } else if (!strcasecmp(value, "fingerprint")) {
1612 dtls_cfg->verify = AST_RTP_DTLS_VERIFY_FINGERPRINT;
1613 } else if (!strcasecmp(value, "certificate")) {
1614 dtls_cfg->verify = AST_RTP_DTLS_VERIFY_CERTIFICATE;
1615 } else if (!strcasecmp(value, "no")) {
1616 dtls_cfg->verify = AST_RTP_DTLS_VERIFY_NONE;
1620 } else if (!strcasecmp(name, "dtlsrekey")) {
1621 if (sscanf(value, "%30u", &dtls_cfg->rekey) != 1) {
1624 } else if (!strcasecmp(name, "dtlscertfile")) {
1625 ast_free(dtls_cfg->certfile);
1626 dtls_cfg->certfile = ast_strdup(value);
1627 } else if (!strcasecmp(name, "dtlsprivatekey")) {
1628 ast_free(dtls_cfg->pvtfile);
1629 dtls_cfg->pvtfile = ast_strdup(value);
1630 } else if (!strcasecmp(name, "dtlscipher")) {
1631 ast_free(dtls_cfg->cipher);
1632 dtls_cfg->cipher = ast_strdup(value);
1633 } else if (!strcasecmp(name, "dtlscafile")) {
1634 ast_free(dtls_cfg->cafile);
1635 dtls_cfg->cafile = ast_strdup(value);
1636 } else if (!strcasecmp(name, "dtlscapath") || !strcasecmp(name, "dtlscadir")) {
1637 ast_free(dtls_cfg->capath);
1638 dtls_cfg->capath = ast_strdup(value);
1639 } else if (!strcasecmp(name, "dtlssetup")) {
1640 if (!strcasecmp(value, "active")) {
1641 dtls_cfg->default_setup = AST_RTP_DTLS_SETUP_ACTIVE;
1642 } else if (!strcasecmp(value, "passive")) {
1643 dtls_cfg->default_setup = AST_RTP_DTLS_SETUP_PASSIVE;
1644 } else if (!strcasecmp(value, "actpass")) {
1645 dtls_cfg->default_setup = AST_RTP_DTLS_SETUP_ACTPASS;
1647 } else if (!strcasecmp(name, "dtlsfingerprint")) {
1648 if (!strcasecmp(value, "sha-256")) {
1649 dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA256;
1650 } else if (!strcasecmp(value, "sha-1")) {
1651 dtls_cfg->hash = AST_RTP_DTLS_HASH_SHA1;
1660 void ast_rtp_dtls_cfg_copy(const struct ast_rtp_dtls_cfg *src_cfg, struct ast_rtp_dtls_cfg *dst_cfg)
1662 dst_cfg->enabled = src_cfg->enabled;
1663 dst_cfg->verify = src_cfg->verify;
1664 dst_cfg->rekey = src_cfg->rekey;
1665 dst_cfg->suite = src_cfg->suite;
1666 dst_cfg->hash = src_cfg->hash;
1667 dst_cfg->certfile = ast_strdup(src_cfg->certfile);
1668 dst_cfg->pvtfile = ast_strdup(src_cfg->pvtfile);
1669 dst_cfg->cipher = ast_strdup(src_cfg->cipher);
1670 dst_cfg->cafile = ast_strdup(src_cfg->cafile);
1671 dst_cfg->capath = ast_strdup(src_cfg->capath);
1672 dst_cfg->default_setup = src_cfg->default_setup;
1675 void ast_rtp_dtls_cfg_free(struct ast_rtp_dtls_cfg *dtls_cfg)
1677 ast_free(dtls_cfg->certfile);
1678 ast_free(dtls_cfg->pvtfile);
1679 ast_free(dtls_cfg->cipher);
1680 ast_free(dtls_cfg->cafile);
1681 ast_free(dtls_cfg->capath);
1685 * \brief Small helper routine that cleans up entry i in
1688 static void rtp_engine_static_RTP_PT_cleanup(int i)
1690 ao2_cleanup(static_RTP_PT[i].format);
1691 memset(&static_RTP_PT[i], 0, sizeof(struct ast_rtp_payload_type));
1695 * \brief Small helper routine that cleans up entry i in
1696 * \c ast_rtp_mime_types.
1698 static void rtp_engine_mime_type_cleanup(int i)
1700 ao2_cleanup(ast_rtp_mime_types[i].payload_type.format);
1701 memset(&ast_rtp_mime_types[i], 0, sizeof(struct ast_rtp_mime_type));
1704 static void set_next_mime_type(struct ast_format *format, int rtp_code, const char *type, const char *subtype, unsigned int sample_rate)
1706 int x = mime_types_len;
1707 if (ARRAY_LEN(ast_rtp_mime_types) == mime_types_len) {
1711 ast_rwlock_wrlock(&mime_types_lock);
1712 /* Make sure any previous value in ast_rtp_mime_types is cleaned up */
1713 memset(&ast_rtp_mime_types[x], 0, sizeof(struct ast_rtp_mime_type));
1715 ast_rtp_mime_types[x].payload_type.asterisk_format = 1;
1716 ast_rtp_mime_types[x].payload_type.format = ao2_bump(format);
1718 ast_rtp_mime_types[x].payload_type.rtp_code = rtp_code;
1720 ast_copy_string(ast_rtp_mime_types[x].type, type, sizeof(ast_rtp_mime_types[x].type));
1721 ast_copy_string(ast_rtp_mime_types[x].subtype, subtype, sizeof(ast_rtp_mime_types[x].subtype));
1722 ast_rtp_mime_types[x].sample_rate = sample_rate;
1724 ast_rwlock_unlock(&mime_types_lock);
1727 static void add_static_payload(int map, struct ast_format *format, int rtp_code)
1730 ast_rwlock_wrlock(&static_RTP_PT_lock);
1732 /* find next available dynamic payload slot */
1733 for (x = 96; x < 127; x++) {
1734 if (!static_RTP_PT[x].asterisk_format && !static_RTP_PT[x].rtp_code) {
1742 ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n",
1743 ast_format_get_name(format));
1744 ast_rwlock_unlock(&static_RTP_PT_lock);
1749 static_RTP_PT[map].asterisk_format = 1;
1750 static_RTP_PT[map].format = ao2_bump(format);
1752 static_RTP_PT[map].rtp_code = rtp_code;
1754 ast_rwlock_unlock(&static_RTP_PT_lock);
1757 int ast_rtp_engine_load_format(struct ast_format *format)
1759 char *codec_name = ast_strdupa(ast_format_get_name(format));
1761 codec_name = ast_str_to_upper(codec_name);
1763 set_next_mime_type(format,
1765 ast_codec_media_type2str(ast_format_get_type(format)),
1767 ast_format_get_sample_rate(format));
1768 add_static_payload(-1, format, 0);
1773 int ast_rtp_engine_unload_format(struct ast_format *format)
1778 ast_rwlock_wrlock(&static_RTP_PT_lock);
1779 /* remove everything pertaining to this format id from the lists */
1780 for (x = 0; x < AST_RTP_MAX_PT; x++) {
1781 if (ast_format_cmp(static_RTP_PT[x].format, format) == AST_FORMAT_CMP_EQUAL) {
1782 rtp_engine_static_RTP_PT_cleanup(x);
1785 ast_rwlock_unlock(&static_RTP_PT_lock);
1787 ast_rwlock_wrlock(&mime_types_lock);
1788 /* rebuild the list skipping the items matching this id */
1789 for (x = 0; x < mime_types_len; x++) {
1790 if (ast_format_cmp(ast_rtp_mime_types[x].payload_type.format, format) == AST_FORMAT_CMP_EQUAL) {
1791 rtp_engine_mime_type_cleanup(x);
1794 ast_rtp_mime_types[y] = ast_rtp_mime_types[x];
1798 ast_rwlock_unlock(&mime_types_lock);
1804 * \brief \ref stasis message payload for RTCP messages
1806 struct rtcp_message_payload {
1807 struct ast_channel_snapshot *snapshot; /*< The channel snapshot, if available */
1808 struct ast_rtp_rtcp_report *report; /*< The RTCP report */
1809 struct ast_json *blob; /*< Extra JSON data to publish */
1812 static void rtcp_message_payload_dtor(void *obj)
1814 struct rtcp_message_payload *payload = obj;
1816 ao2_cleanup(payload->report);
1817 ao2_cleanup(payload->snapshot);
1818 ast_json_unref(payload->blob);
1821 static struct ast_manager_event_blob *rtcp_report_to_ami(struct stasis_message *msg)
1823 struct rtcp_message_payload *payload = stasis_message_data(msg);
1824 RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
1825 RAII_VAR(struct ast_str *, packet_string, ast_str_create(512), ast_free);
1826 unsigned int ssrc = payload->report->ssrc;
1827 unsigned int type = payload->report->type;
1828 unsigned int report_count = payload->report->reception_report_count;
1831 if (!packet_string) {
1835 if (payload->snapshot) {
1836 channel_string = ast_manager_build_channel_state_string(payload->snapshot);
1837 if (!channel_string) {
1842 if (payload->blob) {
1844 struct ast_json *to = ast_json_object_get(payload->blob, "to");
1845 struct ast_json *from = ast_json_object_get(payload->blob, "from");
1846 struct ast_json *rtt = ast_json_object_get(payload->blob, "rtt");
1848 ast_str_append(&packet_string, 0, "To: %s\r\n", ast_json_string_get(to));
1851 ast_str_append(&packet_string, 0, "From: %s\r\n", ast_json_string_get(from));
1854 ast_str_append(&packet_string, 0, "RTT: %4.4f\r\n", ast_json_real_get(rtt));
1858 ast_str_append(&packet_string, 0, "SSRC: 0x%.8x\r\n", ssrc);
1859 ast_str_append(&packet_string, 0, "PT: %u(%s)\r\n", type, type== AST_RTP_RTCP_SR ? "SR" : "RR");
1860 ast_str_append(&packet_string, 0, "ReportCount: %u\r\n", report_count);
1861 if (type == AST_RTP_RTCP_SR) {
1862 ast_str_append(&packet_string, 0, "SentNTP: %lu.%06lu\r\n",
1863 (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec,
1864 (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec * 4096);
1865 ast_str_append(&packet_string, 0, "SentRTP: %u\r\n",
1866 payload->report->sender_information.rtp_timestamp);
1867 ast_str_append(&packet_string, 0, "SentPackets: %u\r\n",
1868 payload->report->sender_information.packet_count);
1869 ast_str_append(&packet_string, 0, "SentOctets: %u\r\n",
1870 payload->report->sender_information.octet_count);
1873 for (i = 0; i < report_count; i++) {
1874 RAII_VAR(struct ast_str *, report_string, NULL, ast_free);
1876 if (!payload->report->report_block[i]) {
1880 report_string = ast_str_create(256);
1881 if (!report_string) {
1885 ast_str_append(&report_string, 0, "Report%dSourceSSRC: 0x%.8x\r\n",
1886 i, payload->report->report_block[i]->source_ssrc);
1887 ast_str_append(&report_string, 0, "Report%dFractionLost: %d\r\n",
1888 i, payload->report->report_block[i]->lost_count.fraction);
1889 ast_str_append(&report_string, 0, "Report%dCumulativeLost: %u\r\n",
1890 i, payload->report->report_block[i]->lost_count.packets);
1891 ast_str_append(&report_string, 0, "Report%dHighestSequence: %u\r\n",
1892 i, payload->report->report_block[i]->highest_seq_no & 0xffff);
1893 ast_str_append(&report_string, 0, "Report%dSequenceNumberCycles: %u\r\n",
1894 i, payload->report->report_block[i]->highest_seq_no >> 16);
1895 ast_str_append(&report_string, 0, "Report%dIAJitter: %u\r\n",
1896 i, payload->report->report_block[i]->ia_jitter);
1897 ast_str_append(&report_string, 0, "Report%dLSR: %u\r\n",
1898 i, payload->report->report_block[i]->lsr);
1899 ast_str_append(&report_string, 0, "Report%dDLSR: %4.4f\r\n",
1900 i, ((double)payload->report->report_block[i]->dlsr) / 65536);
1901 ast_str_append(&packet_string, 0, "%s", ast_str_buffer(report_string));
1904 return ast_manager_event_blob_create(EVENT_FLAG_REPORTING,
1905 stasis_message_type(msg) == ast_rtp_rtcp_received_type() ? "RTCPReceived" : "RTCPSent",
1907 AS_OR(channel_string, ""),
1908 ast_str_buffer(packet_string));
1911 static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
1912 const struct stasis_message_sanitizer *sanitize)
1914 struct rtcp_message_payload *payload = stasis_message_data(msg);
1915 RAII_VAR(struct ast_json *, json_rtcp_report, NULL, ast_json_unref);
1916 RAII_VAR(struct ast_json *, json_rtcp_report_blocks, NULL, ast_json_unref);
1917 RAII_VAR(struct ast_json *, json_rtcp_sender_info, NULL, ast_json_unref);
1918 RAII_VAR(struct ast_json *, json_channel, NULL, ast_json_unref);
1921 json_rtcp_report_blocks = ast_json_array_create();
1922 if (!json_rtcp_report_blocks) {
1926 for (i = 0; i < payload->report->reception_report_count && payload->report->report_block[i]; i++) {
1927 struct ast_json *json_report_block;
1929 snprintf(str_lsr, sizeof(str_lsr), "%u", payload->report->report_block[i]->lsr);
1930 json_report_block = ast_json_pack("{s: i, s: i, s: i, s: i, s: i, s: s, s: i}",
1931 "source_ssrc", payload->report->report_block[i]->source_ssrc,
1932 "fraction_lost", payload->report->report_block[i]->lost_count.fraction,
1933 "packets_lost", payload->report->report_block[i]->lost_count.packets,
1934 "highest_seq_no", payload->report->report_block[i]->highest_seq_no,
1935 "ia_jitter", payload->report->report_block[i]->ia_jitter,
1937 "dlsr", payload->report->report_block[i]->dlsr);
1938 if (!json_report_block) {
1942 if (ast_json_array_append(json_rtcp_report_blocks, json_report_block)) {
1947 if (payload->report->type == AST_RTP_RTCP_SR) {
1950 snprintf(sec, sizeof(sec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec);
1951 snprintf(usec, sizeof(usec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec);
1952 json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: i, s: i, s: i}",
1953 "ntp_timestamp_sec", sec,
1954 "ntp_timestamp_usec", usec,
1955 "rtp_timestamp", payload->report->sender_information.rtp_timestamp,
1956 "packets", payload->report->sender_information.packet_count,
1957 "octets", payload->report->sender_information.octet_count);
1958 if (!json_rtcp_sender_info) {
1963 json_rtcp_report = ast_json_pack("{s: i, s: i, s: i, s: O, s: O}",
1964 "ssrc", payload->report->ssrc,
1965 "type", payload->report->type,
1966 "report_count", payload->report->reception_report_count,
1967 "sender_information", json_rtcp_sender_info ? json_rtcp_sender_info : ast_json_null(),
1968 "report_blocks", json_rtcp_report_blocks);
1969 if (!json_rtcp_report) {
1973 if (payload->snapshot) {
1974 json_channel = ast_channel_snapshot_to_json(payload->snapshot, sanitize);
1975 if (!json_channel) {
1980 return ast_json_pack("{s: O, s: O, s: O}",
1981 "channel", payload->snapshot ? json_channel : ast_json_null(),
1982 "rtcp_report", json_rtcp_report,
1983 "blob", payload->blob);
1986 static void rtp_rtcp_report_dtor(void *obj)
1989 struct ast_rtp_rtcp_report *rtcp_report = obj;
1991 for (i = 0; i < rtcp_report->reception_report_count; i++) {
1992 ast_free(rtcp_report->report_block[i]);
1996 struct ast_rtp_rtcp_report *ast_rtp_rtcp_report_alloc(unsigned int report_blocks)
1998 struct ast_rtp_rtcp_report *rtcp_report;
2000 /* Size of object is sizeof the report + the number of report_blocks * sizeof pointer */
2001 rtcp_report = ao2_alloc((sizeof(*rtcp_report) + report_blocks * sizeof(struct ast_rtp_rtcp_report_block *)),
2002 rtp_rtcp_report_dtor);
2007 void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp,
2008 struct stasis_message_type *message_type,
2009 struct ast_rtp_rtcp_report *report,
2010 struct ast_json *blob)
2012 RAII_VAR(struct rtcp_message_payload *, payload, NULL, ao2_cleanup);
2013 RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
2015 if (!message_type) {
2019 payload = ao2_alloc(sizeof(*payload), rtcp_message_payload_dtor);
2020 if (!payload || !report) {
2024 if (!ast_strlen_zero(rtp->channel_uniqueid)) {
2025 payload->snapshot = ast_channel_snapshot_get_latest(rtp->channel_uniqueid);
2028 payload->blob = blob;
2031 ao2_ref(report, +1);
2032 payload->report = report;
2034 message = stasis_message_create(message_type, payload);
2039 stasis_publish(ast_rtp_topic(), message);
2043 * @{ \brief Define RTCP/RTP message types.
2045 STASIS_MESSAGE_TYPE_DEFN(ast_rtp_rtcp_sent_type,
2046 .to_ami = rtcp_report_to_ami,
2047 .to_json = rtcp_report_to_json,);
2048 STASIS_MESSAGE_TYPE_DEFN(ast_rtp_rtcp_received_type,
2049 .to_ami = rtcp_report_to_ami,
2050 .to_json = rtcp_report_to_json,);
2053 struct stasis_topic *ast_rtp_topic(void)
2058 static void rtp_engine_shutdown(void)
2062 ao2_cleanup(rtp_topic);
2064 STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_received_type);
2065 STASIS_MESSAGE_TYPE_CLEANUP(ast_rtp_rtcp_sent_type);
2067 ast_rwlock_wrlock(&static_RTP_PT_lock);
2068 for (x = 0; x < AST_RTP_MAX_PT; x++) {
2069 if (static_RTP_PT[x].format) {
2070 rtp_engine_static_RTP_PT_cleanup(x);
2073 ast_rwlock_unlock(&static_RTP_PT_lock);
2075 ast_rwlock_wrlock(&mime_types_lock);
2076 for (x = 0; x < mime_types_len; x++) {
2077 if (ast_rtp_mime_types[x].payload_type.format) {
2078 rtp_engine_mime_type_cleanup(x);
2081 ast_rwlock_unlock(&mime_types_lock);
2084 int ast_rtp_engine_init()
2086 ast_rwlock_init(&mime_types_lock);
2087 ast_rwlock_init(&static_RTP_PT_lock);
2089 rtp_topic = stasis_topic_create("rtp_topic");
2093 STASIS_MESSAGE_TYPE_INIT(ast_rtp_rtcp_sent_type);
2094 STASIS_MESSAGE_TYPE_INIT(ast_rtp_rtcp_received_type);
2095 ast_register_cleanup(rtp_engine_shutdown);
2097 /* Define all the RTP mime types available */
2098 set_next_mime_type(ast_format_g723, 0, "audio", "G723", 8000);
2099 set_next_mime_type(ast_format_gsm, 0, "audio", "GSM", 8000);
2100 set_next_mime_type(ast_format_ulaw, 0, "audio", "PCMU", 8000);
2101 set_next_mime_type(ast_format_ulaw, 0, "audio", "G711U", 8000);
2102 set_next_mime_type(ast_format_alaw, 0, "audio", "PCMA", 8000);
2103 set_next_mime_type(ast_format_alaw, 0, "audio", "G711A", 8000);
2104 set_next_mime_type(ast_format_g726, 0, "audio", "G726-32", 8000);
2105 set_next_mime_type(ast_format_adpcm, 0, "audio", "DVI4", 8000);
2106 set_next_mime_type(ast_format_slin, 0, "audio", "L16", 8000);
2107 set_next_mime_type(ast_format_slin16, 0, "audio", "L16", 16000);
2108 set_next_mime_type(ast_format_slin16, 0, "audio", "L16-256", 16000);
2109 set_next_mime_type(ast_format_slin12, 0, "audio", "L16", 12000);
2110 set_next_mime_type(ast_format_slin24, 0, "audio", "L16", 24000);
2111 set_next_mime_type(ast_format_slin32, 0, "audio", "L16", 32000);
2112 set_next_mime_type(ast_format_slin44, 0, "audio", "L16", 44000);
2113 set_next_mime_type(ast_format_slin48, 0, "audio", "L16", 48000);
2114 set_next_mime_type(ast_format_slin96, 0, "audio", "L16", 96000);
2115 set_next_mime_type(ast_format_slin192, 0, "audio", "L16", 192000);
2116 set_next_mime_type(ast_format_lpc10, 0, "audio", "LPC", 8000);
2117 set_next_mime_type(ast_format_g729, 0, "audio", "G729", 8000);
2118 set_next_mime_type(ast_format_g729, 0, "audio", "G729A", 8000);
2119 set_next_mime_type(ast_format_g729, 0, "audio", "G.729", 8000);
2120 set_next_mime_type(ast_format_speex, 0, "audio", "speex", 8000);
2121 set_next_mime_type(ast_format_speex16, 0, "audio", "speex", 16000);
2122 set_next_mime_type(ast_format_speex32, 0, "audio", "speex", 32000);
2123 set_next_mime_type(ast_format_ilbc, 0, "audio", "iLBC", 8000);
2124 /* this is the sample rate listed in the RTP profile for the G.722 codec, *NOT* the actual sample rate of the media stream */
2125 set_next_mime_type(ast_format_g722, 0, "audio", "G722", 8000);
2126 set_next_mime_type(ast_format_g726_aal2, 0, "audio", "AAL2-G726-32", 8000);
2127 set_next_mime_type(NULL, AST_RTP_DTMF, "audio", "telephone-event", 8000);
2128 set_next_mime_type(NULL, AST_RTP_CISCO_DTMF, "audio", "cisco-telephone-event", 8000);
2129 set_next_mime_type(NULL, AST_RTP_CN, "audio", "CN", 8000);
2130 set_next_mime_type(ast_format_jpeg, 0, "video", "JPEG", 90000);
2131 set_next_mime_type(ast_format_png, 0, "video", "PNG", 90000);
2132 set_next_mime_type(ast_format_h261, 0, "video", "H261", 90000);
2133 set_next_mime_type(ast_format_h263, 0, "video", "H263", 90000);
2134 set_next_mime_type(ast_format_h263p, 0, "video", "h263-1998", 90000);
2135 set_next_mime_type(ast_format_h264, 0, "video", "H264", 90000);
2136 set_next_mime_type(ast_format_mp4, 0, "video", "MP4V-ES", 90000);
2137 set_next_mime_type(ast_format_t140_red, 0, "text", "RED", 1000);
2138 set_next_mime_type(ast_format_t140, 0, "text", "T140", 1000);
2139 set_next_mime_type(ast_format_siren7, 0, "audio", "G7221", 16000);
2140 set_next_mime_type(ast_format_siren14, 0, "audio", "G7221", 32000);
2141 set_next_mime_type(ast_format_g719, 0, "audio", "G719", 48000);
2143 set_next_mime_type(ast_format_opus, 0, "audio", "opus", 48000);
2144 set_next_mime_type(ast_format_vp8, 0, "video", "VP8", 90000);
2146 /* Define the static rtp payload mappings */
2147 add_static_payload(0, ast_format_ulaw, 0);
2148 #ifdef USE_DEPRECATED_G726
2149 add_static_payload(2, ast_format_g726, 0);/* Technically this is G.721, but if Cisco can do it, so can we... */
2151 add_static_payload(3, ast_format_gsm, 0);
2152 add_static_payload(4, ast_format_g723, 0);
2153 add_static_payload(5, ast_format_adpcm, 0);/* 8 kHz */
2154 add_static_payload(6, ast_format_adpcm, 0); /* 16 kHz */
2155 add_static_payload(7, ast_format_lpc10, 0);
2156 add_static_payload(8, ast_format_alaw, 0);
2157 add_static_payload(9, ast_format_g722, 0);
2158 add_static_payload(10, ast_format_slin, 0); /* 2 channels */
2159 add_static_payload(11, ast_format_slin, 0); /* 1 channel */
2160 add_static_payload(13, NULL, AST_RTP_CN);
2161 add_static_payload(16, ast_format_adpcm, 0); /* 11.025 kHz */
2162 add_static_payload(17, ast_format_adpcm, 0); /* 22.050 kHz */
2163 add_static_payload(18, ast_format_g729, 0);
2164 add_static_payload(19, NULL, AST_RTP_CN); /* Also used for CN */
2165 add_static_payload(26, ast_format_jpeg, 0);
2166 add_static_payload(31, ast_format_h261, 0);
2167 add_static_payload(34, ast_format_h263, 0);
2168 add_static_payload(97, ast_format_ilbc, 0);
2169 add_static_payload(98, ast_format_h263p, 0);
2170 add_static_payload(99, ast_format_h264, 0);
2171 add_static_payload(101, NULL, AST_RTP_DTMF);
2172 add_static_payload(102, ast_format_siren7, 0);
2173 add_static_payload(103, ast_format_h263p, 0);
2174 add_static_payload(104, ast_format_mp4, 0);
2175 add_static_payload(105, ast_format_t140_red, 0); /* Real time text chat (with redundancy encoding) */
2176 add_static_payload(106, ast_format_t140, 0); /* Real time text chat */
2177 add_static_payload(110, ast_format_speex, 0);
2178 add_static_payload(111, ast_format_g726, 0);
2179 add_static_payload(112, ast_format_g726_aal2, 0);
2180 add_static_payload(115, ast_format_siren14, 0);
2181 add_static_payload(116, ast_format_g719, 0);
2182 add_static_payload(117, ast_format_speex16, 0);
2183 add_static_payload(118, ast_format_slin16, 0); /* 16 Khz signed linear */
2184 add_static_payload(119, ast_format_speex32, 0);
2185 add_static_payload(121, NULL, AST_RTP_CISCO_DTMF); /* Must be type 121 */
2186 add_static_payload(122, ast_format_slin12, 0);
2187 add_static_payload(123, ast_format_slin24, 0);
2188 add_static_payload(124, ast_format_slin32, 0);
2189 add_static_payload(125, ast_format_slin44, 0);
2190 add_static_payload(126, ast_format_slin48, 0);
2191 add_static_payload(127, ast_format_slin96, 0);
2192 /* payload types above 127 are not valid */
2193 add_static_payload(96, ast_format_slin192, 0);
2195 add_static_payload(100, ast_format_vp8, 0);
2196 add_static_payload(107, ast_format_opus, 0);