📄 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -