⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jbuf.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: jbuf.c 1266 2007-05-11 15:14:34Z 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"


typedef struct jb_framelist_t
{
    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;
} jb_framelist_t;


struct pjmedia_jbuf
{
    pj_str_t	    name;		  // jitter buffer name
    jb_framelist_t  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)
#endif


static pj_status_t jb_framelist_init( pj_pool_t *pool,
				      jb_framelist_t *framelist,
				      unsigned frame_size,
				      unsigned max_count) 
{
    PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL);

    pj_bzero(framelist, sizeof(jb_framelist_t));

    framelist->flist_frame_size = frame_size;
    framelist->flist_max_count = max_count;
    framelist->flist_buffer = (char*) 
			      pj_pool_zalloc(pool,
					     framelist->flist_frame_size * 
					     framelist->flist_max_count);

    framelist->flist_frame_type = (int*)
	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_t *framelist) 
{
    PJ_UNUSED_ARG(framelist);
    return PJ_SUCCESS;
}


static unsigned jb_framelist_size(jb_framelist_t *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_t *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_t *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_t *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_T(pool, pjmedia_jbuf);

    status = jb_framelist_init(pool, &jb->jb_framelist, frame_size, max_count);

⌨️ 快捷键说明

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