diff options
Diffstat (limited to 'tinyDAV/src/audio/tdav_speakup_jitterbuffer.c')
-rwxr-xr-x | tinyDAV/src/audio/tdav_speakup_jitterbuffer.c | 361 |
1 files changed, 179 insertions, 182 deletions
diff --git a/tinyDAV/src/audio/tdav_speakup_jitterbuffer.c b/tinyDAV/src/audio/tdav_speakup_jitterbuffer.c index cccc235..0c21e41 100755 --- a/tinyDAV/src/audio/tdav_speakup_jitterbuffer.c +++ b/tinyDAV/src/audio/tdav_speakup_jitterbuffer.c @@ -2,19 +2,19 @@ * Copyright (C) 2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO 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 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO 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 DOUBANGO. * @@ -41,7 +41,7 @@ #if TSK_UNDER_WINDOWS # include <Winsock2.h> // timeval #elif defined(__SYMBIAN32__) -# include <_timeval.h> +# include <_timeval.h> #else # include <sys/time.h> #endif @@ -52,171 +52,170 @@ static int tdav_speakup_jitterbuffer_set(tmedia_jitterbuffer_t *self, const tmedia_param_t* param) { - TSK_DEBUG_ERROR("Not implemented"); - return -2; + TSK_DEBUG_ERROR("Not implemented"); + return -2; } static int tdav_speakup_jitterbuffer_open(tmedia_jitterbuffer_t* self, uint32_t frame_duration, uint32_t rate, uint32_t channels) { - tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; - if(!jitterbuffer->jbuffer){ - if(!(jitterbuffer->jbuffer = jb_new())){ - TSK_DEBUG_ERROR("Failed to create new buffer"); - return -1; - } - jitterbuffer->jcodec = JB_CODEC_OTHER; - } - jitterbuffer->ref_timestamp = 0; - jitterbuffer->frame_duration = frame_duration; - jitterbuffer->rate = rate; - jitterbuffer->channels = channels; - jitterbuffer->_10ms_size_bytes = 160 * (rate/8000); - - return 0; + tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; + if(!jitterbuffer->jbuffer) { + if(!(jitterbuffer->jbuffer = jb_new())) { + TSK_DEBUG_ERROR("Failed to create new buffer"); + return -1; + } + jitterbuffer->jcodec = JB_CODEC_OTHER; + } + jitterbuffer->ref_timestamp = 0; + jitterbuffer->frame_duration = frame_duration; + jitterbuffer->rate = rate; + jitterbuffer->channels = channels; + jitterbuffer->_10ms_size_bytes = 160 * (rate/8000); + + return 0; } static int tdav_speakup_jitterbuffer_tick(tmedia_jitterbuffer_t* self) { - return 0; + return 0; } static int tdav_speakup_jitterbuffer_put(tmedia_jitterbuffer_t* self, void* data, tsk_size_t data_size, const tsk_object_t* proto_hdr) { - tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; - const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr; + tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; + const trtp_rtp_header_t* rtp_hdr = (const trtp_rtp_header_t*)proto_hdr; int i; long now, ts; void* _10ms_buf; - uint8_t* pdata; - - if(!self || !data || !data_size || !jitterbuffer->jbuffer || !rtp_hdr){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - /* synchronize the reference timestamp */ - if(!jitterbuffer->ref_timestamp){ - uint64_t now = tsk_time_now(); - struct timeval tv; - long ts = (rtp_hdr->timestamp/(jitterbuffer->rate/1000)); - //=> Do not use (see clock_gettime() on linux): tsk_gettimeofday(&tv, tsk_null); - tv.tv_sec = (long)(now)/1000; - tv.tv_usec = (long)(now - (tv.tv_sec*1000))*1000; - - tv.tv_sec -= (ts / jitterbuffer->rate); - tv.tv_usec -= (ts % jitterbuffer->rate) * 125; - if((tv.tv_usec -= (tv.tv_usec % (TDAV_SPEAKUP_10MS * 10000))) <0){ - tv.tv_usec += 1000000; - tv.tv_sec -= 1; - } - jitterbuffer->ref_timestamp = tsk_time_get_ms(&tv); - - switch(rtp_hdr->payload_type){ - case 8: /*TMEDIA_CODEC_FORMAT_G711a*/ - case 0: /* TMEDIA_CODEC_FORMAT_G711u */ - jitterbuffer->jcodec = JB_CODEC_G711x; - break; - case 18: /* TMEDIA_CODEC_FORMAT_G729 */ - jitterbuffer->jcodec = JB_CODEC_G729A; - break; - case 3: /* TMEDIA_CODEC_FORMAT_GSM */ - jitterbuffer->jcodec = JB_CODEC_GSM_EFR; - break; - - default: - jitterbuffer->jcodec = JB_CODEC_OTHER; - break; - } - } - - // split as several 10ms frames - now = (long) (tsk_time_now()-jitterbuffer->ref_timestamp); - ts = (long)(rtp_hdr->timestamp/(jitterbuffer->rate/1000)); - pdata = (uint8_t*)data; - for(i=0; i<(int)(data_size/jitterbuffer->_10ms_size_bytes);i++){ - if((_10ms_buf = tsk_calloc(jitterbuffer->_10ms_size_bytes, 1))){ - memcpy(_10ms_buf, &pdata[i*jitterbuffer->_10ms_size_bytes], jitterbuffer->_10ms_size_bytes); - jb_put(jitterbuffer->jbuffer, _10ms_buf, JB_TYPE_VOICE, TDAV_SPEAKUP_10MS, ts, now, jitterbuffer->jcodec); - _10ms_buf = tsk_null; - } - ts += TDAV_SPEAKUP_10MS; - } - - return 0; + uint8_t* pdata; + + if(!self || !data || !data_size || !jitterbuffer->jbuffer || !rtp_hdr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + /* synchronize the reference timestamp */ + if(!jitterbuffer->ref_timestamp) { + uint64_t now = tsk_time_now(); + struct timeval tv; + long ts = (rtp_hdr->timestamp/(jitterbuffer->rate/1000)); + //=> Do not use (see clock_gettime() on linux): tsk_gettimeofday(&tv, tsk_null); + tv.tv_sec = (long)(now)/1000; + tv.tv_usec = (long)(now - (tv.tv_sec*1000))*1000; + + tv.tv_sec -= (ts / jitterbuffer->rate); + tv.tv_usec -= (ts % jitterbuffer->rate) * 125; + if((tv.tv_usec -= (tv.tv_usec % (TDAV_SPEAKUP_10MS * 10000))) <0) { + tv.tv_usec += 1000000; + tv.tv_sec -= 1; + } + jitterbuffer->ref_timestamp = tsk_time_get_ms(&tv); + + switch(rtp_hdr->payload_type) { + case 8: /*TMEDIA_CODEC_FORMAT_G711a*/ + case 0: /* TMEDIA_CODEC_FORMAT_G711u */ + jitterbuffer->jcodec = JB_CODEC_G711x; + break; + case 18: /* TMEDIA_CODEC_FORMAT_G729 */ + jitterbuffer->jcodec = JB_CODEC_G729A; + break; + case 3: /* TMEDIA_CODEC_FORMAT_GSM */ + jitterbuffer->jcodec = JB_CODEC_GSM_EFR; + break; + + default: + jitterbuffer->jcodec = JB_CODEC_OTHER; + break; + } + } + + // split as several 10ms frames + now = (long) (tsk_time_now()-jitterbuffer->ref_timestamp); + ts = (long)(rtp_hdr->timestamp/(jitterbuffer->rate/1000)); + pdata = (uint8_t*)data; + for(i=0; i<(int)(data_size/jitterbuffer->_10ms_size_bytes); i++) { + if((_10ms_buf = tsk_calloc(jitterbuffer->_10ms_size_bytes, 1))) { + memcpy(_10ms_buf, &pdata[i*jitterbuffer->_10ms_size_bytes], jitterbuffer->_10ms_size_bytes); + jb_put(jitterbuffer->jbuffer, _10ms_buf, JB_TYPE_VOICE, TDAV_SPEAKUP_10MS, ts, now, jitterbuffer->jcodec); + _10ms_buf = tsk_null; + } + ts += TDAV_SPEAKUP_10MS; + } + + return 0; } static tsk_size_t tdav_speakup_jitterbuffer_get(tmedia_jitterbuffer_t* self, void* out_data, tsk_size_t out_size) { - tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; - int jret; - - int i, _10ms_count; - long now; - short* _10ms_buf = tsk_null; - uint8_t* pout_data = (uint8_t*)out_data; - - if(!out_data || (out_size % jitterbuffer->_10ms_size_bytes)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - _10ms_count = (out_size/jitterbuffer->_10ms_size_bytes); - now = (long) (tsk_time_now() - jitterbuffer->ref_timestamp); - for(i=0; i<_10ms_count; i++){ - - jret = jb_get(jitterbuffer->jbuffer, (void**)&_10ms_buf, now, TDAV_SPEAKUP_10MS); - switch(jret){ - case JB_INTERP: - TSK_DEBUG_INFO("JB_INTERP"); - jb_reset_all(jitterbuffer->jbuffer); - memset(&pout_data[i*jitterbuffer->_10ms_size_bytes], 0, (_10ms_count*jitterbuffer->_10ms_size_bytes)-(i*jitterbuffer->_10ms_size_bytes)); - i = _10ms_count; // for exit - break; - case JB_OK: - case JB_EMPTY: - case JB_NOFRAME: - case JB_NOJB: - { - if(_10ms_buf && (jret == JB_OK)){ - /* copy data */ - memcpy(&pout_data[i*jitterbuffer->_10ms_size_bytes], _10ms_buf, jitterbuffer->_10ms_size_bytes); - } - else{ - /* copy silence */ - memset(&pout_data[i*jitterbuffer->_10ms_size_bytes], 0, jitterbuffer->_10ms_size_bytes); - } - } - - default: - break; - } - TSK_FREE(_10ms_buf); - } - - return (_10ms_count * jitterbuffer->_10ms_size_bytes); + tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; + int jret; + + int i, _10ms_count; + long now; + short* _10ms_buf = tsk_null; + uint8_t* pout_data = (uint8_t*)out_data; + + if(!out_data || (out_size % jitterbuffer->_10ms_size_bytes)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + _10ms_count = (out_size/jitterbuffer->_10ms_size_bytes); + now = (long) (tsk_time_now() - jitterbuffer->ref_timestamp); + for(i=0; i<_10ms_count; i++) { + + jret = jb_get(jitterbuffer->jbuffer, (void**)&_10ms_buf, now, TDAV_SPEAKUP_10MS); + switch(jret) { + case JB_INTERP: + TSK_DEBUG_INFO("JB_INTERP"); + jb_reset_all(jitterbuffer->jbuffer); + memset(&pout_data[i*jitterbuffer->_10ms_size_bytes], 0, (_10ms_count*jitterbuffer->_10ms_size_bytes)-(i*jitterbuffer->_10ms_size_bytes)); + i = _10ms_count; // for exit + break; + case JB_OK: + case JB_EMPTY: + case JB_NOFRAME: + case JB_NOJB: { + if(_10ms_buf && (jret == JB_OK)) { + /* copy data */ + memcpy(&pout_data[i*jitterbuffer->_10ms_size_bytes], _10ms_buf, jitterbuffer->_10ms_size_bytes); + } + else { + /* copy silence */ + memset(&pout_data[i*jitterbuffer->_10ms_size_bytes], 0, jitterbuffer->_10ms_size_bytes); + } + } + + default: + break; + } + TSK_FREE(_10ms_buf); + } + + return (_10ms_count * jitterbuffer->_10ms_size_bytes); } static int tdav_speakup_jitterbuffer_reset(tmedia_jitterbuffer_t* self) { - tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; - if(jitterbuffer->jbuffer){ - jb_reset_all(jitterbuffer->jbuffer); - return 0; - } - else{ - TSK_DEBUG_ERROR("invalid parameter"); - return -1; - } + tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; + if(jitterbuffer->jbuffer) { + jb_reset_all(jitterbuffer->jbuffer); + return 0; + } + else { + TSK_DEBUG_ERROR("invalid parameter"); + return -1; + } } static int tdav_speakup_jitterbuffer_close(tmedia_jitterbuffer_t* self) { - tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; - if(jitterbuffer->jbuffer){ - jb_destroy(jitterbuffer->jbuffer); - jitterbuffer->jbuffer = tsk_null; - } - return 0; + tdav_speakup_jitterbuffer_t *jitterbuffer = (tdav_speakup_jitterbuffer_t *)self; + if(jitterbuffer->jbuffer) { + jb_destroy(jitterbuffer->jbuffer); + jitterbuffer->jbuffer = tsk_null; + } + return 0; } @@ -228,53 +227,51 @@ static int tdav_speakup_jitterbuffer_close(tmedia_jitterbuffer_t* self) /* constructor */ static tsk_object_t* tdav_speakup_jitterbuffer_ctor(tsk_object_t * self, va_list * app) { - tdav_speakup_jitterbuffer_t *jitterbuffer = self; - TSK_DEBUG_INFO("Create speekup jitter buffer"); - if(jitterbuffer){ - /* init base */ - tmedia_jitterbuffer_init(TMEDIA_JITTER_BUFFER(jitterbuffer)); - /* init self */ - } - return self; + tdav_speakup_jitterbuffer_t *jitterbuffer = self; + TSK_DEBUG_INFO("Create speekup jitter buffer"); + if(jitterbuffer) { + /* init base */ + tmedia_jitterbuffer_init(TMEDIA_JITTER_BUFFER(jitterbuffer)); + /* init self */ + } + return self; } /* destructor */ static tsk_object_t* tdav_speakup_jitterbuffer_dtor(tsk_object_t * self) -{ - tdav_speakup_jitterbuffer_t *jitterbuffer = self; - if(jitterbuffer){ - /* deinit base */ - tmedia_jitterbuffer_deinit(TMEDIA_JITTER_BUFFER(jitterbuffer)); - /* deinit self */ - if(jitterbuffer->jbuffer){ - jb_destroy(jitterbuffer->jbuffer); - jitterbuffer->jbuffer = tsk_null; - } - } - - return self; +{ + tdav_speakup_jitterbuffer_t *jitterbuffer = self; + if(jitterbuffer) { + /* deinit base */ + tmedia_jitterbuffer_deinit(TMEDIA_JITTER_BUFFER(jitterbuffer)); + /* deinit self */ + if(jitterbuffer->jbuffer) { + jb_destroy(jitterbuffer->jbuffer); + jitterbuffer->jbuffer = tsk_null; + } + } + + return self; } /* object definition */ -static const tsk_object_def_t tdav_speakup_jitterbuffer_def_s = -{ - sizeof(tdav_speakup_jitterbuffer_t), - tdav_speakup_jitterbuffer_ctor, - tdav_speakup_jitterbuffer_dtor, - tsk_null, +static const tsk_object_def_t tdav_speakup_jitterbuffer_def_s = { + sizeof(tdav_speakup_jitterbuffer_t), + tdav_speakup_jitterbuffer_ctor, + tdav_speakup_jitterbuffer_dtor, + tsk_null, }; /* plugin definition*/ -static const tmedia_jitterbuffer_plugin_def_t tdav_speakup_jitterbuffer_plugin_def_s = -{ - &tdav_speakup_jitterbuffer_def_s, - tmedia_audio, - "Audio/video JitterBuffer based on Speakup", - - tdav_speakup_jitterbuffer_set, - tdav_speakup_jitterbuffer_open, - tdav_speakup_jitterbuffer_tick, - tdav_speakup_jitterbuffer_put, - tdav_speakup_jitterbuffer_get, - tdav_speakup_jitterbuffer_reset, - tdav_speakup_jitterbuffer_close, +static const tmedia_jitterbuffer_plugin_def_t tdav_speakup_jitterbuffer_plugin_def_s = { + &tdav_speakup_jitterbuffer_def_s, + tmedia_audio, + "Audio/video JitterBuffer based on Speakup", + + tdav_speakup_jitterbuffer_set, + tdav_speakup_jitterbuffer_open, + tdav_speakup_jitterbuffer_tick, + tdav_speakup_jitterbuffer_put, + tdav_speakup_jitterbuffer_get, + tdav_speakup_jitterbuffer_reset, + tdav_speakup_jitterbuffer_close, }; const tmedia_jitterbuffer_plugin_def_t *tdav_speakup_jitterbuffer_plugin_def_t = &tdav_speakup_jitterbuffer_plugin_def_s; |