static int encode_audio(struct mgcp_process_rtp_state *state, uint8_t *dst, size_t buf_size, size_t max_samples) { int nbytes = 0; size_t nsamples = 0; /* Encode samples into dst */ while (nsamples + state->dst_samples_per_frame <= max_samples) { if (nbytes + state->dst_frame_size > buf_size) { if (nbytes > 0) break; /* Not even one frame fits into the buffer */ LOGP(DMGCP, LOGL_INFO, "Encoding (RTP) buffer too small: %d > %d.\n", nbytes + state->dst_frame_size, buf_size); return -ENOSPC; } switch (state->dst_fmt) { case AF_GSM: gsm_encode(state->dst.gsm_handle, state->samples + state->sample_offs, dst); break; #ifdef HAVE_BCG729 case AF_G729: bcg729Encoder(state->dst.g729_enc, state->samples + state->sample_offs, dst); break; #endif case AF_PCMU: ulaw_encode(state->samples + state->sample_offs, dst, state->src_samples_per_frame); break; case AF_PCMA: alaw_encode(state->samples + state->sample_offs, dst, state->src_samples_per_frame); break; case AF_S16: memmove(dst, state->samples + state->sample_offs, state->dst_frame_size); break; case AF_L16: l16_encode(state->samples + state->sample_offs, dst, state->src_samples_per_frame); break; default: break; } dst += state->dst_frame_size; nbytes += state->dst_frame_size; state->sample_offs += state->dst_samples_per_frame; nsamples += state->dst_samples_per_frame; } state->sample_cnt -= nsamples; return nbytes; }
static int codec_drv_control( ErlDrvData handle, unsigned int command, char *buf, int len, char **rbuf, int rlen) { codec_data* d = (codec_data*)handle; int ret = 0; ErlDrvBinary *out; *rbuf = NULL; int n = 0; // Number of frames int i = 0; // Temporary counter switch(command) { case CMD_ENCODE: if (len % 160 != 0) break; n = len / 160; // Calculate a number of frames out = driver_alloc_binary(n*10); // n*80 bits ret = n*10; for(i = 0; i<n; i++) bcg729Encoder(d->estate, (int16_t*)buf+80*i, (uint8_t*)out->orig_bytes+10*i); *rbuf = (char *) out; break; case CMD_DECODE: if (len % 10 != 0) break; n = len / 10; // Calculate a number of frames out = driver_alloc_binary(n*160); // n*160 bytes ret = n*160; for(i = 0; i<n; i++) bcg729Decoder(d->dstate, ((uint8_t*)buf)+10*i, 0, (int16_t*)out->orig_bytes+80*i); *rbuf = (char *) out; break; default: break; } return ret; }
static switch_status_t switch_bcg729_encode(switch_codec_t *codec, switch_codec_t *other_codec, void *decoded_data, uint32_t decoded_data_len, uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag) { struct bcg729_context *context = codec->private_info; if (!context) { return SWITCH_STATUS_FALSE; } if (decoded_data_len % 160 == 0) { uint32_t new_len = 0; int16_t *ddp = decoded_data; uint8_t *edp = encoded_data; int x; int loops = (int) decoded_data_len / 160; for (x = 0; x < loops && new_len < *encoded_data_len; x++) { bcg729Encoder(context->encoder_object, ddp, edp); edp += 10; ddp += 80; new_len += 10; } if (new_len <= *encoded_data_len) { *encoded_data_len = new_len; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer overflow!!! %u >= %u\n", new_len, *encoded_data_len); return SWITCH_STATUS_FALSE; } } return SWITCH_STATUS_SUCCESS; }