No voice in g729 for win mobile

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

        I've integrated g729 codec on pjsip for windows mobile from Voice
Age library. I enabled only g729 on my application and try to make a call,
but there was no voice at all rather it was a loud noice, I've been stuck on
this problem from a couple of days and I've check the blogs similar with
this problem that is post by sebastian, but none can solve the problem. I am
attaching the code of g729.c, where I used to call all the API's of Voice
Age library. Please help if somebody have the similar problem.

Thanks and Regards'
Elangbam Johnson
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20090425/1862ceee/attachment-0001.html>
-------------- next part --------------
/******************************************************************************
*                                                                             *
*                              Cpp File                                       *
*                                                                             *
*******************************************************************************
*
* 
*
*******************************************************************************
*                                                                             *
*                                         *
*                                                        *
*                                                                             *
******************************************************************************/

#include <pjmedia/codec.h>
#include <pjmedia/errno.h>
#include <pjmedia/endpoint.h>
#include <pjmedia/plc.h>
#include <pjmedia/port.h>
#include <pjmedia/silencedet.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/pool.h>
#include <pj/string.h>
#include <pj/os.h>

#include "g729.h"
#include "third_party/g729a/typedef.h"
#include "third_party/g729a/g729a_if.h"


#ifndef PJMEDIA_HAS_G729_CODEC
	#define PJMEDIA_HAS_G729_CODEC 1
#endif


/*
 * Only build this file if PJMEDIA_HAS_G729_CODEC != 0
 */
#if defined(PJMEDIA_HAS_G729_CODEC) && PJMEDIA_HAS_G729_CODEC != 0

#define PLC_DISABLED				0
#define THIS_FILE					"g729.c"

#define CLOCK_RATE				8000
#define SAMPLES_PER_FRAME		L_FRAME_G729
#define BYTES_PER_FRAME			L_PACKED_G729A
#define MILLISECONDSPERFRAME	10

/* Prototypes for g729 factory */
static pj_status_t g729_test_alloc( pjmedia_codec_factory *factory, const pjmedia_codec_info *id );
static pj_status_t g729_default_attr( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec_param *attr );
static pj_status_t g729_enum_codecs( pjmedia_codec_factory *factory, unsigned *count, pjmedia_codec_info codecs[]);
static pj_status_t g729_alloc_codec( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec **p_codec);
static pj_status_t g729_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec );

/* Prototypes for g729 implementation. */
static pj_status_t g729_codec_init( pjmedia_codec *codec, pj_pool_t *pool );
static pj_status_t g729_codec_open( pjmedia_codec *codec, pjmedia_codec_param *attr );
static pj_status_t g729_codec_close( pjmedia_codec *codec );
static pj_status_t g729_codec_modify(pjmedia_codec *codec, const pjmedia_codec_param *attr );
static pj_status_t g729_codec_parse( pjmedia_codec *codec, void *pkt, pj_size_t pkt_size, const pj_timestamp *ts, unsigned *frame_cnt, pjmedia_frame frames[]);
static pj_status_t g729_codec_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output);
static pj_status_t g729_codec_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output);

#if !PLC_DISABLED
static pj_status_t g729_codec_recover(pjmedia_codec *codec, unsigned output_buf_len, struct pjmedia_frame *output);
#endif

/* Definition for g729 codec operations. */
static pjmedia_codec_op g729_op = 
{
	&g729_codec_init,
	&g729_codec_open,
	&g729_codec_close,
	&g729_codec_modify,
	&g729_codec_parse,
	&g729_codec_encode,
	&g729_codec_decode,
#if !PLC_DISABLED
	&g729_codec_recover
#else
	NULL
#endif
};

/* Definition for g729 codec factory operations. */
static pjmedia_codec_factory_op g729_factory_op =
{
	&g729_test_alloc,
	&g729_default_attr,
	&g729_enum_codecs,
	&g729_alloc_codec,
	&g729_dealloc_codec
};

/* G729 factory */
static struct g729_codec_factory
{
	pjmedia_codec_factory   base;
	pjmedia_endpt				*endpt;
	pj_pool_t					*pool;
	pj_mutex_t					*mutex;
	pjmedia_codec				 codec_list;
} g729_codec_factory;


/* g729 codec private data. */
struct g729_data
{
	void                *encoder;
	void                *decoder;
	pj_bool_t			plc_enabled;
#if !PLC_DISABLED
	pjmedia_plc			*plc;
#endif
	pj_bool_t			vad_enabled;
	pjmedia_silence_det *vad;
	pj_timestamp		last_tx;
};



/*
 * Initialize and register g729 codec factory to pjmedia endpoint.
 */
PJ_DEF(pj_status_t) pjmedia_codec_g729_init( pjmedia_endpt *endpt )
{
	pjmedia_codec_mgr *codec_mgr;
	pj_status_t status;

	PJ_LOG(5,(THIS_FILE, "#### pjmedia_codec_g729_init()"));

	if (g729_codec_factory.pool != NULL)
	return PJ_SUCCESS;

	/* Create g729 codec factory. */
	g729_codec_factory.base.op				= &g729_factory_op;
	g729_codec_factory.base.factory_data	= NULL;
	g729_codec_factory.endpt				= endpt;

	g729_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "g729", 4000, 4000);
	if (!g729_codec_factory.pool)
	return PJ_ENOMEM;

	pj_list_init(&g729_codec_factory.codec_list);

	/* Create mutex. */
	status = pj_mutex_create_simple(g729_codec_factory.pool, "g729", &g729_codec_factory.mutex);
	if (status != PJ_SUCCESS)
	goto on_error;

	/* Get the codec manager. */
	codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
	if (!codec_mgr)
	{
		status = PJ_EINVALIDOP;
		goto on_error;
	}

	/* Register codec factory to endpoint. */
	status = pjmedia_codec_mgr_register_factory(codec_mgr, &g729_codec_factory.base);
	if (status != PJ_SUCCESS)
	goto on_error;

	/* Done. */
	return PJ_SUCCESS;

on_error:
	pj_pool_release(g729_codec_factory.pool);
	g729_codec_factory.pool = NULL;
	return status;
}



/*
 * Unregister g729 codec factory from pjmedia endpoint and deinitialize
 * the g729 codec library.
 */
PJ_DEF(pj_status_t) pjmedia_codec_g729_deinit(void)
{
	pjmedia_codec_mgr *codec_mgr;
	pj_status_t status;

	PJ_LOG(5,(THIS_FILE, "#### pjmedia_codec_g729_deinit()"));

	if (g729_codec_factory.pool == NULL)
	return PJ_SUCCESS;

	/* Get the codec manager. */
	codec_mgr = pjmedia_endpt_get_codec_mgr(g729_codec_factory.endpt);
	if (!codec_mgr)
	{
		pj_pool_release(g729_codec_factory.pool);
		g729_codec_factory.pool = NULL;
		return PJ_EINVALIDOP;
	}

	/* Unregister g729 codec factory. */
	status = pjmedia_codec_mgr_unregister_factory(codec_mgr, &g729_codec_factory.base);

	/* Destroy mutex. */
	pj_mutex_destroy(g729_codec_factory.mutex);

	/* Destroy pool. */
	pj_pool_release(g729_codec_factory.pool);
	g729_codec_factory.pool = NULL;

	return status;
}

/* 
 * Check if factory can allocate the specified codec. 
 */
static pj_status_t g729_test_alloc( 
                pjmedia_codec_factory *factory, 
                const pjmedia_codec_info *info )
{
	PJ_LOG(5,(THIS_FILE, "#### g729_test_alloc()"));

	PJ_UNUSED_ARG(factory);

	//const pj_str_t g729_tag = {"g729", 4};

	/* Check payload type. */
	if (info->pt != PJMEDIA_RTP_PT_G729)
	return PJMEDIA_CODEC_EUNSUP;

	/* Type MUST be audio. */
	if (info->type != PJMEDIA_TYPE_AUDIO)
	return PJMEDIA_CODEC_EUNSUP;

	/* Check encoding name. */
	//if (pj_stricmp(&info->encoding_name, &tag) != 0)
	//return PJMEDIA_CODEC_EUNSUP;

	/* Check clock-rate */
	if (info->clock_rate != CLOCK_RATE)
	return PJMEDIA_CODEC_EUNSUP;

	/* Channel count must be one */
	if (info->channel_cnt != 1)
	return PJMEDIA_CODEC_EUNSUP;

	/* Ignore the rest, since it's static payload type. */

	return PJ_SUCCESS;
}

/*
 * Generate default attribute.
 */
static pj_status_t g729_default_attr (
                pjmedia_codec_factory *factory, 
                const pjmedia_codec_info *id,  
                pjmedia_codec_param *attr )
{
	pjmedia_codec_fmtp empty_codec_fmt;
	pj_bzero(&empty_codec_fmt, sizeof(pjmedia_codec_fmtp));

	PJ_LOG(5,(THIS_FILE, "#### g729_default_attr()"));

	PJ_UNUSED_ARG(factory);
	PJ_UNUSED_ARG(id);

	pj_bzero(attr, sizeof(pjmedia_codec_param));
	attr->info.clock_rate  = CLOCK_RATE;				/**< Sampling rate in Hz        */
	attr->info.channel_cnt = 1;							/**< Channel count.             */
	attr->info.avg_bps	  = 8000;						/**< Average bandwidth in bits/sec  */
	attr->info.max_bps	  = 8000;						/**< Maximum bandwidth in bits/sec  */
	attr->info.pcm_bits_per_sample = 16;				/**< Bits/sample in the PCM side    */
	attr->info.frm_ptime	  = MILLISECONDSPERFRAME;	/**< Decoder frame ptime in msec.   */
	attr->info.enc_ptime   = 0;							/**< Encoder ptime, or zero if it's
																		  equal to decoder ptime.    */
	attr->info.pt			  = PJMEDIA_RTP_PT_G729;	/**< Payload type.              */
	attr->setting.frm_per_pkt = 2;  /* 2 */						/**< Number of frames per packet.   */
	attr->setting.vad		  = 0
		;	  /* 1 */					/**< Voice Activity Detector.   */
#if !PLC_DISABLED
	attr->setting.plc		  = 1;							/**< Packet loss concealment    */
#endif
	/* Default all other flag bits disabled. */
	attr->setting.cng		  = attr->setting.vad;		/**< Comfort Noise Generator.   */
	attr->setting.penh	  = 0;							/**< Perceptual Enhancement     */
	attr->setting.reserved = 0;							/**< Reserved, must be zero.    */
	attr->setting.enc_fmtp = empty_codec_fmt;			/**< Mode param in fmtp (def:0) */
	attr->setting.dec_fmtp = empty_codec_fmt;			/**< Mode param in fmtp (def:0) */

	if ((attr->setting.vad == 0) && (id->pt == PJMEDIA_RTP_PT_G729))
	{
		/* Signal G729 Annex B is being disabled (RFC 3555) */
		attr->setting.dec_fmtp.cnt = 1;
		pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb");
		pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no");
	}

	return PJ_SUCCESS;
}

/*
 * Enum codecs supported by this factory (i.e. only g729!).
 */
static pj_status_t g729_enum_codecs(
                pjmedia_codec_factory *factory, 
                unsigned *count, 
                pjmedia_codec_info codecs[])
{
	PJ_LOG(5,(THIS_FILE, "#### g729_enum_codecs()"));

	PJ_UNUSED_ARG(factory);
	PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);

	pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
	codecs[0].encoding_name = pj_str("g729");
	codecs[0].pt            = PJMEDIA_RTP_PT_G729;
	codecs[0].type          = PJMEDIA_TYPE_AUDIO;
	codecs[0].clock_rate    = CLOCK_RATE;
	codecs[0].channel_cnt   = 1;

	*count = 1;

	return PJ_SUCCESS;
}

/*
 * Allocate a new g729 codec instance.
 */
static pj_status_t g729_alloc_codec( pjmedia_codec_factory *factory, 
                    const pjmedia_codec_info *id,
                    pjmedia_codec **p_codec)
{
	pjmedia_codec *codec;
	struct g729_data *g729_data;
	pj_status_t status;

	PJ_LOG(5,(THIS_FILE, "#### g729_alloc_codec()"));

	PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
	PJ_ASSERT_RETURN(factory == &g729_codec_factory.base, PJ_EINVAL);

	pj_mutex_lock(g729_codec_factory.mutex);

	/* Get free nodes, if any. */
	if (!pj_list_empty(&g729_codec_factory.codec_list))
	{
		codec = g729_codec_factory.codec_list.next;
		pj_list_erase(codec);
	}
	else
	{
		codec = PJ_POOL_ZALLOC_T(g729_codec_factory.pool, pjmedia_codec);
		PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
		codec->op = &g729_op;
		codec->factory = factory;

		g729_data = PJ_POOL_ZALLOC_T(g729_codec_factory.pool, struct g729_data);
		codec->codec_data = g729_data;

	#if !PLC_DISABLED
	/* Create PLC */
	status = pjmedia_plc_create(
		g729_codec_factory.pool,  // pool - Pool to allocate memory for the PLC.
		CLOCK_RATE,               // clock_rate - Media sampling rate.
		SAMPLES_PER_FRAME,        // samples_per_frame - Number of samples per frame.
		0,                        // options - Must be zero for now.
		&g729_data->plc           // p_plc - Pointer to receive the PLC instance.
	);
	if (status != PJ_SUCCESS)
	{
		pj_pool_release(g729_codec_factory.pool);
		pj_mutex_unlock(g729_codec_factory.mutex);
		return status;
	}   
	#endif

		/* Create silence detector */
		status = pjmedia_silence_det_create(
			g729_codec_factory.pool,   // pool - Pool for allocating the structure.
			CLOCK_RATE,                // clock_rate - Clock rate.
			SAMPLES_PER_FRAME,         // samples_per_frame - Number of samples per frame.
			&g729_data->vad            // p_sd - Pointer to receive the silence detector instance.
		);
		if (status != PJ_SUCCESS)
		{
		  pj_pool_release(g729_codec_factory.pool);
		  pj_mutex_unlock(g729_codec_factory.mutex);
		  return status;
		}
	}

	pj_mutex_unlock(g729_codec_factory.mutex);

	*p_codec = codec;
	return PJ_SUCCESS;
}

/*
 * Free codec.
 */
static pj_status_t g729_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec )
{
	struct g729_data *g729_data;
	int i;

	PJ_LOG(5,(THIS_FILE, "#### g729_dealloc_codec()"));

	PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
	PJ_ASSERT_RETURN(factory == &g729_codec_factory.base, PJ_EINVAL);

	g729_data = (struct g729_data*) codec->codec_data;

	/* Close codec, if it's not closed. */
	g729_codec_close(codec);

#if !PLC_DISABLED
	/* Clear left samples in the PLC, since codec+plc will be reused
	* next time.
	*/
	for (i=0; i<2; ++i)
	{
		pj_int16_t frame[2*SAMPLES_PER_FRAME];
		pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame));
		pjmedia_plc_save(g729_data->plc, frame);
	}
#else
	PJ_UNUSED_ARG(i);
#endif

	/* Re-init silence_period */
	pj_set_timestamp32(&g729_data->last_tx, 0, 0);

	/* Put in the free list. */
	pj_mutex_lock(g729_codec_factory.mutex);
	pj_list_push_front(&g729_codec_factory.codec_list, codec);
	pj_mutex_unlock(g729_codec_factory.mutex);

	return PJ_SUCCESS;
}

/*
 * Init codec.
 */
static pj_status_t g729_codec_init( pjmedia_codec *codec, pj_pool_t *pool )
{
	PJ_LOG(5,(THIS_FILE, "#### g729_codec_init()"));
	PJ_UNUSED_ARG(codec);
	PJ_UNUSED_ARG(pool);
	return PJ_SUCCESS;
}

/*
 * Open codec.
 */
static pj_status_t g729_codec_open( pjmedia_codec *codec, pjmedia_codec_param *attr )
{
	struct g729_data *g729_data = (struct g729_data*) codec->codec_data;

	PJ_LOG(5,(THIS_FILE, "#### g729_codec_open()"));

	pj_assert(g729_data != NULL);
	pj_assert(g729_data->encoder == NULL && g729_data->decoder == NULL);

	/*----------------------------------------------------------------*
	*           Initialize encoder                                    *
	*-----------------------------------------------------------------*/

	PJ_LOG(5,(THIS_FILE, "#### g729_codec_open() - encoder blocksize=%i", E_IF_g729a_queryBlockSize()));   
	g729_data->encoder = malloc(E_IF_g729a_queryBlockSize());
	if (NULL == g729_data->encoder)
		return PJMEDIA_CODEC_EFAILED;

	E_IF_g729a_init(g729_data->encoder);

	if (!g729_data->encoder)
		return PJMEDIA_CODEC_EFAILED;

	/*----------------------------------------------------------------*
	*           Initialize decoder                                    *
	*-----------------------------------------------------------------*/

	PJ_LOG(5,(THIS_FILE, "#### g729_codec_open() - decoder blocksize=%i", D_IF_g729a_queryBlockSize()));   
	g729_data->decoder = malloc(D_IF_g729a_queryBlockSize());
	if (NULL == g729_data->decoder)
		return PJMEDIA_CODEC_EFAILED;

	D_IF_g729a_init(g729_data->decoder);

	if (!g729_data->decoder)
		return PJMEDIA_CODEC_EFAILED;

	g729_data->vad_enabled = (attr->setting.vad != 0);
	g729_data->plc_enabled = (attr->setting.plc != 0);

	return PJ_SUCCESS;
}

/*
 * Close codec.
 */
static pj_status_t g729_codec_close( pjmedia_codec *codec )
{
	struct g729_data *g729_data = (struct g729_data*) codec->codec_data;

	PJ_LOG(5,(THIS_FILE, "#### g729_codec_close()"));

	pj_assert(g729_data != NULL);

	if (g729_data->encoder) {
		free(g729_data->encoder);
		g729_data->encoder = NULL;
	}
	if (g729_data->decoder) {
		free(g729_data->decoder);
		g729_data->decoder = NULL;
	}

	return PJ_SUCCESS;
}


/*
 * Modify codec settings.
 */
static pj_status_t  g729_codec_modify(pjmedia_codec *codec, 
                     const pjmedia_codec_param *attr )
{
	struct g729_data *g729_data = (struct g729_data*) codec->codec_data;

	PJ_LOG(5,(THIS_FILE, "#### g729_codec_modify()"));

	pj_assert(g729_data != NULL);
	pj_assert(g729_data->encoder != NULL && g729_data->decoder != NULL);

	g729_data->vad_enabled = (attr->setting.vad != 0);
	g729_data->plc_enabled = (attr->setting.plc != 0);

	return PJ_SUCCESS;
}


/*
 * Get frames in the packet.
 */
static pj_status_t  g729_codec_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_LOG(5,(THIS_FILE, "#### g729_codec_parse() (pkt_size=%i, frame_cnt=%i", pkt_size, frame_cnt));

	PJ_UNUSED_ARG(codec);
	PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);

	while (pkt_size >= BYTES_PER_FRAME && count < *frame_cnt)
	{
		frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
		frames[count].buf  = pkt;
		frames[count].size = BYTES_PER_FRAME;
		frames[count].timestamp.u64 = ts->u64 + count * SAMPLES_PER_FRAME;

		pkt = ((char*)pkt) + BYTES_PER_FRAME;
		pkt_size -= BYTES_PER_FRAME;

		++count;
	}

	if (pkt_size && count < *frame_cnt) 
	{
		frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
		frames[count].buf  = pkt;
		frames[count].size = pkt_size;
		frames[count].timestamp.u64 = ts->u64 + count * SAMPLES_PER_FRAME;
		++count;
	}

	*frame_cnt = count;
	return PJ_SUCCESS;
}

/*
 * Encode frame.
 */
static pj_status_t g729_codec_encode( pjmedia_codec *codec, 
                     const struct pjmedia_frame *input,
                     unsigned output_buf_len, 
                     struct pjmedia_frame *output)
{
	struct g729_data *g729_data = (struct g729_data*) codec->codec_data;
	pj_int16_t *pcm_in;
	UWord8 output_buf[L_PACKED_G729AB];
	size_t in_size;
	size_t tx = 0;
	unsigned count = 0;
	Word32 result;
	int i=0;
	 
	pj_assert(g729_data && input && output);

	pcm_in = (pj_int16_t*)input->buf;
	in_size = input->size;

	PJ_ASSERT_RETURN(in_size % (2*SAMPLES_PER_FRAME) == 0, PJMEDIA_CODEC_EPCMFRMINLEN);
	PJ_ASSERT_RETURN(output_buf_len >= 10 * in_size/(2*SAMPLES_PER_FRAME), PJMEDIA_CODEC_EFRMTOOSHORT);

	//PJ_LOG(5,(THIS_FILE, "#### g729_codec_encode - input=%i", input->size));

	/* Detect silence --> g729 detects silence */
	/*change of code*/
	/*if (g729_data->vad_enabled)
	{
		pj_bool_t is_silence;
		pj_int32_t silence_duration;

		silence_duration = pj_timestamp_diff32(&g729_data->last_tx, &input->timestamp);

		is_silence = pjmedia_silence_det_detect(
			g729_data->vad,                 // sd - The silence detector instance.
			(const pj_int16_t*) input->buf, // samples - Pointer to 16-bit PCM input samples.
			input->size,                    // count - Number of samples in the input.
			NULL                            // p_level - Optional pointer to receive average signal level of the input samples.
			);

		if (is_silence && PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 &&
			 silence_duration < (PJMEDIA_CODEC_MAX_SILENCE_PERIOD*CLOCK_RATE)/1000) 
		{
			output->type = PJMEDIA_FRAME_TYPE_NONE;
			output->buf  = NULL;
			output->size = 0;
			output->timestamp.u64 = input->timestamp.u64;
			return PJ_SUCCESS;
		} 
		else 
		{
			g729_data->last_tx.u64 = input->timestamp.u64;
		}
	}
	*/
	//change of code//

	 // nblk = D_IF_g729ab_getFrameProperties(((pj_int16_t*)input->buf)[0]);
     
	/* Encode */
	output->size = 0;
	while (in_size >= 2*SAMPLES_PER_FRAME) // 160 bytes = 80 frames = 10 millisec = 1 G729-frame
	{
		result = E_IF_g729a_encode(
			g729_data->encoder,            // (Input)  Encoder handle.
			pcm_in,								  // (Input)  Buffer containing one frame of speech samples.            
			(UWord8*)&output_buf,		     // (Output) Buffer containing one frame of encoded bitstream data.
			(Word32*)&output->size,        // (Output) Size of encoded bitstream data in bytes. (11 bytes, discard first)
			g729_data->vad_enabled         // (Input)  voice activity detection.
			);

		switch(output_buf[0])
		{
		case 0: // Discontinuous Transmission mode (DTX) frame ( 1 + 0 bytes )
			memcpy(&(((unsigned char*)output->buf)[tx]), &output_buf, 1);
			PJ_LOG(5,(THIS_FILE, "#### E - DTX frame"));
			tx += 1;
			break;
		case 1: // Silence Insertion Descriptor (SID) frame ( 1 + 2 bytes )
			memcpy(&(((unsigned char*)output->buf)[tx]), &output_buf, 3);
			PJ_LOG(5,(THIS_FILE, "#### E - SID frame"));
			tx += 3;
		   break;
		case 2: // speech frame with mode information ( 1 + 10 bytes )
			memcpy(&(((unsigned char*)output->buf)[tx]), &(output_buf[1]), L_PACKED_G729A);
			//memcpy(&(((unsigned char*)output->buf)[tx]), &output_buf, L_PACKED_G729AB);
			tx += L_PACKED_G729A;//output->size; // 10 bytes = 1 G729-frame = 10 millisec
			break;
		default:
			count = 0;
			while (output->size < count)
			{
				PJ_LOG(3,(THIS_FILE, "#### E - size=%i, val=%02x", output->size, output_buf[count]));
				++count;
			}
		   break;
		}

		pcm_in += SAMPLES_PER_FRAME;		     // 160 bytes = 80 frames = 10 millisec
		in_size -= 2*SAMPLES_PER_FRAME;		  // 160 bytes = 80 frames = 10 millisec
	}

	/* Check if we don't need to transmit the frame (DTX) */
	if (tx == 0) 
	{
		output->buf					= NULL;
		output->size				= 0;
		output->timestamp.u64	= input->timestamp.u64;
		output->type				= PJMEDIA_FRAME_TYPE_NONE;

		PJ_LOG(5,(THIS_FILE, "#### g729_codec_encode() - no frame"));

		return PJ_SUCCESS;
	}

	output->size = tx;
	output->type = PJMEDIA_FRAME_TYPE_AUDIO;
	output->timestamp.u64 = input->timestamp.u64;

	return PJ_SUCCESS;
}

/*
 * Decode frame.
 */
static pj_status_t g729_codec_decode( pjmedia_codec *codec, 
                     const struct pjmedia_frame *input,
                     unsigned output_buf_len, 
                     struct pjmedia_frame *output)
{
    struct g729_data *g729_data = (struct g729_data*) codec->codec_data;
	 int count = 0;
	 int badFrameIndicator = 0;
	 unsigned char input_buf[L_PACKED_G729AB];
	 Word32 result;

    //PJ_LOG(5,(THIS_FILE, "#### g729_codec_decode - input=%i, output=%i", input->size, output_buf_len));

    pj_assert(g729_data != NULL);
    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);

    if (output_buf_len < 2*SAMPLES_PER_FRAME)
        return PJMEDIA_CODEC_EPCMTOOSHORT;

	 if (input->size == L_PACKED_G729A) // speech frame without mode information ( 10 bytes )
	 {
		 input_buf[0] = 2;  // set first byte as Speech frame.
		 memcpy(&(input_buf[1]), input->buf, L_PACKED_G729A);
	 }
	 else
	 {
		 count = 0;
		 while (input->size < (unsigned int)count)
		 {
			 PJ_LOG(3,(THIS_FILE, "#### D - in_size=%i, val=%02x", input->size, ((unsigned char *)input->buf)[count]));
			 ++count;
		 }
		 
		 switch(((unsigned char *)input->buf)[0])
		 {
		 case 0: // Discontinuous Transmission mode (DTX) frame ( 1 + 0 bytes )
			 memcpy(&input_buf, input->buf, 1);
			 break;
		 case 1: // Silence Insertion Descriptor (SID) frame ( 1 + 2 bytes )
			 memcpy(&input_buf, input->buf, 3);
		    break;
		 case 2: // speech frame with mode information ( 1 + 10 bytes )
			 memcpy(&input_buf, input->buf, L_PACKED_G729AB);
		 default:
			 PJ_LOG(3,(THIS_FILE, "#### D - Bad frame"));
			 badFrameIndicator = 1;
          break;
		 }

		 //return PJMEDIA_CODEC_EFRMTOOSHORT;
	 }

    // determine size of packed frame
    // nblk = D_IF_g729ab_getFrameProperties(((unsigned char *)input->buf)[0]);
	
    result = D_IF_g729a_decode(g729_data->decoder, (UWord8*)&input_buf, 
		 (Word16*)output->buf, badFrameIndicator);

    output->size = 2*SAMPLES_PER_FRAME;
    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
	 output->timestamp.u64 = input->timestamp.u64;

#if !PLC_DISABLED
    if (g729_data->plc_enabled)
    pjmedia_plc_save( g729_data->plc, (pj_int16_t*)output->buf);
#endif

    return PJ_SUCCESS;
}


#if !PLC_DISABLED
/*
 * Recover lost frame.
 */
static pj_status_t  g729_codec_recover(pjmedia_codec *codec,
                      unsigned output_buf_len,
                      struct pjmedia_frame *output)
{
	struct g729_data *g729_data = (struct g729_data*) codec->codec_data;

	//PJ_LOG(5,(THIS_FILE, "#### g729_codec_recover()"));

	PJ_ASSERT_RETURN(g729_data->plc_enabled, PJ_EINVALIDOP);
	PJ_ASSERT_RETURN(output_buf_len >= (2*SAMPLES_PER_FRAME), PJMEDIA_CODEC_EPCMTOOSHORT);

	output->type = PJMEDIA_FRAME_TYPE_AUDIO;
	output->size = 2*SAMPLES_PER_FRAME;

	if (g729_data->plc_enabled) 
	{
		if (g729_data->plc) 
		{
			pjmedia_plc_generate(g729_data->plc, (pj_int16_t*)output->buf);
		} 
		else
		{
			pjmedia_zero_samples((pj_int16_t*)output->buf, SAMPLES_PER_FRAME);
		}
	}
	else
	{
		pjmedia_zero_samples((pj_int16_t*)output->buf, SAMPLES_PER_FRAME);
	}

	return PJ_SUCCESS;
}
#endif

#endif  /* PJMEDIA_HAS_G729_CODEC */


[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux