Assumed the G723.1 API usage is correct, all the params seem to be fine. Have you tried to disable the VAD/DTX (this may cause the parser doesn't parse correctly)? Or tried the codec in a simple application (unit test)? Regards, nanang 2008/6/9 sre kdkjf <kk_kksri at yahoo.com>: > Hi > > i did the same way how you told to me... > > But as the audio is not at all clear...it is coming lot of choppy..with lot > of disturbance. > > i am sending the G723.c source file....how i made changes.. > > could you please go through this file and let me know what changes i need to > make out. > > if it works fine it would be great help ful for me... > > i am waiting for your valuable reply. > > Thankyou. > > Nanang Izzuddin <nanang at pjsip.org> wrote: > > Sorry, this should be: > > bytes per frame: 320 -> 480 > encoded bytes per frame: 33 -> 24 > samples per frame: 160 -> 240 > > Regards, > nanang > > > 2008/6/6 Nanang Izzuddin : >> Hi, >> >> It seems to be G.723.1 (G.723 is different codec). For bitrate >> 6.3kbps, the attributes must be: >> attr->info.avg_bps = 6400; // integer calculation in stream may cause >> truncation, bigger value is safer, and it won't affect the real >> bitrate. >> attr->info.pcm_bits_per_sample = 16; // as it should be >> (the rest is fine) >> >> Moreover, as you said your reference is GSM wrapper, there are >> hardcoded values you need to modify in your G.723.1 wrapper: >> bytes per frame: 320 -> 240 >> encoded bytes per frame: 33 -> 24 >> samples per frame: 160 -> 120 >> >> Good luck! >> >> nanang >> >> >> 2008/6/6 sre kdkjf : >>> >>> Hi All, >>> >>> >>> i am making a sample application using pjsip stack. in the pjsip stack i >>> am trying to include audio codec G723. >>> >>> i had added G723 codec in the same way of GSM Codec, as it is added in >>> the existing pjsip stack. >>> whenever i made a call from A to B, once the call is in connected state, >>> G723 rtp data is flowing from one end to other end. >>> >>> the problem is, the audio is choppy, in the rtp data G723 data is flowing >>> from A to B. But the no.of frames flowing from one end to other end is >>> coming less than 24. >>> >>> And the bitrate i am using here is 6.3kbps. even then the bitrate coming >>> is 5.3 kbps. >>> >>> whenever i am using microphone to talk, the bit rate i am getting is 5.3 >>> kbps. >>> >>> >>> when the no.of frames are getting less than the actual frame rate i am >>> getting error. >>> >>> PJMEDIA_CODEC_EFRMTOOSHORT >>> >>> so whenever the no. of frames per packet is less than the actual size, >>> the output buffer is also less than the actual rate. >>> >>> at that time i am getting an error like >>> >>> PJMEDIA_CODEC_EPCMTOOSHORT. >>> >>> the attribute values i am using for G723 codec are as given below. >>> >>> pj_bzero(attr, >>> sizeof(pjmedia_codec_param)); >>> attr->info.clock_rate = 8000; >>> attr->info.channel_cnt = 1; >>> attr->info.avg_bps = 6300; >>> attr->info.pcm_bits_per_sample = 24; >>> attr->info.frm_ptime = 30; >>> attr->info.pt = PJMEDIA_RTP_PT_G723; >>> attr->setting.frm_per_pkt = 1; >>> attr->setting.vad = 1; >>> >>> even i had changed the bits per samples to 16. even then the same problem >>> i am getting. >>> >>> >>> so any body please help me out, to how to solve the audio issues by using >>> G723 codec. >>> >>> waiting for valuable reply. >>> >>> Thankyou. >>> >>> _______________________________________________ >>> Visit our blog: http://blog.pjsip.org >>> >>> pjsip mailing list >>> pjsip at lists.pjsip.org >>> http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >>> >> > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip at lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > > > /* $Id: gsm.c 1267 2007-05-11 18:48:23Z bennylp $ */ > /* > * Copyright (C)2003-2007 Benny Prijono <benny at prijono.org> > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > * the Free Software Foundation; either version 2 of the License, or > * (at your option) any later version. > * > * This program is distributed in the hope that it will be useful, > * but WITHOUT ANY WARRANTY; without even the implied warranty of > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details. > * > * You should have received a copy of the GNU General Public License > * along with this program; if not, write to the Free Software > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > */ > #include <pjmedia-codec/g723.h> > #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/pool.h> > #include <pj/string.h> > #include <pj/os.h> > //#include "../../third_party/gsm/inc/gsm.h" > > #include <pjmedia-codec/g723dll.h> > > typedef signed short sint15; > typedef unsigned char uint8; > typedef int sint31; > > /* > * Only build this file if PJMEDIA_HAS_G723_CODEC != 0 > */ > #if defined(PJMEDIA_HAS_G723_CODEC) && PJMEDIA_HAS_G723_CODEC != 0 > > /* We removed PLC in 0.6 */ > #define PLC_DISABLED 1 > > > /* Prototypes for G723 factory */ > static pj_status_t g723_test_alloc( pjmedia_codec_factory *factory, > const pjmedia_codec_info *id ); > static pj_status_t g723_default_attr( pjmedia_codec_factory *factory, > const pjmedia_codec_info *id, > pjmedia_codec_param *attr ); > static pj_status_t g723_enum_codecs( pjmedia_codec_factory *factory, > unsigned *count, > pjmedia_codec_info codecs[]); > static pj_status_t g723_alloc_codec( pjmedia_codec_factory *factory, > const pjmedia_codec_info *id, > pjmedia_codec **p_codec); > static pj_status_t g723_dealloc_codec( pjmedia_codec_factory *factory, > pjmedia_codec *codec ); > > /* Prototypes for G723 implementation. */ > static pj_status_t g723_codec_init( pjmedia_codec *codec, > pj_pool_t *pool ); > static pj_status_t g723_codec_open( pjmedia_codec *codec, > pjmedia_codec_param *attr ); > static pj_status_t g723_codec_close( pjmedia_codec *codec ); > static pj_status_t g723_codec_modify(pjmedia_codec *codec, > const pjmedia_codec_param *attr ); > static pj_status_t g723_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 g723_codec_encode( pjmedia_codec *codec, > const struct pjmedia_frame *input, > unsigned output_buf_len, > struct pjmedia_frame *output); > static pj_status_t g723_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 g723_codec_recover(pjmedia_codec *codec, > unsigned output_buf_len, > struct pjmedia_frame *output); > #endif > > /* Definition for G723 codec operations. */ > static pjmedia_codec_op g723_op = > { > &g723_codec_init, > &g723_codec_open, > &g723_codec_close, > &g723_codec_modify, > &g723_codec_parse, > &g723_codec_encode, > &g723_codec_decode, > #if !PLC_DISABLED > &g723_codec_recover > #else > NULL > #endif > }; > > /* Definition for G723 codec factory operations. */ > static pjmedia_codec_factory_op g723_factory_op = > { > &g723_test_alloc, > &g723_default_attr, > &g723_enum_codecs, > &g723_alloc_codec, > &g723_dealloc_codec > }; > > /* G723 factory */ > static struct g723_codec_factory > { > pjmedia_codec_factory base; > pjmedia_endpt *endpt; > pj_pool_t *pool; > pj_mutex_t *mutex; > pjmedia_codec codec_list; > } g723_codec_factory; > > > /* G723 codec private data. */ > struct g723_data > { > struct g723_state *encoder; > struct g723_state *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 G723 codec factory to pjmedia endpoint. > */ > PJ_DEF(pj_status_t) pjmedia_codec_g723_init( pjmedia_endpt *endpt ) > { > pjmedia_codec_mgr *codec_mgr; > pj_status_t status; > > if (g723_codec_factory.pool != NULL) > return PJ_SUCCESS; > > /* Create G723 codec factory. */ > g723_codec_factory.base.op = &g723_factory_op; > g723_codec_factory.base.factory_data = NULL; > g723_codec_factory.endpt = endpt; > > g723_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "g723.1", > 4000, > 4000); > if (!g723_codec_factory.pool) > return PJ_ENOMEM; > > pj_list_init(&g723_codec_factory.codec_list); > > /* Create mutex. */ > status = pj_mutex_create_simple(g723_codec_factory.pool, "g723.1", > &g723_codec_factory.mutex); > if (status != PJ_SUCCESS) > goto on_error; > > /* Enable high pass filter */ > g723_set_hp(1); > > /* Enable post filter */ > g723_set_pf(1); > > /* Enable VAD */ > g723_set_vx(1); > > /* Use 6.3kbps rate */ > g723_set_rate(0); > > > Init_Coder_G723(); > Init_Decoder_G723(); > > /* 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, > &g723_codec_factory.base); > if (status != PJ_SUCCESS) > goto on_error; > > /* Done. */ > return PJ_SUCCESS; > > on_error: > pj_pool_release(g723_codec_factory.pool); > g723_codec_factory.pool = NULL; > return status; > } > > > > /* > * Unregister G723 codec factory from pjmedia endpoint and deinitialize > * the G723 codec library. > */ > PJ_DEF(pj_status_t) pjmedia_codec_g723_deinit(void) > { > pjmedia_codec_mgr *codec_mgr; > pj_status_t status; > > > if (g723_codec_factory.pool == NULL) > return PJ_SUCCESS; > > /* We don't want to deinit if there's outstanding codec. */ > /* This is silly, as we'll always have codec in the list if > we ever allocate a codec! A better behavior maybe is to > deallocate all codecs in the list. > pj_mutex_lock(gsm_codec_factory.mutex); > if (!pj_list_empty(&gsm_codec_factory.codec_list)) { > pj_mutex_unlock(gsm_codec_factory.mutex); > return PJ_EBUSY; > } > */ > > /* Get the codec manager. */ > codec_mgr = pjmedia_endpt_get_codec_mgr(g723_codec_factory.endpt); > if (!codec_mgr) { > pj_pool_release(g723_codec_factory.pool); > g723_codec_factory.pool = NULL; > return PJ_EINVALIDOP; > } > > /* Unregister G723 codec factory. */ > status = pjmedia_codec_mgr_unregister_factory(codec_mgr, > &g723_codec_factory.base); > > /* Destroy mutex. */ > pj_mutex_destroy(g723_codec_factory.mutex); > > /* Destroy pool. */ > pj_pool_release(g723_codec_factory.pool); > g723_codec_factory.pool = NULL; > > return status; > } > > /* > * Check if factory can allocate the specified codec. > */ > static pj_status_t g723_test_alloc( pjmedia_codec_factory *factory, > const pjmedia_codec_info *info ) > { > PJ_UNUSED_ARG(factory); > > /* Check payload type. */ > if (info->pt != PJMEDIA_RTP_PT_G723) > return PJMEDIA_CODEC_EUNSUP; > > /* Ignore the rest, since it's static payload type. */ > > return PJ_SUCCESS; > } > > /* > * Generate default attribute. > */ > static pj_status_t g723_default_attr (pjmedia_codec_factory *factory, > const pjmedia_codec_info *id, > pjmedia_codec_param *attr ) > { > PJ_UNUSED_ARG(factory); > PJ_UNUSED_ARG(id); > > pj_bzero(attr, sizeof(pjmedia_codec_param)); > attr->info.clock_rate = 8000; > attr->info.channel_cnt = 1; > attr->info.avg_bps = 6400; > attr->info.pcm_bits_per_sample = 16; > attr->info.frm_ptime = 30; > attr->info.pt = PJMEDIA_RTP_PT_G723; > > attr->setting.frm_per_pkt = 1; > attr->setting.vad = 1; > #if !PLC_DISABLED > attr->setting.plc = 1; > #endif > > /* Default all other flag bits disabled. */ > > return PJ_SUCCESS; > } > > /* > * Enum codecs supported by this factory (i.e. only G723!). > */ > static pj_status_t g723_enum_codecs(pjmedia_codec_factory *factory, > unsigned *count, > pjmedia_codec_info 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("G723.1"); > codecs[0].pt = PJMEDIA_RTP_PT_G723; > codecs[0].type = PJMEDIA_TYPE_AUDIO; > codecs[0].clock_rate = 8000; > codecs[0].channel_cnt = 1; > > *count = 1; > > return PJ_SUCCESS; > } > > /* > * Allocate a new G723 codec instance. > */ > static pj_status_t g723_alloc_codec( pjmedia_codec_factory *factory, > const pjmedia_codec_info *id, > pjmedia_codec **p_codec) > { > pjmedia_codec *codec; > struct g723_data *g723_data; > pj_status_t status; > > PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL); > PJ_ASSERT_RETURN(factory == &g723_codec_factory.base, PJ_EINVAL); > > > pj_mutex_lock(g723_codec_factory.mutex); > > /* Get free nodes, if any. */ > if (!pj_list_empty(&g723_codec_factory.codec_list)) { > codec = g723_codec_factory.codec_list.next; > pj_list_erase(codec); > } else { > codec = PJ_POOL_ZALLOC_T(g723_codec_factory.pool, pjmedia_codec); > PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM); > codec->op = &g723_op; > codec->factory = factory; > > g723_data = PJ_POOL_ZALLOC_T(g723_codec_factory.pool, struct > g723_data); > codec->codec_data = g723_data; > > #if !PLC_DISABLED > /* Create PLC */ > status = pjmedia_plc_create(g723_codec_factory.pool, 8000, > 240, 0, &g723_data->plc); > if (status != PJ_SUCCESS) { > pj_mutex_unlock(g723_codec_factory.mutex); > return status; > } > #endif > > /* Create silence detector */ > status = pjmedia_silence_det_create(g723_codec_factory.pool, > 8000, 240, > &g723_data->vad); > if (status != PJ_SUCCESS) { > pj_mutex_unlock(g723_codec_factory.mutex); > return status; > } > } > > pj_mutex_unlock(g723_codec_factory.mutex); > > *p_codec = codec; > return PJ_SUCCESS; > } > > /* > * Free codec. > */ > static pj_status_t g723_dealloc_codec( pjmedia_codec_factory *factory, > pjmedia_codec *codec ) > { > struct g723_data *g723_data; > int i; > > PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL); > PJ_ASSERT_RETURN(factory == &g723_codec_factory.base, PJ_EINVAL); > > g723_data = (struct g723_data*) codec->codec_data; > > /* Close codec, if it's not closed. */ > g723_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[240]; > pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame)); > pjmedia_plc_save(g723_data->plc, frame); > } > #else > PJ_UNUSED_ARG(i); > #endif > > /* Re-init silence_period */ > pj_set_timestamp32(&g723_data->last_tx, 0, 0); > > /* Put in the free list. */ > pj_mutex_lock(g723_codec_factory.mutex); > pj_list_push_front(&g723_codec_factory.codec_list, codec); > pj_mutex_unlock(g723_codec_factory.mutex); > > return PJ_SUCCESS; > } > > /* > * Init codec. > */ > static pj_status_t g723_codec_init( pjmedia_codec *codec, > pj_pool_t *pool ) > { > PJ_UNUSED_ARG(codec); > PJ_UNUSED_ARG(pool); > > /* Enable high pass filter */ > g723_set_hp(1); > /* Enable post filter */ > g723_set_pf(1); > /* Enable VAD */ > g723_set_vx(1); > /* Use 6.3kbps rate */ > g723_set_rate(0); > > Init_Coder_G723(); > Init_Decoder_G723(); > > return PJ_SUCCESS; > } > > /* > * Open codec. > */ > static pj_status_t g723_codec_open( pjmedia_codec *codec, > pjmedia_codec_param *attr ) > { > struct g723_data *g723_data = (struct g723_data*) codec->codec_data; > > pj_assert(g723_data != NULL); > pj_assert(g723_data->encoder == NULL && g723_data->decoder == NULL); > > /* g723_data->encoder = gsm_create(); > if (!gsm_data->encoder) > return PJMEDIA_CODEC_EFAILED; > > gsm_data->decoder = gsm_create(); > if (!gsm_data->decoder) > return PJMEDIA_CODEC_EFAILED; > > gsm_data->vad_enabled = (attr->setting.vad != 0); > gsm_data->plc_enabled = (attr->setting.plc != 0); > */ > return PJ_SUCCESS; > } > > /* > * Close codec. > */ > static pj_status_t g723_codec_close( pjmedia_codec *codec ) > { > struct g723_data *g723_data = (struct g723_data*) codec->codec_data; > > pj_assert(g723_data != NULL); > > /*if (gsm_data->encoder) { > gsm_destroy(gsm_data->encoder); > gsm_data->encoder = NULL; > } > if (gsm_data->decoder) { > gsm_destroy(gsm_data->decoder); > gsm_data->decoder = NULL; > }*/ > > return PJ_SUCCESS; > } > > > /* > * Modify codec settings. > */ > static pj_status_t g723_codec_modify(pjmedia_codec *codec, > const pjmedia_codec_param *attr ) > { > struct g723_data *g723_data = (struct g723_data*) codec->codec_data; > > /* pj_assert(gsm_data != NULL); > pj_assert(gsm_data->encoder != NULL && gsm_data->decoder != NULL); > > gsm_data->vad_enabled = (attr->setting.vad != 0); > gsm_data->plc_enabled = (attr->setting.plc != 0);*/ > > return PJ_SUCCESS; > } > > > /* > * Get frames in the packet. > */ > static pj_status_t g723_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_UNUSED_ARG(codec); > > PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL); > > while (pkt_size >= 24 && count < *frame_cnt) { > frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; > frames[count].buf = pkt; > frames[count].size = 24; > frames[count].timestamp.u64 = ts->u64 + count * 240; > > pkt = ((char*)pkt) + 24; > pkt_size -= 24; > > ++count; > } > > *frame_cnt = count; > return PJ_SUCCESS; > } > > /* > * Encode frame. > */ > static pj_status_t g723_codec_encode( pjmedia_codec *codec, > const struct pjmedia_frame *input, > unsigned output_buf_len, > struct pjmedia_frame *output) > { > struct g723_data *g723_data = (struct g723_data*) codec->codec_data; > > //pj_assert(g723_data != NULL); > // PJ_ASSERT_RETURN(input && output, PJ_EINVAL); > > /*if (output_buf_len < 24) > return PJMEDIA_CODEC_EFRMTOOSHORT;*/ > > //PJ_ASSERT_RETURN(input->size==480, PJMEDIA_CODEC_EPCMFRMINLEN); > > /* Detect silence */ > /* if (g723_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) > { > 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; > } > }*/ > > /* Encode */ > > g723_set_rate(0); > g723_coder((sint15 *)input->buf,(uint8 *)output->buf); > > output->size = 24; > output->type = PJMEDIA_FRAME_TYPE_AUDIO; > > return PJ_SUCCESS; > } > > /* > * Decode frame. > */ > static pj_status_t g723_codec_decode( pjmedia_codec *codec, > const struct pjmedia_frame *input, > unsigned output_buf_len, > struct pjmedia_frame *output) > { > struct g723_data *g723_data = (struct g723_data*) codec->codec_data; > > /*pj_assert(g723_data != NULL); > PJ_ASSERT_RETURN(input && output, PJ_EINVAL); > > if (output_buf_len < 480) > return PJMEDIA_CODEC_EPCMTOOSHORT; > > if (input->size < 24) > return PJMEDIA_CODEC_EFRMTOOSHORT;*/ > > g723_set_rate(0); > g723_decoder((sint15 *)output->buf,(char *)input->buf,0); > > /* gsm_decode(gsm_data->decoder, > (unsigned char*)input->buf, > (short*)output->buf);*/ > > output->size = 480; > > > output->type = PJMEDIA_FRAME_TYPE_AUDIO; > > #if !PLC_DISABLED > /* if (g723_data->plc_enabled) > pjmedia_plc_save( gsm_data->plc, output->buf);*/ > #endif > > return PJ_SUCCESS; > } > > > #if !PLC_DISABLED > /* > * Recover lost frame. > */ > static pj_status_t g723_codec_recover(pjmedia_codec *codec, > unsigned output_buf_len, > struct pjmedia_frame *output) > { > struct g723_data *g723_data = codec->codec_data; > > /* PJ_ASSERT_RETURN(g723_data->plc_enabled, PJ_EINVALIDOP); > > PJ_ASSERT_RETURN(output_buf_len >= 480, PJMEDIA_CODEC_EPCMTOOSHORT);*/ > > pjmedia_plc_generate(g723_data->plc, output->buf); > > output->size = 480; > > // output->size = 240; > > return PJ_SUCCESS; > } > #endif > > > #endif /* PJMEDIA_HAS_G723_CODEC */ > > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip at lists.pjsip.org > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org > >