Changeset 169 for pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
- Timestamp:
- Feb 9, 2006 2:01:40 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
r129 r169 18 18 */ 19 19 #include <pjmedia/jbuf.h> 20 #include <pj /log.h>20 #include <pjmedia/errno.h> 21 21 #include <pj/pool.h> 22 22 #include <pj/assert.h> … … 24 24 25 25 26 /* 27 * At the current state, this is basicly an ugly jitter buffer. 28 * It worked before by observing level, bit it doesn't work. 29 * Then I used the size, which makes the level obsolete. 30 * That's why it's ugly! 31 */ 32 33 #define MAX_SEQ_RANGE 1000 /* Range in which sequence is considered still within session */ 34 #define UPDATE_DURATION 20 /* Number of frames retrieved before jitter is updated */ 35 36 #define THIS_FILE "jbuf" 37 38 /* Individual frame in the frame list. */ 39 struct pj_jbframe 40 { 41 pj_uint32_t extseq; 42 void *buf; 26 27 struct jb_framelist 28 { 29 char *flist_buffer; 30 int *flist_frame_type; 31 unsigned flist_frame_size; 32 unsigned flist_max_count; 33 unsigned flist_empty; 34 unsigned flist_head; 35 unsigned flist_tail; 36 unsigned flist_origin; 43 37 }; 44 38 45 39 46 /* Jitter buffer state. */ 47 typedef enum jb_state_t 48 { 49 JB_PREFETCH, 50 JB_NORMAL, 51 } jb_state_t; 52 53 54 /* Jitter buffer last operation. */ 55 typedef enum jb_op_t 56 { 57 JB_PUT, 58 JB_GET, 59 } jb_op_t; 60 61 62 /* Short name for convenience. */ 63 typedef struct pj_jitter_buffer JB; 64 65 66 /* Initialize framelist. */ 67 static pj_status_t 68 pj_framelist_init( pj_jbframelist *lst, pj_pool_t *pool, unsigned maxcount ) 69 { 70 PJ_LOG(5, (THIS_FILE, "..pj_frame_list_init [lst=%p], maxcount=%d", lst, maxcount)); 71 72 pj_memset(lst, 0, sizeof(*lst)); 73 lst->maxcount = maxcount; 74 lst->frames = pj_pool_calloc( pool, maxcount, sizeof(*lst->frames) ); 75 if (lst->frames == NULL) { 76 PJ_LOG(1,(THIS_FILE, "Unable to allocate frame list!")); 77 return -1; 78 } 79 return 0; 80 } 81 82 /* Reset framelist. */ 83 static void 84 pj_framelist_reset( pj_jbframelist *lst ) 85 { 86 PJ_LOG(6, (THIS_FILE, "..pj_frame_list_reset [lst=%p]", lst)); 87 88 lst->count = 0; 89 lst->head = 0; 90 lst->frames[0].extseq = 0; 91 } 92 93 /* Put a buffer with the specified sequence into the ordered list. */ 94 static int 95 pj_framelist_put( pj_jbframelist *lst, pj_uint32_t extseq, void *buf ) 96 { 97 unsigned pos = (unsigned)-1; 98 pj_uint32_t startseq = lst->frames[lst->head].extseq; 99 100 if (lst->count == 0) { 101 /* Empty list. Initialize frame list. */ 102 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_put [lst=%p], empty, seq=%u@pos=%d", 103 lst, extseq, lst->head)); 104 105 lst->head = 0; 106 lst->count = 1; 107 lst->frames[0].buf = buf; 108 lst->frames[0].extseq = extseq; 109 return 0; 40 typedef struct jb_framelist jb_framelist; 41 42 struct pjmedia_jbuf 43 { 44 jb_framelist jb_framelist; 45 pj_size_t jb_frame_size; // frame size 46 pj_size_t jb_max_count; // max frames in the jitter framelist->flist_buffer 47 48 int jb_level; // delay between source & destination 49 // (calculated according of the number of get/put operations) 50 int jb_last_level; // last delay 51 int jb_last_jitter; // last jitter calculated 52 int jb_max_hist_jitter; // max jitter during the last jitter calculations 53 int jb_stable_hist; // num of times the delay has been lower then the prefetch num 54 int jb_last_op; // last operation executed on the framelist->flist_buffer (put/get) 55 int jb_last_seq_no; // seq no. of the last frame inserted to the framelist->flist_buffer 56 int jb_prefetch; // no. of frame to insert before removing some 57 // (at the beginning of the framelist->flist_buffer operation) 58 int jb_prefetch_cnt; // prefetch counter 59 int jb_status; // status is 'init' until the first 'put' operation 60 61 62 }; 63 64 65 #define JB_STATUS_INITIALIZING 0 66 #define JB_STATUS_PROCESSING 1 67 68 #define PJ_ABS(x) ((x > 0) ? (x) : -(x)) 69 #define PJ_MAX(x, y) ((x > y) ? (x) : (y)) 70 #define PJ_MIN(x, y) ((x < y) ? (x) : (y)) 71 72 73 74 static pj_status_t jb_framelist_init( pj_pool_t *pool, 75 jb_framelist *framelist, 76 unsigned frame_size, 77 unsigned max_count) 78 { 79 PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL); 80 81 pj_memset(framelist, 0, sizeof(jb_framelist)); 82 83 framelist->flist_frame_size = frame_size; 84 framelist->flist_max_count = max_count; 85 framelist->flist_buffer = pj_pool_zalloc(pool, 86 framelist->flist_frame_size * 87 framelist->flist_max_count); 88 89 framelist->flist_frame_type = pj_pool_zalloc(pool, 90 sizeof(framelist->flist_frame_type[0]) * 91 framelist->flist_max_count); 92 93 framelist->flist_empty = 1; 94 framelist->flist_head = framelist->flist_tail = framelist->flist_origin = 0; 95 96 return PJ_SUCCESS; 97 98 } 99 100 static pj_status_t jb_framelist_destroy(jb_framelist *framelist) 101 { 102 PJ_UNUSED_ARG(framelist); 103 return PJ_SUCCESS; 104 } 105 106 107 static unsigned jb_framelist_size(jb_framelist *framelist) 108 { 109 if (framelist->flist_tail == framelist->flist_head) { 110 return framelist->flist_empty ? 0 : framelist->flist_max_count; 111 } else { 112 return (framelist->flist_tail - framelist->flist_head + 113 framelist->flist_max_count) % framelist->flist_max_count; 114 } 115 } 116 117 118 static pj_bool_t jb_framelist_get(jb_framelist *framelist, 119 void *frame, 120 pjmedia_jb_frame_type *p_type) 121 { 122 if (!framelist->flist_empty) { 123 pj_memcpy(frame, 124 framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 125 framelist->flist_frame_size); 126 *p_type = (pjmedia_jb_frame_type) framelist->flist_frame_type[framelist->flist_head]; 127 128 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 129 0, framelist->flist_frame_size); 130 framelist->flist_frame_type[framelist->flist_head] = 0; 131 132 framelist->flist_origin++; 133 framelist->flist_head = ++framelist->flist_head % framelist->flist_max_count; 134 if (framelist->flist_head == framelist->flist_tail) 135 framelist->flist_empty = PJ_TRUE; 110 136 111 } else if (extseq < startseq) { 112 /* The sequence number is lower than our oldest packet. This can mean 113 two things: 114 - old packet has been receieved, or 115 - the sequence number has wrapped around. 116 */ 117 if (startseq + lst->maxcount <= extseq) { 118 /* The sequence number has wrapped around, but it is beyond 119 the capacity of the list (i.e. too soon). 120 */ 121 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d", 122 lst, extseq, startseq)); 123 return PJ_JB_STATUS_TOO_SOON; 124 125 } else if (startseq-extseq > lst->maxcount && startseq+lst->maxcount > extseq) { 126 /* The sequence number has wrapped around, and it is still inside 127 the 'window' of the framelist. 128 */ 129 pos = extseq - startseq; 137 return PJ_TRUE; 138 139 } else { 140 pj_memset(frame, 0, framelist->flist_frame_size); 141 return PJ_FALSE; 142 } 143 } 144 145 146 static void jb_framelist_remove_head( jb_framelist *framelist, 147 unsigned count) 148 { 149 unsigned cur_size; 150 151 cur_size = jb_framelist_size(framelist); 152 if (count > cur_size) 153 count = cur_size; 154 155 if (count) { 156 // may be done in two steps if overlapping 157 unsigned step1,step2; 158 unsigned tmp = framelist->flist_head+count; 159 160 if (tmp > framelist->flist_max_count) { 161 step1 = framelist->flist_max_count - framelist->flist_head; 162 step2 = count-step1; 130 163 } else { 131 /* The new frame is too old. */ 132 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d", 133 lst, extseq, startseq)); 134 return PJ_JB_STATUS_TOO_OLD; 164 step1 = count; 165 step2 = 0; 135 166 } 136 137 } else if (extseq > startseq + lst->maxcount) { 138 /* Two possibilities here. Either:139 - packet is really too soon, or140 - sequence number of startseq has just wrapped around, and old packet141 which hasn't wrapped is received.142 */143 if (extseq < MAX_SEQ_RANGE /*approx 20 seconds with 50 fps*/) { 144 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_SOON! [lst=%p] seq=%u, startseq=%d",145 lst, extseq, startseq));146 return PJ_JB_STATUS_TOO_SOON;147 } else {148 PJ_LOG(5, (THIS_FILE, " ..pj_frame_list_put TOO_OLD! [lst=%p] seq=%u, startseq=%d",149 lst, extseq, startseq));150 return PJ_JB_STATUS_TOO_OLD;167 168 pj_memset(framelist->flist_buffer + framelist->flist_head * framelist->flist_frame_size, 169 0, 170 step1*framelist->flist_frame_size); 171 pj_memset(framelist->flist_frame_type+framelist->flist_head, 172 0, 173 step1*sizeof(framelist->flist_frame_type[0])); 174 175 if (step2) { 176 pj_memset(framelist->flist_buffer, 177 0, 178 step2*framelist->flist_frame_size); 179 pj_memset(framelist->flist_frame_type, 180 0, 181 step2*sizeof(framelist->flist_frame_type[0])); 151 182 } 152 } 153 154 /* The new frame is within the framelist capacity. 155 Calculate position where to put it in the list. 156 */ 157 if (pos == (unsigned)-1) 158 pos = ((extseq - startseq) + lst->head) % lst->maxcount; 159 160 pj_assert(pos < lst->maxcount); 161 162 /* Update count only if we're not overwriting existing frame. */ 163 if (lst->frames[pos].buf == NULL) 164 ++lst->count; 165 166 lst->frames[pos].buf = buf; 167 lst->frames[pos].extseq = extseq; 168 169 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_put [lst=%p] seq=%u, startseq=%d, head=%d, pos=%d", 170 lst, extseq, startseq, lst->head, pos)); 171 return 0; 172 } 173 174 /* Get the first element of the list. */ 175 static int 176 pj_framelist_get( pj_jbframelist *lst, pj_uint32_t *extseq, void **buf ) 177 { 178 if (lst->count == 0) { 179 /* Empty. */ 180 *buf = NULL; 181 *extseq = 0; 182 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_get [lst=%p], empty!", lst)); 183 return -1; 184 185 } else { 186 *buf = lst->frames[lst->head].buf; 187 *extseq = lst->frames[lst->head].extseq; 188 lst->frames[lst->head].buf = NULL; 189 190 PJ_LOG(6, (THIS_FILE, " ..pj_frame_list_get [lst=%p] seq=%u, head=%d", 191 lst, *extseq, lst->head)); 192 193 lst->head = (lst->head + 1) % lst->maxcount; 194 --lst->count; 195 return 0; 196 } 197 } 198 199 200 /***************************************************************************** 201 * Reset jitter buffer. 202 **************************************************************************** 203 */ 204 PJ_DEF(void) pj_jb_reset(JB *jb) 205 { 206 PJ_LOG(6, (THIS_FILE, "pj_jb_reset [jb=%p]", jb)); 207 208 jb->level = jb->max_level = 1; 209 jb->prefetch = jb->min; 210 jb->get_cnt = 0; 211 jb->lastseq = 0; 212 jb->state = JB_PREFETCH; 213 jb->upd_count = 0; 214 jb->last_op = -1; 215 pj_framelist_reset( &jb->lst ); 216 } 217 218 219 /***************************************************************************** 220 * Create jitter buffer. 221 ***************************************************************************** 222 */ 223 PJ_DEF(pj_status_t) pj_jb_init( pj_jitter_buffer *jb, pj_pool_t *pool, 224 unsigned min, unsigned max, unsigned maxcount) 225 { 183 184 // update pointers 185 framelist->flist_origin += count; 186 framelist->flist_head = (framelist->flist_head+count) % framelist->flist_max_count; 187 if (framelist->flist_head == framelist->flist_tail) 188 framelist->flist_empty = PJ_TRUE; 189 } 190 } 191 192 193 static pj_bool_t jb_framelist_put_at(jb_framelist *framelist, 194 unsigned index, 195 const void *frame, 196 unsigned frame_size) 197 { 198 unsigned where; 199 200 // too late 201 if (index < framelist->flist_origin) 202 return PJ_FALSE; 203 204 // too soon 205 if ((index > (framelist->flist_origin + framelist->flist_max_count - 1)) && !framelist->flist_empty) 206 return PJ_FALSE; 207 208 assert(frame_size <= framelist->flist_frame_size); 209 210 if (!framelist->flist_empty) { 211 unsigned cur_size; 212 213 where = (index - framelist->flist_origin + framelist->flist_head) % framelist->flist_max_count; 214 215 // update framelist->flist_tail pointer 216 cur_size = jb_framelist_size(framelist); 217 if (index >= framelist->flist_origin + cur_size) { 218 unsigned diff = (index - (framelist->flist_origin + cur_size)); 219 framelist->flist_tail = (framelist->flist_tail + diff + 1) % framelist->flist_max_count; 220 } 221 } else { 222 where = framelist->flist_tail; 223 framelist->flist_origin = index; 224 framelist->flist_tail = (++framelist->flist_tail % framelist->flist_max_count); 225 framelist->flist_empty = PJ_FALSE; 226 } 227 228 pj_memcpy(framelist->flist_buffer + where * framelist->flist_frame_size, 229 frame, frame_size); 230 231 framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME; 232 233 return PJ_TRUE; 234 } 235 236 237 238 enum pjmedia_jb_op 239 { 240 JB_OP_INIT = -1, 241 JB_OP_PUT = 1, 242 JB_OP_GET = 2 243 }; 244 245 246 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 247 int frame_size, 248 int initial_prefetch, 249 int max_count, 250 pjmedia_jbuf **p_jb) 251 { 252 pjmedia_jbuf *jb; 226 253 pj_status_t status; 227 254 228 if (maxcount <= max) { 229 maxcount = max * 5 / 4; 230 PJ_LOG(3,(THIS_FILE, "Jitter buffer maximum count was adjusted.")); 231 } 232 233 jb->min = min; 234 jb->max = max; 235 236 status = pj_framelist_init( &jb->lst, pool, maxcount ); 255 jb = pj_pool_zalloc(pool, sizeof(pjmedia_jbuf)); 256 257 status = jb_framelist_init(pool, &jb->jb_framelist, frame_size, max_count); 237 258 if (status != PJ_SUCCESS) 238 259 return status; 239 260 240 pj_jb_reset(jb); 241 242 PJ_LOG(4, (THIS_FILE, "pj_jb_init success [jb=%p], min=%d, max=%d, maxcount=%d", 243 jb, min, max, maxcount)); 261 jb->jb_frame_size = frame_size; 262 jb->jb_last_seq_no = -1; 263 jb->jb_level = 0; 264 jb->jb_last_level = 0; 265 jb->jb_last_jitter = 0; 266 jb->jb_last_op = JB_OP_INIT; 267 jb->jb_prefetch = PJ_MIN(initial_prefetch, max_count*4/5); 268 jb->jb_prefetch_cnt = 0; 269 jb->jb_stable_hist = 0; 270 jb->jb_status = JB_STATUS_INITIALIZING; 271 jb->jb_max_hist_jitter = 0; 272 jb->jb_max_count = max_count; 273 274 *p_jb = jb; 244 275 return PJ_SUCCESS; 245 276 } 246 277 247 278 248 /***************************************************************************** 249 * Put a packet to the jitter buffer. 250 ***************************************************************************** 251 */ 252 PJ_DEF(pj_status_t) pj_jb_put( JB *jb, pj_uint32_t extseq, void *buf ) 253 { 254 unsigned distance; 255 int status; 279 PJ_DEF(pj_status_t) pjmedia_jbuf_destroy(pjmedia_jbuf *jb) 280 { 281 return jb_framelist_destroy(&jb->jb_framelist); 282 } 283 284 285 static void jbuf_calculate_jitter(pjmedia_jbuf *jb) 286 { 287 enum { STABLE_HISTORY_LIMIT = (500/20) }; 288 289 jb->jb_last_jitter = PJ_ABS(jb->jb_level-jb->jb_last_level); 290 jb->jb_last_level = jb->jb_level; 291 jb->jb_max_hist_jitter = PJ_MAX(jb->jb_max_hist_jitter,jb->jb_last_jitter); 256 292 257 PJ_LOG(6, (THIS_FILE, "==> pj_jb_put [jb=%p], seq=%u, buf=%p", jb, extseq, buf)); 258 259 if (jb->lastseq == 0) 260 jb->lastseq = extseq - 1; 261 262 /* Calculate distance between this packet and last received packet 263 to detect long jump (indicating probably remote has just been 264 restarted. 265 */ 266 distance = (extseq > jb->lastseq) ? extseq - jb->lastseq : jb->lastseq - extseq; 267 if (distance > MAX_SEQ_RANGE) { 268 /* Distance is out of range, reset jitter while maintaining current jitter 269 level. 270 */ 271 int old_level = jb->level; 272 int old_prefetch = jb->prefetch; 273 274 PJ_LOG(4, (THIS_FILE, " ..[jb=%p] distance out of range, resetting", jb)); 275 276 pj_jb_reset(jb); 277 jb->level = old_level; 278 jb->prefetch = old_prefetch; 279 distance = 1; 280 jb->lastseq = extseq - 1; 281 } 282 283 jb->lastseq = extseq; 284 285 status = pj_framelist_put( &jb->lst, extseq, buf ); 286 if (status == PJ_JB_STATUS_TOO_OLD) 287 return -1; 288 289 if (status == PJ_JB_STATUS_TOO_SOON) { 290 /* TODO: discard old packets.. */ 291 /* No, don't do it without putting a way to inform application so that 292 it can free the memory */ 293 } 294 295 296 if (jb->last_op != JB_PUT) { 297 if (jb->state != JB_PREFETCH) 298 jb->level--; 299 } else { 300 jb->level++; 301 } 302 303 if ((int)jb->lst.count > jb->max_level) 304 jb->max_level++; 305 306 jb->last_op = JB_PUT; 307 return 0; 308 } 309 310 311 /* 312 * Update jitter buffer algorithm. 313 */ 314 static void jb_update(JB *jb, int apply, int log_info) 315 { 316 unsigned abs_level = jb->max_level > 0 ? jb->max_level : -jb->max_level; 317 unsigned new_prefetch; 318 319 /* Update prefetch count */ 320 if (abs_level > jb->prefetch) 321 new_prefetch = (jb->prefetch + abs_level*9 + 1) / 10; 322 else { 323 new_prefetch = (jb->prefetch*4 + abs_level) / 5; 324 pj_assert(new_prefetch <= jb->prefetch); 325 } 326 327 if (log_info) { 328 PJ_LOG(5, (THIS_FILE, " ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d", 329 jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 330 } else { 331 PJ_LOG(6, (THIS_FILE, " ..jb_update [jb=%p], level=%d, max_level=%d, old_prefetch=%d, new_prefetch=%d", 332 jb, jb->level, jb->max_level, jb->prefetch, new_prefetch)); 333 } 334 335 if (new_prefetch < jb->min) new_prefetch = jb->min; 336 if (new_prefetch > jb->max) new_prefetch = jb->max; 337 338 /* If jitter buffer is empty, set state to JB_PREFETCH, taking care of the 339 new prefetch setting. 340 */ 341 if (jb->lst.count == 0) { 342 jb->state = JB_PREFETCH; 343 jb->get_cnt = 0; 344 } else { 345 /* Check if delay is too long, which in this case probably better to 346 discard some frames.. 347 */ 348 /* No, don't do it without putting a way to inform application so that 349 it can free the memory */ 350 } 351 352 353 if (apply) { 354 jb->prefetch = new_prefetch; 355 if (jb->max_level > 0) 356 jb->max_level--; 357 } else { 358 jb->level = new_prefetch; 359 } 360 } 361 362 363 /***************************************************************************** 364 * Get the oldest frame from jitter buffer. 365 ***************************************************************************** 366 */ 367 PJ_DEF(pj_status_t) pj_jb_get( JB *jb, pj_uint32_t *extseq, void **buf ) 368 { 369 pj_status_t status; 370 371 PJ_LOG(6, (THIS_FILE, "<== pj_jb_get [jb=%p]", jb)); 372 373 /* 374 * Check whether we're ready to give frame. When we're in JB_PREFETCH state, 375 * only give frames only when: 376 * - the buffer has enough frames in it (jb->list.count > jb->prefetch), OR 377 * - after 'prefetch' attempts, there's still no frame, which in this 378 * case PJ_JB_STATUS_FRAME_NULL will be returned by the next check. 379 */ 380 if (jb->state == JB_PREFETCH && jb->lst.count <= jb->prefetch && jb->get_cnt < jb->prefetch) { 381 jb->get_cnt++; 382 jb->last_op = JB_GET; 383 PJ_LOG(5, (THIS_FILE, " ..[jb=%p] bufferring...", jb)); 384 return PJ_JB_STATUS_FRAME_NULL; 385 } 386 387 /* Attempt to get one frame from the list. */ 388 status = pj_framelist_get( &jb->lst, extseq, buf ); 389 if (status != 0) { 390 PJ_LOG(6, (THIS_FILE, " ..[jb=%p] no packet!", jb)); 391 status = jb->lst.count ? PJ_JB_STATUS_FRAME_MISSING : PJ_JB_STATUS_FRAME_NULL; 392 jb_update(jb, 1, 0); 393 return status; 394 } 395 396 /* Force state to NORMAL */ 397 jb->state = JB_NORMAL; 398 399 /* Increase level only when last operation is GET. 400 * This is to prevent level from increasing during silence period, which 401 * no packets is receieved. 402 */ 403 if (jb->last_op != JB_GET) { 404 int apply; 405 406 //jb->level++; 407 jb->last_op = JB_GET; 408 409 apply = (++jb->upd_count > UPDATE_DURATION); 410 if (apply) 411 jb->upd_count = 0; 412 413 jb_update(jb, apply, apply); 414 } 415 416 PJ_LOG(6, (THIS_FILE, " ..[jb=%p] seq=%u, level=%d, prefetch=%d, size=%u, delay=%d", 417 jb, *extseq, jb->level, jb->prefetch, jb->lst.count, 418 jb->lastseq - *extseq)); 419 return 0; 420 } 421 422 293 if (jb->jb_last_jitter< jb->jb_prefetch) { 294 jb->jb_stable_hist += jb->jb_last_jitter; 295 if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) { 296 int seq_diff = (jb->jb_prefetch - jb->jb_max_hist_jitter)/3; 297 if (seq_diff<1) seq_diff = 1; 298 299 jb->jb_prefetch -= seq_diff; 300 if (jb->jb_prefetch < 1) jb->jb_prefetch = 1; 301 302 jb->jb_stable_hist = 0; 303 jb->jb_max_hist_jitter = 0; 304 } 305 } else { 306 jb->jb_prefetch = PJ_MIN(jb->jb_last_jitter,(int)(jb->jb_max_count*4/5)); 307 jb->jb_stable_hist = 0; 308 jb->jb_max_hist_jitter = 0; 309 } 310 } 311 312 static void jbuf_update(pjmedia_jbuf *jb, int oper) 313 { 314 if(jb->jb_last_op != oper) { 315 jbuf_calculate_jitter(jb); 316 jb->jb_last_op = oper; 317 } 318 } 319 320 PJ_DEF(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb, 321 const void *frame, 322 pj_size_t frame_size, 323 int frame_seq) 324 { 325 pj_size_t min_frame_size; 326 int seq_diff; 327 328 if (jb->jb_last_seq_no == -1) { 329 jb->jb_last_seq_no = frame_seq - 1; 330 } 331 332 seq_diff = frame_seq - jb->jb_last_seq_no; 333 jb->jb_last_seq_no = PJ_MAX(jb->jb_last_seq_no, frame_seq); 334 if (seq_diff > 0) jb->jb_level += seq_diff; 335 336 if(jb->jb_status == JB_STATUS_INITIALIZING) { 337 jb->jb_status = JB_STATUS_PROCESSING; 338 jb->jb_level = 0; 339 jb->jb_last_level = 0; 340 jb->jb_last_jitter = 0; 341 } else { 342 jbuf_update(jb, JB_OP_PUT); 343 } 344 345 min_frame_size = PJ_MIN(frame_size, jb->jb_frame_size); 346 if (seq_diff > 0) { 347 348 while (!jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size)) { 349 jb_framelist_remove_head(&jb->jb_framelist,PJ_MAX(jb->jb_max_count/4,1)); 350 } 351 352 if (jb->jb_prefetch_cnt < jb->jb_prefetch) 353 jb->jb_prefetch_cnt += seq_diff; 354 355 } 356 else 357 { 358 jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size); 359 } 360 361 return PJ_SUCCESS; 362 } 363 364 PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, 365 void *frame, 366 char *p_frame_type) 367 { 368 pjmedia_jb_frame_type ftype; 369 370 jb->jb_level--; 371 372 jbuf_update(jb, JB_OP_GET); 373 374 if (jb_framelist_size(&jb->jb_framelist) == 0) { 375 jb->jb_prefetch_cnt = 0; 376 } 377 378 if ((jb->jb_prefetch_cnt < jb->jb_prefetch) || !jb_framelist_get(&jb->jb_framelist,frame,&ftype)) { 379 pj_memset(frame, 0, jb->jb_frame_size); 380 *p_frame_type = PJMEDIA_JB_ZERO_FRAME; 381 return PJ_SUCCESS; 382 } 383 384 if (ftype == PJMEDIA_JB_NORMAL_FRAME) { 385 *p_frame_type = PJMEDIA_JB_NORMAL_FRAME; 386 } else { 387 *p_frame_type = PJMEDIA_JB_MISSING_FRAME; 388 } 389 390 return PJ_SUCCESS; 391 } 392 393 PJ_DEF(unsigned) pjmedia_jbuf_get_prefetch_size(pjmedia_jbuf *jb) 394 { 395 return jb->jb_prefetch; 396 } 397 398 PJ_DEF(unsigned) pjmedia_jbuf_get_current_size(pjmedia_jbuf *jb) 399 { 400 return jb_framelist_size(&jb->jb_framelist); 401 } 402 403
Note: See TracChangeset
for help on using the changeset viewer.