mirror of https://github.com/sipwise/rtpengine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.3 KiB
133 lines
3.3 KiB
#include "codecmod.h"
|
|
#include "loglib.h"
|
|
|
|
|
|
static bool ilbc_format_parse(struct rtp_codec_format *f, const str *fmtp) {
|
|
switch (__csh_lookup(fmtp)) {
|
|
case CSH_LOOKUP("mode=20"):
|
|
f->parsed.ilbc.mode = 20;
|
|
break;
|
|
case CSH_LOOKUP("mode=30"):
|
|
f->parsed.ilbc.mode = 30;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int ilbc_mode(int ptime, const union codec_format_options *fmtp, const char *direction) {
|
|
int mode = 0;
|
|
if (fmtp)
|
|
mode = fmtp->ilbc.mode;
|
|
|
|
if (!mode) {
|
|
switch (ptime) {
|
|
case 20:
|
|
case 40:
|
|
case 60:
|
|
case 80:
|
|
case 100:
|
|
case 120:
|
|
mode = 20;
|
|
ilog(LOG_DEBUG, "Setting iLBC %s mode to 20 ms based on ptime %i",
|
|
direction, ptime);
|
|
break;
|
|
case 30:
|
|
case 90:
|
|
mode = 30;
|
|
ilog(LOG_DEBUG, "Setting iLBC %s mode to 30 ms based on ptime %i",
|
|
direction, ptime);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!mode) {
|
|
mode = 20;
|
|
ilog(LOG_WARNING, "No iLBC %s mode specified, setting to 20 ms", direction);
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
static void ilbc_set_enc_options(encoder_t *enc, const str *codec_opts) {
|
|
int mode = ilbc_mode(enc->ptime, &enc->format_options, "encoder");
|
|
codeclib_set_av_opt_int(enc, "mode", mode);
|
|
}
|
|
|
|
static void ilbc_set_dec_options(decoder_t *dec, const str *codec_opts) {
|
|
int mode = ilbc_mode(dec->ptime, &dec->format_options, "decoder");
|
|
if (mode == 20)
|
|
dec->avc.avcctx->block_align = 38;
|
|
else if (mode == 30)
|
|
dec->avc.avcctx->block_align = 50;
|
|
else
|
|
ilog(LOG_WARN, "Unsupported iLBC mode %i", mode);
|
|
}
|
|
|
|
static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
|
|
int mode = 0, block_align = 0;
|
|
static const union codec_format_options mode_20 = { .ilbc = { 20 } };
|
|
static const union codec_format_options mode_30 = { .ilbc = { 30 } };
|
|
const union codec_format_options *fmtp;
|
|
|
|
if (data->len % 50 == 0) {
|
|
mode = 30;
|
|
block_align = 50;
|
|
fmtp = &mode_30;
|
|
}
|
|
else if (data->len % 38 == 0) {
|
|
mode = 20;
|
|
block_align = 38;
|
|
fmtp = &mode_20;
|
|
}
|
|
else
|
|
ilog(LOG_WARNING | LOG_FLAG_LIMIT, "iLBC received %i bytes packet, does not match "
|
|
"one of the block sizes", (int) data->len);
|
|
|
|
if (block_align && dec->avc.avcctx->block_align != block_align) {
|
|
ilog(LOG_INFO | LOG_FLAG_LIMIT, "iLBC decoder set to %i bytes blocks, but received packet "
|
|
"of %i bytes, therefore resetting decoder and switching to %i bytes "
|
|
"block mode (%i ms mode)",
|
|
(int) dec->avc.avcctx->block_align, (int) data->len, block_align, mode);
|
|
avc_decoder_close(dec);
|
|
dec->format_options = *fmtp;
|
|
avc_decoder_init(dec, NULL);
|
|
}
|
|
|
|
return avc_decoder_input(dec, data, out);
|
|
}
|
|
|
|
|
|
static const codec_type_t codec_type_ilbc = {
|
|
.def_init = avc_def_init,
|
|
.decoder_init = avc_decoder_init,
|
|
.decoder_input = ilbc_decoder_input,
|
|
.decoder_close = avc_decoder_close,
|
|
.encoder_init = avc_encoder_init,
|
|
.encoder_input = avc_encoder_input,
|
|
.encoder_close = avc_encoder_close,
|
|
};
|
|
|
|
|
|
static const codec_def_t ilbc = {
|
|
.rtpname = "iLBC",
|
|
.avcodec_id = AV_CODEC_ID_ILBC,
|
|
.default_clockrate = 8000,
|
|
.default_channels = 1,
|
|
.default_ptime = 30,
|
|
.default_fmtp = "mode=30",
|
|
.format_parse = ilbc_format_parse,
|
|
//.default_bitrate = 15200,
|
|
.packetizer = packetizer_passthrough,
|
|
.media_type = MT_AUDIO,
|
|
.codec_type = &codec_type_ilbc,
|
|
.set_enc_options = ilbc_set_enc_options,
|
|
.set_dec_options = ilbc_set_dec_options,
|
|
};
|
|
|
|
__attribute__((constructor))
|
|
static void init(void) {
|
|
codeclib_register_codec(&ilbc);
|
|
}
|