jbuf.c

来自「基于sip协议的网络电话源码」· C语言 代码 · 共 572 行 · 第 1/2 页

C
572
字号
/* $Id: jbuf.c 974 2007-02-19 01:13:53Z bennylp $ *//*  * Copyright (C) 2003-2007 Benny Prijono <benny@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  *//* * Based on implementation kindly contributed by Switchlab, Ltd. */#include <pjmedia/jbuf.h>#include <pjmedia/errno.h>#include <pj/pool.h>#include <pj/assert.h>#include <pj/log.h>#include <pj/string.h>#define THIS_FILE   "jbuf.c"struct jb_framelist{    char	*flist_buffer;    int		*flist_frame_type;    unsigned	 flist_frame_size;    unsigned	 flist_max_count;    unsigned	 flist_empty;    unsigned	 flist_head;    unsigned	 flist_tail;    unsigned	 flist_origin;};typedef struct jb_framelist jb_framelist;struct pjmedia_jbuf{    pj_str_t	    name;		  // jitter buffer name    jb_framelist    jb_framelist;    pj_size_t	    jb_frame_size;	  // frame size	    unsigned	    jb_frame_ptime;	  // frame duration.    pj_size_t	    jb_max_count;	  // max frames in the jitter framelist->flist_buffer    int		    jb_level;		  // delay between source & destination					  // (calculated according of the number of get/put operations)    int		    jb_last_level;	  // last delay	    int		    jb_last_jitter;	  // last jitter calculated    int		    jb_max_hist_jitter;   // max jitter	during the last	jitter calculations    int		    jb_stable_hist;	  // num of times the delay has	been lower then	the prefetch num    unsigned	    jb_op_count;	  // of of operations.    int		    jb_last_op;		  // last operation executed on	the framelist->flist_buffer (put/get)    int		    jb_last_seq_no;	  // seq no. of	the last frame inserted	to the framelist->flist_buffer    int		    jb_prefetch;	  // no. of frame to insert before removing some					  // (at the beginning of the framelist->flist_buffer operation)    int		    jb_prefetch_cnt;	  // prefetch counter    int		    jb_min_prefetch;	  // Minimum allowable prefetch    int		    jb_max_prefetch;	  // Maximum allowable prefetch    int		    jb_status;		  // status is 'init' until the	first 'put' operation};#define JB_STATUS_INITIALIZING	0#define JB_STATUS_PROCESSING	1#define	PJ_ABS(x)	((x > 0) ? (x) : -(x))#define	PJ_MAX(x, y)	((x > y) ? (x) : (y))#define	PJ_MIN(x, y)	((x < y) ? (x) : (y))/* Enabling this would log the jitter buffer state about once per  * second. */#if 0#  define TRACE__(args)	    PJ_LOG(4,args)#else#  define TRACE__(args)#endifstatic pj_status_t jb_framelist_init( pj_pool_t *pool,				      jb_framelist *framelist,				      unsigned frame_size,				      unsigned max_count) {    PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL);    pj_bzero(framelist, sizeof(jb_framelist));    framelist->flist_frame_size = frame_size;    framelist->flist_max_count = max_count;    framelist->flist_buffer = pj_pool_zalloc(pool,					     framelist->flist_frame_size * 					     framelist->flist_max_count);    framelist->flist_frame_type = 	pj_pool_zalloc(pool, sizeof(framelist->flist_frame_type[0]) * 				framelist->flist_max_count);    framelist->flist_empty = 1;    return PJ_SUCCESS;}static pj_status_t jb_framelist_destroy(jb_framelist *framelist) {    PJ_UNUSED_ARG(framelist);    return PJ_SUCCESS;}static unsigned jb_framelist_size(jb_framelist *framelist) {    if (framelist->flist_tail == framelist->flist_head) {	return framelist->flist_empty ? 0 : framelist->flist_max_count;    } else {	return (framelist->flist_tail - framelist->flist_head + 		framelist->flist_max_count) % framelist->flist_max_count;    }}static pj_bool_t jb_framelist_get(jb_framelist *framelist,				  void *frame,				  pjmedia_jb_frame_type *p_type) {    if (!framelist->flist_empty) {	pj_memcpy(frame, 		  framelist->flist_buffer + 		    framelist->flist_head * framelist->flist_frame_size,		  framelist->flist_frame_size);	*p_type = (pjmedia_jb_frame_type) 		  framelist->flist_frame_type[framelist->flist_head];	pj_bzero(framelist->flist_buffer + 		    framelist->flist_head * framelist->flist_frame_size,		  framelist->flist_frame_size);	framelist->flist_frame_type[framelist->flist_head] = 	    PJMEDIA_JB_MISSING_FRAME;	framelist->flist_origin++;	framelist->flist_head = (framelist->flist_head + 1 ) % 				framelist->flist_max_count;	if (framelist->flist_head == framelist->flist_tail) 	    framelist->flist_empty = PJ_TRUE;		return PJ_TRUE;    } else {	pj_bzero(frame, framelist->flist_frame_size);	return PJ_FALSE;    }}static void jb_framelist_remove_head( jb_framelist *framelist,				      unsigned count) {    unsigned cur_size;    cur_size = jb_framelist_size(framelist);    if (count > cur_size) 	count = cur_size;    if (count) {	// may be done in two steps if overlapping	unsigned step1,step2;	unsigned tmp = framelist->flist_head+count;	if (tmp > framelist->flist_max_count) {	    step1 = framelist->flist_max_count - framelist->flist_head;	    step2 = count-step1;	} else {	    step1 = count;	    step2 = 0;	}	pj_bzero(framelist->flist_buffer + 		    framelist->flist_head * framelist->flist_frame_size,	          step1*framelist->flist_frame_size);	pj_memset(framelist->flist_frame_type+framelist->flist_head,		  PJMEDIA_JB_MISSING_FRAME,		  step1*sizeof(framelist->flist_frame_type[0]));	if (step2) {	    pj_bzero( framelist->flist_buffer,		      step2*framelist->flist_frame_size);	    pj_memset(framelist->flist_frame_type,		      PJMEDIA_JB_MISSING_FRAME,		      step2*sizeof(framelist->flist_frame_type[0]));	}	// update pointers	framelist->flist_origin += count;	framelist->flist_head = (framelist->flist_head + count) % 			        framelist->flist_max_count;	if (framelist->flist_head == framelist->flist_tail) 	    framelist->flist_empty = PJ_TRUE;    }}static pj_bool_t jb_framelist_put_at(jb_framelist *framelist,				     unsigned index,				     const void *frame,				     unsigned frame_size) {    unsigned where;    assert(frame_size <= framelist->flist_frame_size);    if (!framelist->flist_empty) {	unsigned max_index;	unsigned cur_size;	// too late	if (index < framelist->flist_origin) 	    return PJ_FALSE;	// too soon	max_index = framelist->flist_origin + framelist->flist_max_count - 1;	if (index > max_index)	    return PJ_FALSE;	where = (index - framelist->flist_origin + framelist->flist_head) % 	        framelist->flist_max_count;	// update framelist->flist_tail pointer	cur_size = jb_framelist_size(framelist);	if (index >= framelist->flist_origin + cur_size) {	    unsigned diff = (index - (framelist->flist_origin + cur_size));	    framelist->flist_tail = (framelist->flist_tail + diff + 1) % 				    framelist->flist_max_count;	}    } else {	where = framelist->flist_tail;	framelist->flist_origin = index;	framelist->flist_tail = (framelist->flist_tail + 1) % 				framelist->flist_max_count;	framelist->flist_empty = PJ_FALSE;    }    pj_memcpy(framelist->flist_buffer + where * framelist->flist_frame_size, 	      frame, frame_size);    framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME;    return PJ_TRUE;}enum pjmedia_jb_op{    JB_OP_INIT  = -1,    JB_OP_PUT   = 1,    JB_OP_GET   = 2};PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 					const pj_str_t *name,					unsigned frame_size, 					unsigned ptime,					unsigned max_count,					pjmedia_jbuf **p_jb){    pjmedia_jbuf *jb;    pj_status_t status;    jb = pj_pool_zalloc(pool, sizeof(pjmedia_jbuf));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?