TT#91003 support passing extra codec options

Change-Id: I8e994f69d4ffc21ab5ab6e8c269e266cb1635b79
pull/1077/head
Richard Fuchs 5 years ago
parent 30b11936e8
commit 48d4dc3f7b

@ -1127,7 +1127,8 @@ Optionally included keys are:
channels) must also be specified.
Additional options that can be appended to the codec string with additional slashes
are ptime and the `fmtp` string, for example `iLBC/8000/1///mode=30`.
are ptime, the `fmtp` string, and additional codec-specific options, for example
`iLBC/8000/1///mode=30` to use as `fmtp`.
If a literal `=` cannot be used due to parsing constraints (i.e. being wrongly
interpreted as a key-value pair), it can be escaped by using two dashes instead,

@ -1558,7 +1558,7 @@ void codec_packet_free(void *pp) {
struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct call_media *media) {
str codec_fmt = *codec_str;
str codec, parms, chans, opts, extra_opts, fmt_params;
str codec, parms, chans, opts, extra_opts, fmt_params, codec_opts;
if (str_token_sep(&codec, &codec_fmt, '/'))
return NULL;
str_token_sep(&parms, &codec_fmt, '/');
@ -1566,6 +1566,7 @@ struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct ca
str_token_sep(&opts, &codec_fmt, '/');
str_token_sep(&extra_opts, &codec_fmt, '/');
str_token_sep(&fmt_params, &codec_fmt, '/');
str_token_sep(&codec_opts, &codec_fmt, '/');
int clockrate = str_to_i(&parms, 0);
int channels = str_to_i(&chans, 0);
@ -1583,6 +1584,7 @@ struct rtp_payload_type *codec_make_payload_type(const str *codec_str, struct ca
ret->bitrate = bitrate;
ret->ptime = ptime;
ret->format_parameters = fmt_params;
ret->codec_opts = codec_opts;
const codec_def_t *def = codec_find(&ret->encoding, 0);
ret->codec_def = def;
@ -1773,7 +1775,8 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p) {
if (encoder_config_fmtp(ch->encoder, h->dest_pt.codec_def,
ch->bitrate,
ch->ptime,
&enc_format, &ch->encoder_format, &h->dest_pt.format_parameters))
&enc_format, &ch->encoder_format, &h->dest_pt.format_parameters,
&h->dest_pt.codec_opts))
goto err;
if (h->pcm_dtmf_detect) {
@ -1788,7 +1791,7 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p) {
ch->decoder = decoder_new_fmtp(h->source_pt.codec_def, h->source_pt.clock_rate, h->source_pt.channels,
h->source_pt.ptime,
&ch->encoder_format, &h->source_pt.format_parameters);
&ch->encoder_format, &h->source_pt.format_parameters, &h->source_pt.codec_opts);
if (!ch->decoder)
goto err;
@ -2189,6 +2192,7 @@ static void __rtp_payload_type_dup(struct call *call, struct rtp_payload_type *p
call_str_cpy(call, &pt->encoding, &pt->encoding);
call_str_cpy(call, &pt->encoding_parameters, &pt->encoding_parameters);
call_str_cpy(call, &pt->format_parameters, &pt->format_parameters);
call_str_cpy(call, &pt->codec_opts, &pt->codec_opts);
}
static struct rtp_payload_type *__rtp_payload_type_copy(const struct rtp_payload_type *pt) {
struct rtp_payload_type *pt_copy = g_slice_alloc(sizeof(*pt));
@ -2273,7 +2277,9 @@ static int __revert_codec_strip(GHashTable *removed, const str *codec,
g_queue_free(q);
return 1;
}
static int __codec_options_set1(struct rtp_payload_type *pt, const str *enc, GHashTable *codec_set) {
static int __codec_options_set1(struct call *call, struct rtp_payload_type *pt, const str *enc,
GHashTable *codec_set)
{
str *pt_str = g_hash_table_lookup(codec_set, enc);
if (!pt_str)
return 0;
@ -2288,15 +2294,17 @@ static int __codec_options_set1(struct rtp_payload_type *pt, const str *enc, GHa
// match - apply options
if (!pt->bitrate)
pt->bitrate = pt_parsed->bitrate;
if (!pt->codec_opts.len && pt_parsed->codec_opts.len)
call_str_cpy(call, &pt->codec_opts, &pt_parsed->codec_opts);
payload_type_free(pt_parsed);
return 1;
}
static void __codec_options_set(struct rtp_payload_type *pt, GHashTable *codec_set) {
static void __codec_options_set(struct call *call, struct rtp_payload_type *pt, GHashTable *codec_set) {
if (!codec_set)
return;
if (__codec_options_set1(pt, &pt->encoding_with_params, codec_set))
if (__codec_options_set1(call, pt, &pt->encoding_with_params, codec_set))
return;
if (__codec_options_set1(pt, &pt->encoding, codec_set))
if (__codec_options_set1(call, pt, &pt->encoding, codec_set))
return;
}
void codec_rtp_payload_types(struct call_media *media, struct call_media *other_media,
@ -2354,7 +2362,7 @@ void codec_rtp_payload_types(struct call_media *media, struct call_media *other_
continue;
}
}
__codec_options_set(pt, flags->codec_set);
__codec_options_set(call, pt, flags->codec_set);
if (!mask_all && (!flags->codec_mask || !g_hash_table_lookup(flags->codec_mask, &pt->encoding))
&& (!flags->codec_mask || !g_hash_table_lookup(flags->codec_mask, &pt->encoding_with_params)))
__rtp_payload_type_add(media, other_media, pt);

@ -49,10 +49,10 @@ static set_enc_options_f amr_set_enc_options;
static set_dec_options_f amr_set_dec_options;
static void avc_def_init(codec_def_t *);
static const char *avc_decoder_init(decoder_t *, const str *);
static const char *avc_decoder_init(decoder_t *, const str *, const str *);
static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static void avc_decoder_close(decoder_t *);
static const char *avc_encoder_init(encoder_t *enc, const str *);
static const char *avc_encoder_init(encoder_t *enc, const str *, const str *);
static int avc_encoder_input(encoder_t *enc, AVFrame **frame);
static void avc_encoder_close(encoder_t *enc);
@ -60,7 +60,7 @@ static int amr_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static void amr_encoder_got_packet(encoder_t *enc);
static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static const char *dtmf_decoder_init(decoder_t *, const str *);
static const char *dtmf_decoder_init(decoder_t *, const str *, const str *);
static int dtmf_decoder_input(decoder_t *dec, const str *data, GQueue *out);
@ -103,10 +103,10 @@ static const codec_type_t codec_type_dtmf = {
static packetizer_f packetizer_g729; // aggregate some frames into packets
static void bcg729_def_init(codec_def_t *);
static const char *bcg729_decoder_init(decoder_t *, const str *);
static const char *bcg729_decoder_init(decoder_t *, const str *, const str *);
static int bcg729_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static void bcg729_decoder_close(decoder_t *);
static const char *bcg729_encoder_init(encoder_t *enc, const str *);
static const char *bcg729_encoder_init(encoder_t *enc, const str *, const str *);
static int bcg729_encoder_input(encoder_t *enc, AVFrame **frame);
static void bcg729_encoder_close(encoder_t *enc);
@ -447,7 +447,7 @@ const codec_def_t *codec_find_by_av(enum AVCodecID id) {
static const char *avc_decoder_init(decoder_t *dec, const str *fmtp) {
static const char *avc_decoder_init(decoder_t *dec, const str *fmtp, const str *extra_opts) {
AVCodec *codec = dec->def->decoder;
if (!codec)
return "codec not supported";
@ -459,7 +459,7 @@ static const char *avc_decoder_init(decoder_t *dec, const str *fmtp) {
dec->u.avc.avcctx->sample_rate = dec->in_format.clockrate;
if (dec->def->set_dec_options)
dec->def->set_dec_options(dec, fmtp);
dec->def->set_dec_options(dec, fmtp, extra_opts);
int i = avcodec_open2(dec->u.avc.avcctx, codec, NULL);
if (i) {
@ -476,12 +476,16 @@ static const char *avc_decoder_init(decoder_t *dec, const str *fmtp) {
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int ptime, const format_t *resample_fmt) {
return decoder_new_fmtp(def, clockrate, channels, ptime, resample_fmt, NULL);
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int ptime,
const format_t *resample_fmt)
{
return decoder_new_fmtp(def, clockrate, channels, ptime, resample_fmt, NULL, NULL);
}
decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels, int ptime, const format_t *resample_fmt,
const str *fmtp)
decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels, int ptime,
const format_t *resample_fmt,
const str *fmtp,
const str *extra_opts)
{
const char *err;
decoder_t *ret = NULL;
@ -507,7 +511,7 @@ decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels,
else
ret->ptime = def->default_ptime;
err = def->codec_type->decoder_init(ret, fmtp);
err = def->codec_type->decoder_init(ret, fmtp, extra_opts);
if (err)
goto err;
@ -1008,7 +1012,7 @@ encoder_t *encoder_new(void) {
return ret;
}
static const char *avc_encoder_init(encoder_t *enc, const str *fmtp) {
static const char *avc_encoder_init(encoder_t *enc, const str *fmtp, const str *extra_opts) {
enc->u.avc.codec = enc->def->encoder;
if (!enc->u.avc.codec)
return "output codec not found";
@ -1044,7 +1048,7 @@ static const char *avc_encoder_init(encoder_t *enc, const str *fmtp) {
enc->samples_per_packet = enc->samples_per_frame;
if (enc->def->set_enc_options)
enc->def->set_enc_options(enc, fmtp);
enc->def->set_enc_options(enc, fmtp, extra_opts);
int i = avcodec_open2(enc->u.avc.avcctx, enc->u.avc.codec, NULL);
if (i) {
@ -1058,11 +1062,12 @@ static const char *avc_encoder_init(encoder_t *enc, const str *fmtp) {
int encoder_config(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime,
const format_t *requested_format, format_t *actual_format)
{
return encoder_config_fmtp(enc, def, bitrate, ptime, requested_format, actual_format, NULL);
return encoder_config_fmtp(enc, def, bitrate, ptime, requested_format, actual_format, NULL, NULL);
}
int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime,
const format_t *requested_format, format_t *actual_format, const str *fmtp)
const format_t *requested_format, format_t *actual_format, const str *fmtp,
const str *extra_opts)
{
const char *err;
@ -1081,7 +1086,7 @@ int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int
enc->ptime = ptime / def->clockrate_mult;
enc->bitrate = bitrate;
err = def->codec_type->encoder_init ? def->codec_type->encoder_init(enc, fmtp) : 0;
err = def->codec_type->encoder_init ? def->codec_type->encoder_init(enc, fmtp, extra_opts) : 0;
if (err)
goto err;
@ -1370,7 +1375,7 @@ static void opus_init(struct rtp_payload_type *pt) {
ilog(LOG_DEBUG, "Using default bitrate of %i bps for %i-channel Opus", pt->bitrate, pt->channels);
}
static void opus_set_enc_options(encoder_t *enc, const str *fmtp) {
static void opus_set_enc_options(encoder_t *enc, const str *fmtp, const str *codec_opts) {
int ret;
if (enc->ptime)
if ((ret = av_opt_set_int(enc->u.avc.avcctx, "frame_duration", enc->ptime,
@ -1423,7 +1428,7 @@ static int ilbc_mode(int ptime, const str *fmtp, const char *direction) {
return mode;
}
static void ilbc_set_enc_options(encoder_t *enc, const str *fmtp) {
static void ilbc_set_enc_options(encoder_t *enc, const str *fmtp, const str *codec_opts) {
int ret;
int mode = ilbc_mode(enc->ptime, fmtp, "encoder");
@ -1433,7 +1438,7 @@ static void ilbc_set_enc_options(encoder_t *enc, const str *fmtp) {
mode, av_error(ret));
}
static void ilbc_set_dec_options(decoder_t *dec, const str *fmtp) {
static void ilbc_set_dec_options(decoder_t *dec, const str *fmtp, const str *codec_opts) {
int mode = ilbc_mode(dec->ptime, fmtp, "decoder");
if (mode == 20)
dec->u.avc.avcctx->block_align = 38;
@ -1469,7 +1474,7 @@ static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
"block mode (%i ms mode)",
(int) dec->u.avc.avcctx->block_align, (int) data->len, block_align, mode);
avc_decoder_close(dec);
avc_decoder_init(dec, fmtp);
avc_decoder_init(dec, fmtp, NULL);
}
return avc_decoder_input(dec, data, out);
@ -1598,7 +1603,7 @@ static void amr_set_encdec_options(codec_options_t *opts, const str *fmtp, const
// XXX other options
}
}
static void amr_set_enc_options(encoder_t *enc, const str *fmtp) {
static void amr_set_enc_options(encoder_t *enc, const str *fmtp, const str *codec_opts) {
amr_set_encdec_options(&enc->codec_options, fmtp, enc->def);
// if a mode-set was given, pick the highest supported bitrate
@ -1627,7 +1632,7 @@ static void amr_set_enc_options(encoder_t *enc, const str *fmtp) {
}
}
}
static void amr_set_dec_options(decoder_t *dec, const str *fmtp) {
static void amr_set_dec_options(decoder_t *dec, const str *fmtp, const str *codec_opts) {
amr_set_encdec_options(&dec->codec_options, fmtp, dec->def);
}
@ -1833,7 +1838,7 @@ static void bcg729_def_init(codec_def_t *def) {
}
}
static const char *bcg729_decoder_init(decoder_t *dec, const str *fmtp) {
static const char *bcg729_decoder_init(decoder_t *dec, const str *fmtp, const str *extra_opts) {
dec->u.bcg729 = initBcg729DecoderChannel();
if (!dec->u.bcg729)
return "failed to initialize bcg729";
@ -1877,7 +1882,7 @@ static void bcg729_decoder_close(decoder_t *dec) {
dec->u.bcg729 = NULL;
}
static const char *bcg729_encoder_init(encoder_t *enc, const str *fmtp) {
static const char *bcg729_encoder_init(encoder_t *enc, const str *fmtp, const str *extra_opts) {
enc->u.bcg729 = initBcg729EncoderChannel(0); // no VAD
if (!enc->u.bcg729)
return "failed to initialize bcg729";
@ -1968,7 +1973,7 @@ static int packetizer_g729(AVPacket *pkt, GString *buf, str *input_output, encod
#endif
static const char *dtmf_decoder_init(decoder_t *dec, const str *fmtp) {
static const char *dtmf_decoder_init(decoder_t *dec, const str *fmtp, const str *extra_opts) {
dec->u.dtmf.event = -1;
return NULL;
}

@ -67,19 +67,19 @@ typedef union codec_options_u codec_options_t;
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 void set_enc_options_f(encoder_t *, const str *, const str *);
typedef void set_dec_options_f(decoder_t *, const str *, const str *);
struct codec_type_s {
void (*def_init)(codec_def_t *);
const char *(*decoder_init)(decoder_t *, const str *);
const char *(*decoder_init)(decoder_t *, const str *, const str *);
int (*decoder_input)(decoder_t *, const str *data, GQueue *);
void (*decoder_close)(decoder_t *);
const char *(*encoder_init)(encoder_t *, const str *);
const char *(*encoder_init)(encoder_t *, const str *, const str *);
int (*encoder_input)(encoder_t *, AVFrame **);
void (*encoder_got_packet)(encoder_t *);
void (*encoder_close)(encoder_t *);
@ -242,9 +242,11 @@ const codec_def_t *codec_find(const str *name, enum media_type);
const codec_def_t *codec_find_by_av(enum AVCodecID);
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int ptime, const format_t *resample_fmt);
decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels, int ptime, const format_t *resample_fmt,
const str *fmtp);
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int ptime,
const format_t *resample_fmt);
decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels, int ptime,
const format_t *resample_fmt,
const str *fmtp, const str *codec_opts);
void decoder_close(decoder_t *dec);
int decoder_input_data(decoder_t *dec, const str *data, unsigned long ts,
int (*callback)(decoder_t *, AVFrame *, void *u1, void *u2), void *u1, void *u2);
@ -254,7 +256,7 @@ encoder_t *encoder_new(void);
int encoder_config(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime,
const format_t *requested_format, format_t *actual_format);
int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime,
const format_t *requested_format, format_t *actual_format, const str *fmtp);
const format_t *requested_format, format_t *actual_format, const str *fmtp, const str *codec_opts);
void encoder_close(encoder_t *);
void encoder_free(encoder_t *);
int encoder_input_data(encoder_t *enc, AVFrame *frame,

@ -24,6 +24,7 @@ struct rtp_payload_type {
str encoding_parameters; // "2"
int channels; // 2
str format_parameters; // value of a=fmtp
str codec_opts; // extra codec-specific options
int ptime; // default from RFC
int bitrate;

Loading…
Cancel
Save