📄 g711.c
字号:
pjmedia_codec *codec = NULL; pj_status_t status; PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL); /* Lock mutex. */ pj_mutex_lock(g711_factory.mutex); /* Allocate new codec if no more is available */ if (pj_list_empty(&g711_factory.codec_list)) { struct g711_private *codec_priv; codec = pj_pool_alloc(g711_factory.pool, sizeof(pjmedia_codec)); codec_priv = pj_pool_zalloc(g711_factory.pool, sizeof(struct g711_private)); if (!codec || !codec_priv) { pj_mutex_unlock(g711_factory.mutex); return PJ_ENOMEM; } /* Set the payload type */ codec_priv->pt = id->pt; /* Create PLC, always with 10ms ptime */ status = pjmedia_plc_create(g711_factory.pool, 8000, 80, 0, &codec_priv->plc); if (status != PJ_SUCCESS) { pj_mutex_unlock(g711_factory.mutex); return status; } /* Create VAD */ status = pjmedia_silence_det_create(g711_factory.pool, 8000, 80, &codec_priv->vad); if (status != PJ_SUCCESS) { pj_mutex_unlock(g711_factory.mutex); return status; } codec->factory = factory; codec->op = &g711_op; codec->codec_data = codec_priv; } else { codec = g711_factory.codec_list.next; pj_list_erase(codec); } /* Zero the list, for error detection in g711_dealloc_codec */ codec->next = codec->prev = NULL; *p_codec = codec; /* Unlock mutex. */ pj_mutex_unlock(g711_factory.mutex); return PJ_SUCCESS;}static pj_status_t g711_dealloc_codec(pjmedia_codec_factory *factory, pjmedia_codec *codec ){ struct g711_private *priv = codec->codec_data; pj_int16_t frame[SAMPLES_PER_FRAME]; int i; PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL); /* Check that this node has not been deallocated before */ pj_assert (codec->next==NULL && codec->prev==NULL); if (codec->next!=NULL || codec->prev!=NULL) { return PJ_EINVALIDOP; } /* Clear left samples in the PLC, since codec+plc will be reused * next time. */ for (i=0; i<2; ++i) { pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame)); pjmedia_plc_save(priv->plc, frame); } /* Lock mutex. */ pj_mutex_lock(g711_factory.mutex); /* Insert at the back of the list */ pj_list_insert_before(&g711_factory.codec_list, codec); /* Unlock mutex. */ pj_mutex_unlock(g711_factory.mutex); return PJ_SUCCESS;}static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool ){ /* There's nothing to do here really */ PJ_UNUSED_ARG(codec); PJ_UNUSED_ARG(pool); return PJ_SUCCESS;}static pj_status_t g711_open(pjmedia_codec *codec, pjmedia_codec_param *attr ){ struct g711_private *priv = codec->codec_data; priv->pt = attr->info.pt; priv->plc_enabled = (attr->setting.plc != 0); priv->vad_enabled = (attr->setting.vad != 0); return PJ_SUCCESS;}static pj_status_t g711_close( pjmedia_codec *codec ){ PJ_UNUSED_ARG(codec); /* Nothing to do */ return PJ_SUCCESS;}static pj_status_t g711_modify(pjmedia_codec *codec, const pjmedia_codec_param *attr ){ struct g711_private *priv = codec->codec_data; if (attr->info.pt != priv->pt) return PJMEDIA_EINVALIDPT; priv->plc_enabled = (attr->setting.plc != 0); priv->vad_enabled = (attr->setting.vad != 0); return PJ_SUCCESS;}static pj_status_t g711_parse( pjmedia_codec *codec, void *pkt, pj_size_t pkt_size, const pj_timestamp *ts, unsigned *frame_cnt, pjmedia_frame frames[]){ unsigned count = 0; PJ_UNUSED_ARG(codec); PJ_ASSERT_RETURN(ts && frame_cnt && frames, PJ_EINVAL); while (pkt_size >= FRAME_SIZE && count < *frame_cnt) { frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; frames[count].buf = pkt; frames[count].size = FRAME_SIZE; frames[count].timestamp.u64 = ts->u64 + SAMPLES_PER_FRAME * count; pkt = ((char*)pkt) + FRAME_SIZE; pkt_size -= FRAME_SIZE; ++count; } *frame_cnt = count; return PJ_SUCCESS;}static pj_status_t g711_encode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output){ pj_int16_t *samples = (pj_int16_t*) input->buf; struct g711_private *priv = codec->codec_data; /* Check output buffer length */ if (output_buf_len < (input->size >> 1)) return PJMEDIA_CODEC_EFRMTOOSHORT; /* Detect silence if VAD is enabled */ if (priv->vad_enabled) { pj_bool_t is_silence; pj_int32_t silence_period; silence_period = pj_timestamp_diff32(&priv->last_tx, &input->timestamp); is_silence = pjmedia_silence_det_detect(priv->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 { priv->last_tx = input->timestamp; } } /* Encode */ if (priv->pt == PJMEDIA_RTP_PT_PCMA) { unsigned i, n; pj_uint8_t *dst = output->buf; n = (input->size >> 1); for (i=0; i!=n; ++i, ++dst) { *dst = pjmedia_linear2alaw(samples[i]); } } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { unsigned i, n; pj_uint8_t *dst = output->buf; n = (input->size >> 1); for (i=0; i!=n; ++i, ++dst) { *dst = pjmedia_linear2ulaw(samples[i]); } } else { return PJMEDIA_EINVALIDPT; } output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->size = (input->size >> 1); return PJ_SUCCESS;}static pj_status_t g711_decode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output){ struct g711_private *priv = codec->codec_data; /* Check output buffer length */ PJ_ASSERT_RETURN(output_buf_len >= (input->size << 1), PJMEDIA_CODEC_EPCMTOOSHORT); /* Input buffer MUST have exactly 80 bytes long */ PJ_ASSERT_RETURN(input->size == FRAME_SIZE, PJMEDIA_CODEC_EFRMINLEN); /* Decode */ if (priv->pt == PJMEDIA_RTP_PT_PCMA) { unsigned i; pj_uint8_t *src = input->buf; pj_uint16_t *dst = output->buf; for (i=0; i!=input->size; ++i) { *dst++ = (pj_uint16_t) pjmedia_alaw2linear(*src++); } } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { unsigned i; pj_uint8_t *src = input->buf; pj_uint16_t *dst = output->buf; for (i=0; i!=input->size; ++i) { *dst++ = (pj_uint16_t) pjmedia_ulaw2linear(*src++); } } else { return PJMEDIA_EINVALIDPT; } output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->size = (input->size << 1); if (priv->plc_enabled) pjmedia_plc_save( priv->plc, output->buf); return PJ_SUCCESS;}static pj_status_t g711_recover( pjmedia_codec *codec, unsigned output_buf_len, struct pjmedia_frame *output){ struct g711_private *priv = codec->codec_data; if (!priv->plc_enabled) return PJ_EINVALIDOP; PJ_ASSERT_RETURN(output_buf_len >= SAMPLES_PER_FRAME * 2, PJMEDIA_CODEC_EPCMTOOSHORT); pjmedia_plc_generate(priv->plc, output->buf); output->size = SAMPLES_PER_FRAME * 2; return PJ_SUCCESS;}#endif /* PJMEDIA_HAS_G711_CODEC */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -