/* * 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; pj_int16_t *pcm_in; unsigned nsamples; #if defined(PJMEDIA_ILBC_CODEC_USE_COREAUDIO)&& PJMEDIA_ILBC_CODEC_USE_COREAUDIO UInt32 npackets; OSStatus err; AudioBufferList theABL; #endif pj_assert(ilbc_codec && input && output); pcm_in = (pj_int16_t*)input->buf; nsamples = input->size >> 1; PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0, PJMEDIA_CODEC_EPCMFRMINLEN); PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples / ilbc_codec->enc_samples_per_frame, PJMEDIA_CODEC_EFRMTOOSHORT); /* 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, (const pj_int16_t*)input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)) { 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; } }
/* * Encode frame. */ static pj_status_t codec2_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct codec2_data *codec2_data = (struct codec2_data*) codec->codec_data; pj_int16_t *pcm_in; unsigned in_size; // PJ_LOG(4, (THIS_FILE, "codec2 encode ....")); pj_assert(codec2_data && input && output); pcm_in = (pj_int16_t*)input->buf; in_size = input->size; // PJ_LOG(4, (THIS_FILE, "codec2 encode %d ", input->size)); PJ_ASSERT_RETURN(in_size % (CODEC2_SAMPLES_PER_FRAME*2) == 0, PJMEDIA_CODEC_EPCMFRMINLEN); //PJ_ASSERT_RETURN(output_buf_len >= BYTES_PER_FRAME * in_size/(CODEC2_SAMPLES_PER_FRAME*2), // PJMEDIA_CODEC_EFRMTOOSHORT); /* Detect silence */ if (codec2_data->vad_enabled) { pj_bool_t is_silence; pj_int32_t silence_duration; silence_duration = pj_timestamp_diff32(&codec2_data->last_tx, &input->timestamp); is_silence = pjmedia_silence_det_detect(codec2_data->vad, (const pj_int16_t*) input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)) { output->type = PJMEDIA_FRAME_TYPE_NONE; output->buf = NULL; output->size = 0; output->timestamp = input->timestamp; return PJ_SUCCESS; } else { codec2_data->last_tx = input->timestamp; } }
static pj_status_t g729_encode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct g729_private *priv = (struct g729_private*) codec->codec_data; pj_int16_t *pcm_in; unsigned in_size; // UWord8 bitstream[L_PACKED_G729A]; int nb; pj_assert(priv && input && output); pcm_in = (pj_int16_t*)input->buf; in_size = input->size; PJ_ASSERT_RETURN(in_size % 160 == 0, PJMEDIA_CODEC_EPCMFRMINLEN); PJ_ASSERT_RETURN(output_buf_len >= L_PACKED_G729A * in_size/160, 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, (const pj_int16_t*) input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)) { 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 frame. */ static pj_status_t gsm_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data; pj_int16_t *pcm_in; pj_size_t in_size; pj_assert(gsm_data && input && output); pcm_in = (pj_int16_t*)input->buf; in_size = input->size; PJ_ASSERT_RETURN(in_size % 320 == 0, PJMEDIA_CODEC_EPCMFRMINLEN); PJ_ASSERT_RETURN(output_buf_len >= 33 * in_size/320, PJMEDIA_CODEC_EFRMTOOSHORT); /* Detect silence */ if (gsm_data->vad_enabled) { pj_bool_t is_silence; pj_int32_t silence_duration; silence_duration = pj_timestamp_diff32(&gsm_data->last_tx, &input->timestamp); is_silence = pjmedia_silence_det_detect(gsm_data->vad, (const pj_int16_t*) input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)) { output->type = PJMEDIA_FRAME_TYPE_NONE; output->buf = NULL; output->size = 0; output->timestamp = input->timestamp; return PJ_SUCCESS; } else { gsm_data->last_tx = input->timestamp; } }
static pj_status_t l16_encode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct l16_data *data = (struct l16_data*) codec->codec_data; const pj_int16_t *samp = (const pj_int16_t*) input->buf; const pj_int16_t *samp_end = samp + input->size/sizeof(pj_int16_t); pj_int16_t *samp_out = (pj_int16_t*) output->buf; pj_assert(data && input && output); /* Check output buffer length */ if (output_buf_len < input->size) return PJMEDIA_CODEC_EFRMTOOSHORT; /* Detect silence */ if (data->vad_enabled) { pj_bool_t is_silence; pj_int32_t silence_duration; silence_duration = pj_timestamp_diff32(&data->last_tx, &input->timestamp); is_silence = pjmedia_silence_det_detect(data->vad, (const pj_int16_t*) input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD* (int)data->clock_rate/1000)) { output->type = PJMEDIA_FRAME_TYPE_NONE; output->buf = NULL; output->size = 0; output->timestamp = input->timestamp; return PJ_SUCCESS; } else { data->last_tx = input->timestamp; } }
/* * 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; } }
/* * Encode frame. */ static pj_status_t g726_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct g726_private *priv = (struct g726_private*) codec->codec_data; unsigned samples, i; pj_uint8_t *dst; pj_int16_t *src; unsigned code; unsigned int out_buffer = 0; int out_bits = 0; /* Check output buffer length */ if (output_buf_len < priv->encoded_frame_size) 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, (const pj_int16_t*) input->buf, (input->size >> 1), NULL); if (is_silence && (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*SAMPLE_RATE/1000)) { 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 frame. */ static pj_status_t amr_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct amr_data *amr_data = (struct amr_data*) codec->codec_data; unsigned char *bitstream; pj_int16_t *speech; unsigned nsamples, samples_per_frame; enum {MAX_FRAMES_PER_PACKET = 16}; pjmedia_frame frames[MAX_FRAMES_PER_PACKET]; pj_uint8_t *p; unsigned i, out_size = 0, nframes = 0; pj_size_t payload_len; unsigned dtx_cnt, sid_cnt; pj_status_t status; pj_assert(amr_data != NULL); PJ_ASSERT_RETURN(input && output, PJ_EINVAL); nsamples = input->size >> 1; samples_per_frame = amr_data->clock_rate * FRAME_LENGTH_MS / 1000; PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, PJMEDIA_CODEC_EPCMFRMINLEN); nframes = nsamples / samples_per_frame; PJ_ASSERT_RETURN(nframes <= MAX_FRAMES_PER_PACKET, PJMEDIA_CODEC_EFRMTOOSHORT); /* Encode the frames */ speech = (pj_int16_t*)input->buf; bitstream = (unsigned char*)output->buf; while (nsamples >= samples_per_frame) { int size; if (amr_data->enc_setting.amr_nb) { #ifdef USE_AMRNB size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode, speech, bitstream, 0); #else size = 0; #endif } else { #ifdef USE_AMRWB size = E_IF_encode (amr_data->encoder, amr_data->enc_mode, speech, bitstream, 0); #else size = 0; #endif } if (size == 0) { output->size = 0; output->buf = NULL; output->type = PJMEDIA_FRAME_TYPE_NONE; TRACE_((THIS_FILE, "AMR encode() failed")); return PJMEDIA_CODEC_EFAILED; } nsamples -= samples_per_frame; speech += samples_per_frame; bitstream += size; out_size += size; TRACE_((THIS_FILE, "AMR encode(): mode=%d, size=%d", amr_data->enc_mode, out_size)); } /* Pack payload */ p = (pj_uint8_t*)output->buf + output_buf_len - out_size; pj_memmove(p, output->buf, out_size); dtx_cnt = sid_cnt = 0; for (i = 0; i < nframes; ++i) { pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*) &frames[i].bit_info; info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F); info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01); info->mode = (pj_int8_t)amr_data->enc_mode; info->start_bit = 0; frames[i].buf = p + 1; if (amr_data->enc_setting.amr_nb) { frames[i].size = (info->frame_type <= 8)? pjmedia_codec_amrnb_framelen[info->frame_type] : 0; } else { frames[i].size = (info->frame_type <= 9)? pjmedia_codec_amrwb_framelen[info->frame_type] : 0; } p += frames[i].size + 1; /* Count the number of SID and DTX frames */ if (info->frame_type == 15) /* DTX*/ ++dtx_cnt; else if (info->frame_type == 8) /* SID */ ++sid_cnt; } /* VA generates DTX frames as DTX+SID frames switching quickly and it * seems that the SID frames occur too often (assuming the purpose is * only for keeping NAT alive?). So let's modify the behavior a bit. * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD * milliseconds. */ if (sid_cnt + dtx_cnt == nframes) { pj_int32_t dtx_duration; dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, &input->timestamp); if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD* amr_data->clock_rate/1000) { output->size = 0; output->type = PJMEDIA_FRAME_TYPE_NONE; output->timestamp = input->timestamp; return PJ_SUCCESS; } } payload_len = output_buf_len; status = pjmedia_codec_amr_pack(frames, nframes, &amr_data->enc_setting, output->buf, &payload_len); if (status != PJ_SUCCESS) { output->size = 0; output->buf = NULL; output->type = PJMEDIA_FRAME_TYPE_NONE; TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status)); return status; } output->size = payload_len; output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->timestamp = input->timestamp; amr_data->last_tx = input->timestamp; return PJ_SUCCESS; }