unsigned int framing;
/*! The preferred format, as the mappings are numerically sorted */
struct ast_format *preferred_format;
+ /*! The preferred dtmf sample rate */
+ int preferred_dtmf_rate;
+ /*! The preferred dtmf payload type */
+ int preferred_dtmf_pt;
};
#define AST_RTP_CODECS_NULL_INIT \
- { .codecs_lock = AST_RWLOCK_INIT_VALUE, .payload_mapping_rx = { 0, }, .payload_mapping_tx = { 0, }, .framing = 0, .preferred_format = NULL }
+ { .codecs_lock = AST_RWLOCK_INIT_VALUE, .payload_mapping_rx = { 0, }, .payload_mapping_tx = { 0, }, .framing = 0, .preferred_format = NULL, \
+ .preferred_dtmf_rate = -1, .preferred_dtmf_pt = -1}
/*! Structure that represents the glue that binds an RTP instance to a channel */
struct ast_rtp_glue {
*/
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format);
+/*!
+ * \brief Retrieve rx preferred dtmf format payload type
+ *
+ * \param codecs Codecs structure to look in
+ *
+ * \return Payload type of preferred dtmf format.
+ * \retval -1 if not set.
+ *
+ * Example usage:
+ *
+ * \code
+ * int payload;
+ * payload = ast_rtp_codecs_get_preferred_dtmf_format_pt(codec);
+ * \endcode
+ *
+ * This looks up the preferred dtmf format pt on the codec
+ */
+int ast_rtp_codecs_get_preferred_dtmf_format_pt(struct ast_rtp_codecs *codecs);
+
+/*!
+ * \brief Retrieve rx preferred dtmf format sample rate
+ *
+ * \param codecs Codecs structure to look in
+ *
+ * \return Sample rate of preferred dtmf format.
+ * \retval -1 if not set.
+ *
+ * Example usage:
+ *
+ * \code
+ * int sample_rate;
+ * sample_rate = ast_rtp_codecs_get_preferred_dtmf_format_rate(codec);
+ * \endcode
+ *
+ * This looks up the preferred dtmf format sample rate on the codec
+ */
+int ast_rtp_codecs_get_preferred_dtmf_format_rate(struct ast_rtp_codecs *codecs);
+
+/*!
+ * \brief Set the preferred dtmf format pt and sample rate
+ *
+ * \param codecs Codecs structure to set the preferred format in
+ * \param pt Preferred dtmf payload type to set.
+ * \param rate Preferred dtmf payload rate to set.
+ *
+ * \return 0
+ *
+ * \note The format passed this function has its reference count increased. If an existing
+ * format is set, that format is replaced.
+ *
+ * Example usage:
+ *
+ * \code
+ * int dtmf_code = atoi(dtmf_pt);
+ * int dtmf_rate = clock_rate;
+ * ast_rtp_codecs_set_preferred_dtmf_format(codecs, dtmf_code, dtmf_rate);
+ * \endcode
+ *
+ * This sets the preferred dtmf_code and dtmf_rate on the codec.
+ */
+int ast_rtp_codecs_set_preferred_dtmf_format(struct ast_rtp_codecs *codecs, int pt, int rate);
+
+
/*!
* \brief Update the format associated with a tx payload type in a codecs structure
*
*/
struct stasis_topic *ast_rtp_topic(void);
+/*!
+ * \brief Determine if a type of payload is already present in mappings.
+ * \since 18
+ *
+ * \param codecs Codecs to be checked for mappings.
+ * \param to_match Payload type object to compare against.
+ *
+ * \note It is assumed that codecs is not locked before calling.
+ *
+ * \retval 0 not found
+ * \retval 1 found
+ */
+int ast_rtp_payload_mapping_tx_is_present(struct ast_rtp_codecs *codecs, const struct ast_rtp_payload_type *to_match);
+
/* RTP debug logging category name */
#define AST_LOG_CATEGORY_RTP "rtp"
/* RTP packet debug logging category name */
return 0;
}
+int ast_rtp_payload_mapping_tx_is_present(struct ast_rtp_codecs *codecs, const struct ast_rtp_payload_type *to_match) {
+ int ret = 0;
+ if (codecs && to_match) {
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ ret = payload_mapping_tx_is_present(codecs, to_match);
+ ast_rwlock_unlock(&codecs->codecs_lock);
+ }
+ return ret;
+}
+
/*!
* \internal
* \brief Copy the tx payload type mapping to the destination.
rtp_codecs_payloads_copy_tx(src, dest, instance);
dest->framing = src->framing;
ao2_replace(dest->preferred_format, src->preferred_format);
+ dest->preferred_dtmf_rate = src->preferred_dtmf_rate;
+ dest->preferred_dtmf_pt = src->preferred_dtmf_pt;
ast_rwlock_unlock(&src->codecs_lock);
ast_rwlock_unlock(&dest->codecs_lock);
dest->framing = src->framing;
ao2_replace(dest->preferred_format, src->preferred_format);
+ dest->preferred_dtmf_rate = src->preferred_dtmf_rate;
+ dest->preferred_dtmf_pt = src->preferred_dtmf_pt;
if (src != dest) {
ast_rwlock_unlock(&src->codecs_lock);
return 0;
}
+int ast_rtp_codecs_get_preferred_dtmf_format_pt(struct ast_rtp_codecs *codecs)
+{
+ int pt = -1;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ pt = codecs->preferred_dtmf_pt;
+ ast_rwlock_unlock(&codecs->codecs_lock);
+ return pt;
+}
+
+int ast_rtp_codecs_get_preferred_dtmf_format_rate(struct ast_rtp_codecs *codecs)
+{
+ int rate = -1;
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ rate = codecs->preferred_dtmf_rate;
+ ast_rwlock_unlock(&codecs->codecs_lock);
+ return rate;
+}
+
+int ast_rtp_codecs_set_preferred_dtmf_format(struct ast_rtp_codecs *codecs, int pt, int rate)
+{
+ ast_rwlock_wrlock(&codecs->codecs_lock);
+ codecs->preferred_dtmf_pt = pt;
+ codecs->preferred_dtmf_rate = rate;
+ ast_rwlock_unlock(&codecs->codecs_lock);
+ return 0;
+}
+
int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
{
struct ast_rtp_payload_type *type;
ast_rwlock_rdlock(&static_RTP_PT_lock);
payload = find_static_payload_type(asterisk_format, format, code);
ast_rwlock_unlock(&static_RTP_PT_lock);
+
+ ast_rwlock_rdlock(&codecs->codecs_lock);
+ if (payload >= 0 && payload < AST_VECTOR_SIZE(&codecs->payload_mapping_tx)){
+ type = AST_VECTOR_GET(&codecs->payload_mapping_tx, payload);
+ if (!type || (sample_rate != 0 && type->sample_rate != sample_rate)) {
+ /* Don't use the type if we can't find it or it doesn't match the supplied sample_rate */
+ payload = -1;
+ }
+ }
+ ast_rwlock_unlock(&codecs->codecs_lock);
}
return payload;
ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name));
if (strcmp(name, "telephone-event") == 0) {
+ if (tel_event == 0) {
+ int dtmf_rate = 0, dtmf_code = 0;
+ char dtmf_pt[8];
+ ast_copy_pj_str(dtmf_pt, &rtpmap->pt, sizeof(dtmf_pt));
+ dtmf_code = atoi(dtmf_pt);
+ dtmf_rate = rtpmap->clock_rate;
+ ast_rtp_codecs_set_preferred_dtmf_format(codecs, dtmf_code, dtmf_rate);
+ }
tel_event++;
}
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_sockaddr remote_address = { {0,} };
- int hdrlen = 12, res = 0, i = 0, payload = 101;
- unsigned int sample_rate = 8000;
+ int hdrlen = 12, res = 0, i = 0, payload = -1, sample_rate = -1;
char data[256];
unsigned int *rtpheader = (unsigned int*)data;
RAII_VAR(struct ast_format *, payload_format, NULL, ao2_cleanup);
sample_rate = ast_format_get_sample_rate(rtp->lasttxformat);
}
- /* Grab the matching DTMF type payload */
- payload = ast_rtp_codecs_payload_code_tx_sample_rate(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF, sample_rate);
+ if (sample_rate != -1) {
+ payload = ast_rtp_codecs_payload_code_tx_sample_rate(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF, sample_rate);
+ }
- /* If this returns -1, we are using a codec with a sample rate that does not have a matching RFC 2833/4733
- offer. The offer may have included a default-rate one that doesn't match the codec rate, so try to use that. */
- if (payload == -1) {
+ if (payload == -1 ||
+ !ast_rtp_payload_mapping_tx_is_present(
+ ast_rtp_instance_get_codecs(instance), ast_rtp_codecs_get_payload(ast_rtp_instance_get_codecs(instance), payload))) {
+ /* Fall back to the preferred DTMF payload type and sample rate as either we couldn't find an audio codec to try and match
+ sample rates with or we could, but a telephone-event matching that audio codec's sample rate was not included in the
+ sdp negotiated by the far end. */
+ payload = ast_rtp_codecs_get_preferred_dtmf_format_pt(ast_rtp_instance_get_codecs(instance));
+ sample_rate = ast_rtp_codecs_get_preferred_dtmf_format_rate(ast_rtp_instance_get_codecs(instance));
+ }
+
+ /* The sdp negotiation has not yeilded a usable RFC 2833/4733 format. Try a default-rate one as a last resort. */
+ if (payload == -1 || sample_rate == -1) {
sample_rate = DEFAULT_DTMF_SAMPLE_RATE_MS;
payload = ast_rtp_codecs_payload_code_tx(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_DTMF);
}
- /* No default-rate offer either, trying to send a digit outside of what was negotiated for. */
+ /* Even trying a default payload has failed. We are trying to send a digit outside of what was negotiated for. */
if (payload == -1) {
return -1;
}