- Timestamp:
- Dec 30, 2010 4:31:16 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c
r3401 r3402 50 50 *dec_clock; 51 51 52 pjmedia_clock_src cap_clocksrc, 53 rend_clocksrc; 54 55 struct sync_clock_src_t 56 { 57 pjmedia_clock_src *sync_clocksrc; 58 pj_int32_t sync_delta; 59 unsigned max_sync_ticks; 60 unsigned nsync_frame; 61 unsigned nsync_progress; 62 } cap_sync_clocksrc, rend_sync_clocksrc; 63 52 64 pjmedia_frame *enc_frm_buf, 53 65 *dec_frm_buf; … … 99 111 pj_bool_t need_frame_buf = PJ_FALSE; 100 112 pj_status_t status; 113 unsigned ptime_usec; 101 114 102 115 PJ_ASSERT_RETURN(pool && prm && p_vid_port, PJ_EINVAL); … … 140 153 vp->stream_role = di.has_callback ? ROLE_ACTIVE : ROLE_PASSIVE; 141 154 155 ptime_usec = PJMEDIA_PTIME(&vfd->fps); 156 pjmedia_clock_src_init(&vp->cap_clocksrc, PJMEDIA_TYPE_VIDEO, 157 prm->vidparam.clock_rate, ptime_usec); 158 pjmedia_clock_src_init(&vp->rend_clocksrc, PJMEDIA_TYPE_VIDEO, 159 prm->vidparam.clock_rate, ptime_usec); 160 vp->cap_sync_clocksrc.max_sync_ticks = 161 PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION * 162 1000 / vp->cap_clocksrc.ptime_usec; 163 vp->rend_sync_clocksrc.max_sync_ticks = 164 PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION * 165 1000 / vp->rend_clocksrc.ptime_usec; 166 142 167 /* Create the video stream */ 143 168 pj_bzero(&vid_cb, sizeof(vid_cb)); … … 269 294 270 295 296 297 PJ_DEF(pjmedia_clock_src *) 298 pjmedia_vid_port_get_clock_src( pjmedia_vid_port *vid_port, 299 pjmedia_dir dir ) 300 { 301 return (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_clocksrc: 302 &vid_port->rend_clocksrc); 303 } 304 305 PJ_DECL(pj_status_t) 306 pjmedia_vid_port_set_clock_src( pjmedia_vid_port *vid_port, 307 pjmedia_dir dir, 308 pjmedia_clock_src *clocksrc) 309 { 310 pjmedia_clock_src *vclocksrc; 311 struct sync_clock_src_t *sync_src; 312 313 PJ_ASSERT_RETURN(vid_port && clocksrc, PJ_EINVAL); 314 315 vclocksrc = (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_clocksrc: 316 &vid_port->rend_clocksrc); 317 sync_src = (dir == PJMEDIA_DIR_CAPTURE? &vid_port->cap_sync_clocksrc: 318 &vid_port->rend_sync_clocksrc); 319 sync_src->sync_clocksrc = clocksrc; 320 sync_src->sync_delta = pjmedia_clock_src_get_time_msec(vclocksrc) - 321 pjmedia_clock_src_get_time_msec(clocksrc); 322 323 return PJ_SUCCESS; 324 } 325 326 271 327 PJ_DEF(pj_status_t) pjmedia_vid_port_connect(pjmedia_vid_port *vp, 272 328 pjmedia_port *port, … … 438 494 pjmedia_vid_port *vp = (pjmedia_vid_port*)user_data; 439 495 pj_status_t status; 496 unsigned frame_ts = vp->rend_clocksrc.clock_rate / 1000 * 497 vp->rend_clocksrc.ptime_usec / 1000; 440 498 441 499 pj_assert(vp->role==ROLE_ACTIVE && vp->stream_role==ROLE_PASSIVE); … … 446 504 return; 447 505 506 if (vp->rend_sync_clocksrc.sync_clocksrc) { 507 pjmedia_clock_src *src = vp->rend_sync_clocksrc.sync_clocksrc; 508 pj_int32_t diff; 509 unsigned nsync_frame; 510 511 /* Synchronization */ 512 /* Calculate the time difference (in ms) with the sync source */ 513 diff = pjmedia_clock_src_get_time_msec(&vp->rend_clocksrc) - 514 pjmedia_clock_src_get_time_msec(src) - 515 vp->rend_sync_clocksrc.sync_delta; 516 517 /* Check whether sync source made a large jump */ 518 if (diff < 0 && -diff > PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC) { 519 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 520 vp->rend_sync_clocksrc.sync_delta = 521 pjmedia_clock_src_get_time_msec(src) - 522 pjmedia_clock_src_get_time_msec(&vp->rend_clocksrc); 523 vp->rend_sync_clocksrc.nsync_frame = 0; 524 return; 525 } 526 527 /* Calculate the difference (in frames) with the sync source */ 528 nsync_frame = abs(diff) * 1000 / vp->rend_clocksrc.ptime_usec; 529 if (nsync_frame == 0) { 530 /* Nothing to sync */ 531 vp->rend_sync_clocksrc.nsync_frame = 0; 532 } else { 533 pj_int32_t init_sync_frame = nsync_frame; 534 535 /* Check whether it's a new sync or whether we need to reset 536 * the sync 537 */ 538 if (vp->rend_sync_clocksrc.nsync_frame == 0 || 539 (vp->rend_sync_clocksrc.nsync_frame > 0 && 540 nsync_frame > vp->rend_sync_clocksrc.nsync_frame)) 541 { 542 vp->rend_sync_clocksrc.nsync_frame = nsync_frame; 543 vp->rend_sync_clocksrc.nsync_progress = 0; 544 } else { 545 init_sync_frame = vp->rend_sync_clocksrc.nsync_frame; 546 } 547 548 if (diff >= 0) { 549 unsigned skip_mod; 550 551 /* We are too fast */ 552 if (vp->rend_sync_clocksrc.max_sync_ticks > 0) { 553 skip_mod = init_sync_frame / 554 vp->rend_sync_clocksrc.max_sync_ticks + 2; 555 } else 556 skip_mod = init_sync_frame + 2; 557 558 PJ_LOG(5, (THIS_FILE, "synchronization: early by %d ms", 559 diff)); 560 /* We'll play a frame every skip_mod-th tick instead of 561 * a complete pause 562 */ 563 if (++vp->rend_sync_clocksrc.nsync_progress % skip_mod > 0) { 564 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 565 return; 566 } 567 } else { 568 unsigned i, ndrop = init_sync_frame; 569 570 /* We are too late, drop the frame */ 571 if (vp->rend_sync_clocksrc.max_sync_ticks > 0) { 572 ndrop /= vp->rend_sync_clocksrc.max_sync_ticks; 573 ndrop++; 574 } 575 PJ_LOG(5, (THIS_FILE, "synchronization: late, " 576 "dropping %d frame(s)", ndrop)); 577 578 if (ndrop >= nsync_frame) { 579 vp->rend_sync_clocksrc.nsync_frame = 0; 580 ndrop = nsync_frame; 581 } else 582 vp->rend_sync_clocksrc.nsync_progress += ndrop; 583 for (i = 0; i < ndrop; i++) { 584 status = pjmedia_port_get_frame(vp->client_port, 585 vp->dec_frm_buf); 586 if (status != PJ_SUCCESS) { 587 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 588 return; 589 } 590 pj_add_timestamp32(&vp->rend_clocksrc.timestamp, 591 frame_ts); 592 } 593 } 594 } 595 } 596 448 597 status = pjmedia_port_get_frame(vp->client_port, vp->dec_frm_buf); 449 if (status != PJ_SUCCESS) 598 if (status != PJ_SUCCESS) { 599 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 450 600 return; 601 } 602 pj_add_timestamp32(&vp->rend_clocksrc.timestamp, frame_ts); 603 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 451 604 452 605 status = pjmedia_vid_stream_put_frame(vp->strm, vp->dec_frm_buf);
Note: See TracChangeset
for help on using the changeset viewer.