?? ilbc.c
字號:
2000, 2000);
PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
codec = pj_pool_zalloc(pool, sizeof(struct ilbc_codec));
codec->base.op = &ilbc_op;
codec->base.factory = factory;
codec->pool = pool;
pj_ansi_snprintf(codec->obj_name, sizeof(codec->obj_name),
"ilbc%p", codec);
*p_codec = &codec->base;
return PJ_SUCCESS;
}
/*
* Free codec.
*/
static pj_status_t ilbc_dealloc_codec( pjmedia_codec_factory *factory,
pjmedia_codec *codec )
{
struct ilbc_codec *ilbc_codec;
PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
PJ_UNUSED_ARG(factory);
PJ_ASSERT_RETURN(factory == &ilbc_factory.base, PJ_EINVAL);
ilbc_codec = (struct ilbc_codec*) codec;
pj_pool_release(ilbc_codec->pool);
return PJ_SUCCESS;
}
/*
* Init codec.
*/
static pj_status_t ilbc_codec_init(pjmedia_codec *codec,
pj_pool_t *pool )
{
PJ_UNUSED_ARG(codec);
PJ_UNUSED_ARG(pool);
return PJ_SUCCESS;
}
/*
* Open codec.
*/
static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
pjmedia_codec_param *attr )
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
pj_status_t status;
pj_assert(ilbc_codec != NULL);
pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&
ilbc_codec->dec_ready == PJ_FALSE);
/* Decoder mode must be set */
PJ_ASSERT_RETURN(attr->setting.dec_fmtp_mode==20 ||
attr->setting.dec_fmtp_mode==30, PJMEDIA_CODEC_EINMODE);
/* The enc mode must be set in the attribute
* (from the mode parameter in fmtp attribute in the SDP
* received from remote)
*/
if (attr->setting.enc_fmtp_mode == 0)
attr->setting.enc_fmtp_mode = attr->setting.dec_fmtp_mode;
PJ_ASSERT_RETURN(attr->setting.enc_fmtp_mode==20 ||
attr->setting.enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE);
/* Update enc_ptime in the param */
if (attr->setting.enc_fmtp_mode != attr->setting.dec_fmtp_mode) {
attr->info.enc_ptime = attr->setting.enc_fmtp_mode;
} else {
attr->info.enc_ptime = 0;
}
/* Create enc */
ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc,
attr->setting.enc_fmtp_mode);
ilbc_codec->enc_samples_per_frame = CLOCK_RATE*attr->setting.enc_fmtp_mode/
1000;
ilbc_codec->enc_ready = PJ_TRUE;
/* Create decoder */
ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
attr->setting.dec_fmtp_mode,
attr->setting.penh);
if (attr->setting.dec_fmtp_mode == 20)
ilbc_codec->dec_frame_size = 38;
else if (attr->setting.dec_fmtp_mode == 30)
ilbc_codec->dec_frame_size = 50;
else {
pj_assert(!"Invalid iLBC mode");
ilbc_codec->dec_frame_size = ilbc_codec->enc_frame_size;
}
ilbc_codec->dec_ready = PJ_TRUE;
/* Save plc flags */
ilbc_codec->plc_enabled = (attr->setting.plc != 0);
/* Create silence detector. */
ilbc_codec->vad_enabled = (attr->setting.vad != 0);
status = pjmedia_silence_det_create(ilbc_codec->pool, CLOCK_RATE,
ilbc_codec->enc_samples_per_frame,
&ilbc_codec->vad);
if (status != PJ_SUCCESS)
return status;
/* Init last_tx (not necessary because of zalloc, but better
* be safe in case someone remove zalloc later.
*/
pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
PJ_LOG(5,(ilbc_codec->obj_name,
"iLBC codec opened, encoder mode=%d, decoder mode=%d",
attr->setting.enc_fmtp_mode, attr->setting.dec_fmtp_mode));
return PJ_SUCCESS;
}
/*
* Close codec.
*/
static pj_status_t ilbc_codec_close( pjmedia_codec *codec )
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
PJ_UNUSED_ARG(codec);
PJ_LOG(5,(ilbc_codec->obj_name, "iLBC codec closed"));
return PJ_SUCCESS;
}
/*
* Modify codec settings.
*/
static pj_status_t ilbc_codec_modify(pjmedia_codec *codec,
const pjmedia_codec_param *attr )
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
ilbc_codec->plc_enabled = (attr->setting.plc != 0);
ilbc_codec->vad_enabled = (attr->setting.vad != 0);
return PJ_SUCCESS;
}
/*
* Get frames in the packet.
*/
static pj_status_t ilbc_codec_parse( pjmedia_codec *codec,
void *pkt,
pj_size_t pkt_size,
const pj_timestamp *ts,
unsigned *frame_cnt,
pjmedia_frame frames[])
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
unsigned count;
PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
count = 0;
while (pkt_size >= ilbc_codec->dec_frame_size && count < *frame_cnt) {
frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
frames[count].buf = pkt;
frames[count].size = ilbc_codec->dec_frame_size;
frames[count].timestamp.u64 = ts->u64 + count *
ilbc_codec->dec_samples_per_frame;
pkt = ((char*)pkt) + ilbc_codec->dec_frame_size;
pkt_size -= ilbc_codec->dec_frame_size;
++count;
}
*frame_cnt = count;
return PJ_SUCCESS;
}
/*
* Encode frame.
*/
static pj_status_t ilbc_codec_encode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
unsigned i;
pj_assert(ilbc_codec != NULL);
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
if (output_buf_len < ilbc_codec->enc_frame_size)
return PJMEDIA_CODEC_EFRMTOOSHORT;
if (input->size != (ilbc_codec->enc_samples_per_frame << 1))
return PJMEDIA_CODEC_EPCMFRMINLEN;
/* Detect silence */
if (ilbc_codec->vad_enabled) {
pj_bool_t is_silence;
pj_int32_t silence_period;
silence_period = pj_timestamp_diff32(&ilbc_codec->last_tx,
&input->timestamp);
is_silence = pjmedia_silence_det_detect(ilbc_codec->vad,
input->buf,
(input->size >> 1),
NULL);
if (is_silence &&
PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 &&
silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD)
{
output->type = PJMEDIA_FRAME_TYPE_NONE;
output->buf = NULL;
output->size = 0;
output->timestamp = input->timestamp;
return PJ_SUCCESS;
} else {
ilbc_codec->last_tx = input->timestamp;
}
}
/* Convert to float */
for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) {
ilbc_codec->enc_block[i] = (float) (((pj_int16_t*)input->buf)[i]);
}
/* Encode */
iLBC_encode((unsigned char *)output->buf,
ilbc_codec->enc_block,
&ilbc_codec->enc);
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->size = ilbc_codec->enc.no_of_bytes;
output->timestamp = input->timestamp;
return PJ_SUCCESS;
}
/*
* Decode frame.
*/
static pj_status_t ilbc_codec_decode(pjmedia_codec *codec,
const struct pjmedia_frame *input,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
unsigned i;
pj_assert(ilbc_codec != NULL);
PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
return PJMEDIA_CODEC_EPCMTOOSHORT;
if (input->size != ilbc_codec->dec_frame_size)
return PJMEDIA_CODEC_EFRMINLEN;
/* Decode to temporary buffer */
iLBC_decode(ilbc_codec->dec_block, input->buf,
&ilbc_codec->dec, 1);
/* Convert decodec samples from float to short */
for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
}
output->size = (ilbc_codec->dec_samples_per_frame << 1);
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->timestamp = input->timestamp;
return PJ_SUCCESS;
}
/*
* Recover lost frame.
*/
static pj_status_t ilbc_codec_recover(pjmedia_codec *codec,
unsigned output_buf_len,
struct pjmedia_frame *output)
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
unsigned i;
pj_assert(ilbc_codec != NULL);
PJ_ASSERT_RETURN(output, PJ_EINVAL);
if (output_buf_len < (ilbc_codec->dec_samples_per_frame << 1))
return PJMEDIA_CODEC_EPCMTOOSHORT;
/* Decode to temporary buffer */
iLBC_decode(ilbc_codec->dec_block, NULL, &ilbc_codec->dec, 0);
/* Convert decodec samples from float to short */
for (i=0; i<ilbc_codec->dec_samples_per_frame; ++i) {
((short*)output->buf)[i] = (short)ilbc_codec->dec_block[i];
}
output->size = (ilbc_codec->dec_samples_per_frame << 1);
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
return PJ_SUCCESS;
}
#endif /* PJMEDIA_HAS_ILBC_CODEC */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -