Sam Kaufman wrote:
Hi.

Have there been any attempts at developing a subclass of AmAudio to act as an 
interface to GStreamer (pipelines)?

I would like to use the GStreamer G.729 implementation.
I think it will be easier and more efficient to make a wrapper around the g729 codec directly, without gstreamer. In gstreamer, can you do the processing in chunks your own thread, without the gst main loop? Otherwise you have some buffering delay there.

Attached is a wrapper by Vadim Lebedev for the Intel IPP G729 codec. While the wrapper's license is BSD, of course all patent restrictions, the original IPP code license, ianal etc apply.

If you adapt it to work with current SEMS (AFAIR you would need to add little pieces in the g729_create), and could post patches and/or some instructions, that would be nice.

Stefan


Sam
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems



--
Stefan Sayer
VoIP Services Consulting and Development

Warschauer Str. 24
10243 Berlin

tel:+491621366449
sip:[email protected]
email/xmpp:[email protected]


/*

  This file is part of SEMS, a free SIP media server.

 Copyright (c) 2007, Vadim Lebedev
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the <organization> nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (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.5 G729 codec.

*/

#ifndef TEST
#include "amci.h"
#include "codecs.h"
#include "../../log.h"
#else
#include <stdio.h>
#define ERROR  printf
#endif


#include <stdlib.h>
#include <usc.h>


static int pcm16_2_g729(unsigned char* out_buf, unsigned char* in_buf, unsigned int size, 
		       unsigned int channels, unsigned int rate, int h_codec );

static int g729_2_pcm16(unsigned char* out_buf, unsigned char* in_buf, unsigned int size, 
		       unsigned int channels, unsigned int rate, int h_codec );

static int  g729_create();
static void g729_destroy(int h_codec);

#ifndef TEST 
BEGIN_EXPORTS( "g729" )

    BEGIN_CODECS
      CODEC( CODEC_G729, 1, pcm16_2_g729, g729_2_pcm16, 
	     (amci_codec_init_t)g729_create, (amci_codec_destroy_t)g729_destroy )
    END_CODECS
    
    BEGIN_PAYLOADS
      PAYLOAD( 18, "G729", 8000, 1, CODEC_G729, AMCI_PT_AUDIO_FRAME )
    END_PAYLOADS

    BEGIN_FILE_FORMATS
    END_FILE_FORMATS

END_EXPORTS

#endif

struct stream
{
  USC_Handle  handle;
  int nBanks;
  USC_MemBank*  banks;
};

struct G729_codec 
{
  struct  stream  dec, enc;
  USC_CodecInfo pInfo;  
};


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 = (unsigned 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);
}


int g729_create()
{
    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);

    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;
      }

    codec->pInfo = pInfo;
    return (int) codec;
}


static void
g729_destroy(int h_codec)
{
    struct G729_codec *codec = (struct G729_codec *) h_codec;

    if (h_codec)
      return;

    stream_destroy(&codec->dec);
    stream_destroy(&codec->enc);
    free(codec);
}



static int pcm16_2_g729(unsigned char* out_buf, unsigned char* in_buf, unsigned int size, 
		       unsigned int channels, unsigned int rate, int h_codec )
{
    div_t blocks;
    struct G729_codec *codec = (struct G729_codec *) h_codec;
    int out_size = 0;
    int err;

    if (!h_codec)
      return -1;
    
    blocks = div(size, codec->pInfo.framesize);

    if (blocks.rem)
      {
	ERROR("pcm16_2_G729: number of blocks should be integral (block size = %d)\n", codec->pInfo.framesize);
	return -1;
      }

   

    while(size >= codec->pInfo.framesize) 
      {
        USC_PCMStream in;
        USC_Bitstream out;
   

        /* Set input stream params */
        in.bitrate = codec->pInfo.params.modes.bitrate;
        in.nbytes = size;
        in.pBuffer = in_buf;
        in.pcmType = codec->pInfo.pcmType;

        /* Set output buffer */
        out.pBuffer = out_buf;

        /* 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;
      }

    return out_size;
}

static int g729_2_pcm16(unsigned char* out_buf, unsigned char* in_buf, unsigned int size, 
		       unsigned int channels, unsigned int rate, int 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;

    if (!h_codec)
      return -1;

    for(x = 0; x < size; x += frameSize) 
      {
        USC_PCMStream out;
        USC_Bitstream in;
	
	
	in.pBuffer = in_buf;
	in.nbytes = size;
	in.bitrate = codec->pInfo.params.modes.bitrate;
	in.frametype = 3;

	out.pcmType = codec->pInfo.pcmType;
	out.pBuffer = 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;
      }

    return out_size;
}


#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);
}
  

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
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems

Reply via email to