MT#55447 support non-exact matching of codecs

Introduce an additional function for codec matching. Different functions
match different parts of an RTP payload type object and the referenced
codecs.

Change-Id: I2e488eaa7f69a55322db748fd40c8d1195e38605
pull/1563/head
Richard Fuchs 3 years ago
parent e0ad15dcd0
commit ec2aaf0249

@ -419,7 +419,7 @@ static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_
// don't reset handler if it already matches what we want
if (!handler->transcoder)
goto reset;
if (!rtp_payload_type_eq(dest, &handler->dest_pt))
if (!rtp_payload_type_eq_exact(dest, &handler->dest_pt))
goto reset;
if (handler->handler_func != handler_func_transcode)
goto reset;
@ -707,7 +707,7 @@ static struct codec_handler *__get_pt_handler(struct call_media *receiver, struc
handler = codec_handler_lookup(receiver->codec_handlers, pt->payload_type, sink);
if (handler) {
// make sure existing handler matches this PT
if (!rtp_payload_type_eq(pt, &handler->source_pt)) {
if (!rtp_payload_type_eq_exact(pt, &handler->source_pt)) {
ilogs(codec, LOG_DEBUG, "Resetting codec handler for PT %i", pt->payload_type);
g_hash_table_remove(receiver->codec_handlers, handler);
__handler_shutdown(handler);
@ -1069,7 +1069,7 @@ bool codec_handlers_update(struct call_media *receiver, struct call_media *sink,
sink_pt = g_hash_table_lookup(sink->codecs.codecs,
GINT_TO_POINTER(pt->payload_type));
// is it actually the same?
if (sink_pt && !rtp_payload_type_eq(pt, sink_pt))
if (sink_pt && !rtp_payload_type_eq_compat(pt, sink_pt))
sink_pt = NULL;
}
@ -4894,7 +4894,7 @@ bool codec_store_is_full_answer(const struct codec_store *src, const struct code
const struct rtp_payload_type *src_pt = l->data;
const struct rtp_payload_type *dst_pt = g_hash_table_lookup(dst->codecs,
GINT_TO_POINTER(src_pt->payload_type));
if (!dst_pt || !rtp_payload_type_eq(src_pt, dst_pt)) {
if (!dst_pt || !rtp_payload_type_eq_compat(src_pt, dst_pt)) {
ilogs(codec, LOG_DEBUG, "Source codec " STR_FORMAT " is not present in the answer",
STR_FMT(&src_pt->encoding_with_params));
return false;

@ -308,8 +308,8 @@ found:
// if we already have a handler, see if anything needs changing
if (mp->handler) {
if (!rtp_payload_type_eq(&mp->handler->dest_pt, dst_pt)
|| !rtp_payload_type_eq(&mp->handler->source_pt, src_pt))
if (!rtp_payload_type_eq_exact(&mp->handler->dest_pt, dst_pt)
|| !rtp_payload_type_eq_exact(&mp->handler->source_pt, src_pt))
{
ilog(LOG_DEBUG, "Resetting codec handler for media player");
codec_handler_free(&mp->handler);

@ -6,6 +6,7 @@ struct codec_def_s;
struct packet_sequencer_s;
typedef struct codec_def_s codec_def_t;
typedef struct packet_sequencer_s packet_sequencer_t;
struct rtp_payload_type;
enum media_type {
MT_UNKNOWN = 0,
@ -35,6 +36,12 @@ INLINE enum media_type codec_get_type(const str *type) {
}
// 0: exact match
// 1: a is compatible with b (not necessarily the other way around)
// -1: a is not compatible with b
typedef int format_cmp_f(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
#ifndef WITHOUT_CODECLIB
@ -77,7 +84,7 @@ typedef int packetizer_f(AVPacket *, GString *, str *, encoder_t *);
typedef void format_init_f(struct rtp_payload_type *);
typedef void set_enc_options_f(encoder_t *, const str *);
typedef void set_dec_options_f(decoder_t *, const str *);
typedef int format_cmp_f(const struct rtp_payload_type *, const struct rtp_payload_type *);
typedef int format_parse_f(struct rtp_codec_format *, const str *fmtp);
@ -389,7 +396,6 @@ INLINE int decoder_event(decoder_t *dec, enum codec_event event, void *ptr) {
#else
typedef int format_cmp_f(const void *, const void *);
// stubs
struct codec_def_s {

@ -144,28 +144,53 @@ const struct rtp_payload_type *rtp_get_rfc_codec(const str *codec) {
return NULL;
}
bool rtp_payload_type_eq(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (!rtp_payload_type_eq_nf(a, b))
// helper function: matches only basic params, without matching payload type number
static bool rtp_payload_type_fmt_eq_nf(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (a->clock_rate != b->clock_rate)
return false;
if (a->channels != b->channels)
return false;
if (str_casecmp_str(&a->encoding, &b->encoding))
return false;
return true;
}
// matches basic params and format params, but not payload type number
// returns matching val as per format_cmp_f
int rtp_payload_type_fmt_eq(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (!rtp_payload_type_fmt_eq_nf(a, b))
return -1;
if (a->codec_def && a->codec_def == b->codec_def) {
if (a->codec_def->format_cmp)
return a->codec_def->format_cmp(a, b) == 0;
return a->codec_def->format_cmp(a, b);
}
if (!a->codec_def) // ignore format of codecs we don't know
return true;
return 0;
if (str_cmp_str(&a->format_parameters, &b->format_parameters))
return false;
return true;
return -1;
return 0;
}
bool rtp_payload_type_fmt_eq_exact(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
return rtp_payload_type_fmt_eq(a, b) == 0;
}
bool rtp_payload_type_fmt_eq_compat(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
return rtp_payload_type_fmt_eq(a, b) >= 0;
}
bool rtp_payload_type_eq_nf(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
bool rtp_payload_type_eq_exact(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (a->payload_type != b->payload_type)
return false;
if (a->clock_rate != b->clock_rate)
return false;
if (a->channels != b->channels)
return rtp_payload_type_fmt_eq(a, b) == 0;
}
bool rtp_payload_type_eq_compat(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (a->payload_type != b->payload_type)
return false;
if (str_casecmp_str(&a->encoding, &b->encoding))
return rtp_payload_type_fmt_eq(a, b) >= 0;
}
// same as rtp_payload_type_fmt_eq_nf plus matching payload type number
bool rtp_payload_type_eq_nf(const struct rtp_payload_type *a, const struct rtp_payload_type *b) {
if (a->payload_type != b->payload_type)
return false;
return true;
return rtp_payload_type_fmt_eq_nf(a, b);
}

@ -75,8 +75,16 @@ int rtp_padding(const struct rtp_header *header, str *payload);
const struct rtp_payload_type *rtp_get_rfc_payload_type(unsigned int type);
const struct rtp_payload_type *rtp_get_rfc_codec(const str *codec);
bool rtp_payload_type_eq(const struct rtp_payload_type *, const struct rtp_payload_type *);
// if not `exact` then also returns true if `a` is compatible with `b`
// matches all params
bool rtp_payload_type_eq_exact(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
bool rtp_payload_type_eq_compat(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
// matches only basic params and payload type number
bool rtp_payload_type_eq_nf(const struct rtp_payload_type *, const struct rtp_payload_type *);
// matches all params except payload type number
int rtp_payload_type_fmt_eq(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
bool rtp_payload_type_fmt_eq_exact(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
bool rtp_payload_type_fmt_eq_compat(const struct rtp_payload_type *a, const struct rtp_payload_type *b);
#endif

Loading…
Cancel
Save