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 + -
显示快捷键?