|
|
|
|
@ -28,27 +28,16 @@
|
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
|
|
|
|
This is a wrapper for Intel IPP 0.6 G729 codec.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef TEST
|
|
|
|
|
#include "../../log.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include "amci.h"
|
|
|
|
|
#include "codecs.h"
|
|
|
|
|
#else
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#define ERROR printf
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <usc.h>
|
|
|
|
|
|
|
|
|
|
#include <bcg729/decoder.h>
|
|
|
|
|
#include <bcg729/encoder.h>
|
|
|
|
|
|
|
|
|
|
static int pcm16_2_g729(unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
|
|
|
|
|
unsigned int channels, unsigned int rate, long h_codec );
|
|
|
|
|
@ -63,7 +52,7 @@ static void g729_destroy(long h_codec);
|
|
|
|
|
static unsigned int g729_bytes2samples(long, unsigned int);
|
|
|
|
|
static unsigned int g729_samples2bytes(long, unsigned int);
|
|
|
|
|
|
|
|
|
|
static amci_codec_fmt_info_t[] gsm_fmt_description = { { AMCI_FMT_FRAME_LENGTH, 20 },
|
|
|
|
|
static amci_codec_fmt_info_t g729_fmt_description[] = { { AMCI_FMT_FRAME_LENGTH, 20 },
|
|
|
|
|
{ AMCI_FMT_FRAME_SIZE, 160 },
|
|
|
|
|
{ AMCI_FMT_ENCODED_FRAME_SIZE, 33 },
|
|
|
|
|
{ 0, 0 }
|
|
|
|
|
@ -72,8 +61,8 @@ static amci_codec_fmt_info_t[] gsm_fmt_description = { { AMCI_FMT_FRAME_LENGTH,
|
|
|
|
|
#define G729_PAYLOAD_ID 18
|
|
|
|
|
#define G729_BYTES_PER_FRAME 10
|
|
|
|
|
#define G729_SAMPLES_PER_FRAME 10
|
|
|
|
|
#define PCM_BYTES_PER_FRAME 160
|
|
|
|
|
|
|
|
|
|
#ifndef TEST
|
|
|
|
|
BEGIN_EXPORTS( "g729", AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY)
|
|
|
|
|
|
|
|
|
|
BEGIN_CODECS
|
|
|
|
|
@ -82,7 +71,7 @@ BEGIN_EXPORTS( "g729", AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY)
|
|
|
|
|
g729_bytes2samples, g729_samples2bytes
|
|
|
|
|
)
|
|
|
|
|
END_CODECS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_PAYLOADS
|
|
|
|
|
PAYLOAD( G729_PAYLOAD_ID, "G729", 8000, 8000, 1, CODEC_G729, AMCI_PT_AUDIO_FRAME )
|
|
|
|
|
END_PAYLOADS
|
|
|
|
|
@ -92,136 +81,24 @@ BEGIN_EXPORTS( "g729", AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY)
|
|
|
|
|
|
|
|
|
|
END_EXPORTS
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct stream
|
|
|
|
|
{
|
|
|
|
|
USC_Handle handle;
|
|
|
|
|
int nBanks;
|
|
|
|
|
USC_MemBank* banks;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct G729_codec
|
|
|
|
|
struct G729_codec
|
|
|
|
|
{
|
|
|
|
|
struct stream dec, enc;
|
|
|
|
|
USC_CodecInfo pInfo;
|
|
|
|
|
bcg729DecoderChannelContextStruct* dec;
|
|
|
|
|
bcg729EncoderChannelContextStruct* enc;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern USC_Fxns USC_G729I_Fxns;
|
|
|
|
|
USC_Fxns *fns = &USC_G729I_Fxns;
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
stream_alloc(USC_CodecInfo *info, struct stream *md, const char *name)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (USC_NoError != fns->std.NumAlloc(&info->params, &md->nBanks))
|
|
|
|
|
{
|
|
|
|
|
ERROR("g729_stream_alloc: can't query memory reqirements for %s\n", name);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* allocate memory for memory bank table */
|
|
|
|
|
md->banks = (USC_MemBank*)malloc(sizeof(USC_MemBank)*md->nBanks);
|
|
|
|
|
|
|
|
|
|
/* Query how big has to be each block */
|
|
|
|
|
if (USC_NoError != fns->std.MemAlloc(&info->params, md->banks))
|
|
|
|
|
{
|
|
|
|
|
ERROR("g729_stream_alloc: can't query memory bank size for %s\n", name);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate memory for each block */
|
|
|
|
|
for(i=0; i<md->nBanks; i++)
|
|
|
|
|
{
|
|
|
|
|
md->banks[i].pMem = (char*)malloc(md->banks[i].nbytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
stream_free(struct stream *st)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < st->nBanks; i++)
|
|
|
|
|
free(st->banks[i].pMem);
|
|
|
|
|
|
|
|
|
|
free(st->banks);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
stream_create(USC_CodecInfo *info, struct stream *st, const char *name)
|
|
|
|
|
{
|
|
|
|
|
if (stream_alloc(info, st, name))
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create encoder instance */
|
|
|
|
|
if(USC_NoError != fns->std.Init(&info->params, st->banks, &st->handle))
|
|
|
|
|
{
|
|
|
|
|
ERROR("g729_stream_create: can't intialize stream %s\n", name);
|
|
|
|
|
stream_free(st);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
stream_destroy(struct stream *st)
|
|
|
|
|
{
|
|
|
|
|
stream_free(st);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long g729_create(const char* format_parameters, const char** format_parameters_out,
|
|
|
|
|
amci_codec_fmt_info_t** format_description)
|
|
|
|
|
{
|
|
|
|
|
USC_CodecInfo pInfo;
|
|
|
|
|
struct G729_codec *codec;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (USC_NoError != fns->std.GetInfo((USC_Handle)NULL, &pInfo))
|
|
|
|
|
{
|
|
|
|
|
ERROR("g729: Can't query codec info\n");
|
|
|
|
|
return (0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pInfo.params.direction = 0; /* Direction: encode */
|
|
|
|
|
pInfo.params.modes.vad = 0; /* Suppress a silence compression */
|
|
|
|
|
pInfo.params.law = 0; /* Linear PCM input */
|
|
|
|
|
pInfo.params.modes.bitrate = 8000; /* pInfo.pRateTbl[pInfo.nRates-1].bitrate; */ /* Set highest bitrate */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
codec = calloc(sizeof(struct G729_codec), 1);
|
|
|
|
|
codec->enc = initBcg729EncoderChannel(0 /* no VAT/DTX detection */);
|
|
|
|
|
codec->dec = initBcg729DecoderChannel();
|
|
|
|
|
|
|
|
|
|
if (stream_create(&pInfo, &codec->enc, "encoder"))
|
|
|
|
|
{
|
|
|
|
|
free(codec);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pInfo.params.direction = 1; /* Direction: decode */
|
|
|
|
|
|
|
|
|
|
if (stream_create(&pInfo, &codec->dec, "decoder"))
|
|
|
|
|
{
|
|
|
|
|
stream_destroy(&codec->enc);
|
|
|
|
|
free(codec);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
*format_description = g729_fmt_description;
|
|
|
|
|
|
|
|
|
|
codec->pInfo = pInfo;
|
|
|
|
|
return (long) codec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -234,8 +111,8 @@ g729_destroy(long h_codec)
|
|
|
|
|
if (!h_codec)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
stream_destroy(&codec->dec);
|
|
|
|
|
stream_destroy(&codec->enc);
|
|
|
|
|
closeBcg729DecoderChannel(codec->dec);
|
|
|
|
|
closeBcg729EncoderChannel(codec->enc);
|
|
|
|
|
free(codec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -244,98 +121,55 @@ g729_destroy(long h_codec)
|
|
|
|
|
static int pcm16_2_g729(unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
|
|
|
|
|
unsigned int channels, unsigned int rate, long h_codec )
|
|
|
|
|
{
|
|
|
|
|
div_t blocks;
|
|
|
|
|
struct G729_codec *codec = (struct G729_codec *) h_codec;
|
|
|
|
|
int out_size = 0;
|
|
|
|
|
int err;
|
|
|
|
|
unsigned int out_size = 0;
|
|
|
|
|
|
|
|
|
|
if (!h_codec)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
blocks = div(size, codec->pInfo.params.framesize);
|
|
|
|
|
|
|
|
|
|
if (blocks.rem)
|
|
|
|
|
{
|
|
|
|
|
ERROR("pcm16_2_G729: number of blocks should be integral (block size = %d)\n",
|
|
|
|
|
codec->pInfo.params.framesize);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(size >= codec->pInfo.params.framesize)
|
|
|
|
|
{
|
|
|
|
|
USC_PCMStream in;
|
|
|
|
|
USC_Bitstream out;
|
|
|
|
|
|
|
|
|
|
if (size % PCM_BYTES_PER_FRAME != 0){
|
|
|
|
|
ERROR("pcm16_2_g729: number of blocks should be integral (block size = %u)\n", PCM_BYTES_PER_FRAME);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set input stream params */
|
|
|
|
|
in.bitrate = codec->pInfo.params.modes.bitrate;
|
|
|
|
|
in.nbytes = size;
|
|
|
|
|
in.pBuffer = (char*)in_buf;
|
|
|
|
|
in.pcmType = codec->pInfo.params.pcmType;
|
|
|
|
|
while(size >= PCM_BYTES_PER_FRAME){
|
|
|
|
|
/* Encode a frame */
|
|
|
|
|
uint8_t olen;
|
|
|
|
|
bcg729Encoder(codec->enc, (int16_t*)in_buf, (uint8_t*)out_buf, &olen);
|
|
|
|
|
|
|
|
|
|
/* Set output buffer */
|
|
|
|
|
out.pBuffer = (char*)out_buf;
|
|
|
|
|
size -= PCM_BYTES_PER_FRAME;
|
|
|
|
|
in_buf += PCM_BYTES_PER_FRAME;
|
|
|
|
|
|
|
|
|
|
/* Encode a frame */
|
|
|
|
|
err = fns->Encode (codec->enc.handle, &in, &out);
|
|
|
|
|
if (USC_NoError != err)
|
|
|
|
|
{
|
|
|
|
|
ERROR("pcm16_2_G729: error %d encoding\n", err);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size -= in.nbytes;
|
|
|
|
|
in_buf += in.nbytes;
|
|
|
|
|
|
|
|
|
|
out_buf += out.nbytes;
|
|
|
|
|
out_size += out.nbytes;
|
|
|
|
|
}
|
|
|
|
|
out_buf += olen;
|
|
|
|
|
out_size += olen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return out_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int g729_2_pcm16(unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
|
|
|
|
|
static int g729_2_pcm16(unsigned char* out_buf, unsigned char* in_buf, unsigned int size,
|
|
|
|
|
unsigned int channels, unsigned int rate, long h_codec )
|
|
|
|
|
{
|
|
|
|
|
/* div_t blocks; */
|
|
|
|
|
unsigned int out_size = 0;
|
|
|
|
|
int frameSize = 0;
|
|
|
|
|
int x;
|
|
|
|
|
struct G729_codec *codec = (struct G729_codec *) h_codec;
|
|
|
|
|
int err;
|
|
|
|
|
unsigned int out_size = 0;
|
|
|
|
|
|
|
|
|
|
if (!h_codec)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
for(x = 0; x < size; x += frameSize)
|
|
|
|
|
{
|
|
|
|
|
USC_PCMStream out;
|
|
|
|
|
USC_Bitstream in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
in.pBuffer = (char*)in_buf;
|
|
|
|
|
in.nbytes = size;
|
|
|
|
|
in.bitrate = codec->pInfo.params.modes.bitrate;
|
|
|
|
|
in.frametype = 3;
|
|
|
|
|
|
|
|
|
|
out.pcmType = codec->pInfo.params.pcmType;
|
|
|
|
|
out.pBuffer = (char*)out_buf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = fns->Decode (codec->dec.handle, &in, &out);
|
|
|
|
|
if (USC_NoError != err)
|
|
|
|
|
{
|
|
|
|
|
ERROR("g729_2_pcm16: error %d decoding data\n", err);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
in_buf += in.nbytes;
|
|
|
|
|
frameSize = in.nbytes;
|
|
|
|
|
|
|
|
|
|
out_buf += out.nbytes;
|
|
|
|
|
out_size += out.nbytes;
|
|
|
|
|
if (size % G729_BYTES_PER_FRAME != 0){
|
|
|
|
|
ERROR("g729_2_pcm16: number of blocks should be integral (block size = %u)\n", G729_BYTES_PER_FRAME);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(size >= G729_BYTES_PER_FRAME){
|
|
|
|
|
/* Decode a frame */
|
|
|
|
|
bcg729Decoder(codec->dec, in_buf, G729_BYTES_PER_FRAME, 0 /* no erasure */, 0 /* not SID */, 0 /* not RFC3389 */, (int16_t*)out_buf);
|
|
|
|
|
|
|
|
|
|
size -= G729_BYTES_PER_FRAME;
|
|
|
|
|
in_buf += G729_BYTES_PER_FRAME;
|
|
|
|
|
|
|
|
|
|
out_buf += PCM_BYTES_PER_FRAME;
|
|
|
|
|
out_size += PCM_BYTES_PER_FRAME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return out_size;
|
|
|
|
|
@ -346,93 +180,5 @@ static unsigned int g729_bytes2samples(long h_codec, unsigned int num_bytes) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned int g729_samples2bytes(long h_codec, unsigned int num_samples) {
|
|
|
|
|
return G729_BYTES_PER_FRAME * num_samples / G729_SAMPLES_PER_FRAME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef TEST
|
|
|
|
|
#define N 160
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
int inpcm[N];
|
|
|
|
|
unsigned char outg729[1024];
|
|
|
|
|
int outpcm[N];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void encodeFile(const char *iname, const char *oname)
|
|
|
|
|
{
|
|
|
|
|
int ifd = open(iname, O_RDONLY);
|
|
|
|
|
int ofd = open(oname, O_WRONLY|O_CREAT, 0666);
|
|
|
|
|
short ibuf[ 2 * 8000/100 ];
|
|
|
|
|
unsigned char obuf[1024];
|
|
|
|
|
int h = g729_create();
|
|
|
|
|
|
|
|
|
|
int ilen, olen;
|
|
|
|
|
|
|
|
|
|
while(0 <= (ilen = read(ifd, ibuf, sizeof(ibuf))))
|
|
|
|
|
{
|
|
|
|
|
olen = pcm16_2_g729(obuf, ibuf, ilen, 1, 8000, h);
|
|
|
|
|
|
|
|
|
|
if (olen <= 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
write(ofd, obuf, olen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g729_destroy(h);
|
|
|
|
|
close(ofd);
|
|
|
|
|
close(ifd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void decodeFile(const char *iname, const char *oname)
|
|
|
|
|
{
|
|
|
|
|
int ifd = open(iname, O_RDONLY);
|
|
|
|
|
int ofd = open(oname, O_WRONLY|O_CREAT, 0666);
|
|
|
|
|
short obuf[ 2 * 8000/100 ];
|
|
|
|
|
unsigned char ibuf[20];
|
|
|
|
|
int h = g729_create();
|
|
|
|
|
|
|
|
|
|
int ilen, olen;
|
|
|
|
|
|
|
|
|
|
while(0 <= (ilen = read(ifd, ibuf, sizeof(ibuf))))
|
|
|
|
|
{
|
|
|
|
|
olen = g729_2_pcm16(obuf, ibuf, ilen, 1, 8000, h);
|
|
|
|
|
|
|
|
|
|
if (olen <= 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
write(ofd, obuf, olen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g729_destroy(h);
|
|
|
|
|
close(ofd);
|
|
|
|
|
close(ifd);
|
|
|
|
|
return G729_BYTES_PER_FRAME * num_samples / G729_SAMPLES_PER_FRAME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "-e"))
|
|
|
|
|
{
|
|
|
|
|
printf("encoding %s to %s\n", argv[2], argv[3]);
|
|
|
|
|
encodeFile(argv[2], argv[3]);
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp(argv[1], "-d"))
|
|
|
|
|
{
|
|
|
|
|
printf("decoding %s to %s\n", argv[2], argv[3]);
|
|
|
|
|
decodeFile(argv[2], argv[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|