Changeset 3431
- Timestamp:
- Mar 1, 2011 3:55:34 PM (14 years ago)
- Location:
- pjproject/branches/projects/2.0-dev
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia-videodev/videodev.h
r3420 r3431 161 161 { 162 162 PJMEDIA_EVENT_NONE, 163 PJMEDIA_EVENT_FMT_CHANGED, 163 164 PJMEDIA_EVENT_MOUSEBUTTONDOWN, 164 165 PJMEDIA_EVENT_WINDOW_RESIZE, … … 169 170 typedef struct pjmedia_vid_event 170 171 { 171 pjmedia_event_type event_type; 172 long lparam; 173 void *pparam; 172 pjmedia_event_type event_type; 173 union { 174 struct resize_event { 175 pjmedia_rect_size new_size; 176 } resize; 177 struct fmt_changed_event { 178 pjmedia_format new_format; 179 } fmt_change; 180 } event_desc; 174 181 } pjmedia_vid_event; 175 182 -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/clock.h
r3402 r3431 181 181 }; 182 182 183 184 typedef struct pjmedia_clock_param 185 { 186 /** 187 * The frame interval, in microseconds. 188 */ 189 unsigned usec_interval; 190 /** 191 * The media clock rate, to determine timestamp 192 * increment for each call. 193 */ 194 unsigned clock_rate; 195 } pjmedia_clock_param; 183 196 184 197 /** … … 232 245 * 233 246 * @param pool Pool to allocate memory. 234 * @param usec_interval The frame interval, in microseconds. 235 * @param clock_rate The media clock rate, to determine timestamp 236 * increment for each call. 247 * @param param The clock parameter. 237 248 * @param options Bitmask of pjmedia_clock_options. 238 249 * @param cb Callback to be called for each clock tick. … … 244 255 */ 245 256 PJ_DECL(pj_status_t) pjmedia_clock_create2(pj_pool_t *pool, 246 unsigned usec_interval, 247 unsigned clock_rate, 257 const pjmedia_clock_param *param, 248 258 unsigned options, 249 259 pjmedia_clock_callback *cb, … … 273 283 274 284 285 /** 286 * Modify the clock's parameter. 287 * 288 * @param clock The media clock. 289 * @param param The clock's new parameter. 290 * @return PJ_SUCCES on success. 291 */ 292 PJ_DECL(pj_status_t) pjmedia_clock_modify(pjmedia_clock *clock, 293 const pjmedia_clock_param *param); 294 275 295 276 296 /** -
pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/videoport.h
r3420 r3431 170 170 171 171 /** 172 * Connect the video port from its downstream (slave) media port, if any.172 * Disconnect the video port from its downstream (slave) media port, if any. 173 173 * This operation is only valid for video ports created with active interface 174 174 * selected, and assertion may be triggered if this is invoked on a passive -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia-videodev/sdl_dev.c
r3420 r3431 392 392 pjmedia_vid_event pevent; 393 393 394 /** 395 * The event polling must be placed in the same thread that 396 * call SDL_SetVideoMode(). Please consult the official doc of 397 * SDL_PumpEvents(). 398 */ 394 399 while (SDL_WaitEvent(&sevent)) { 395 400 pj_bzero(&pevent, sizeof(pevent)); … … 397 402 switch(sevent.type) { 398 403 case SDL_USEREVENT: 399 goto on_return; 404 { 405 pjmedia_format *fmt; 406 407 if (sevent.user.code == PJMEDIA_EVENT_NONE) 408 goto on_return; 409 410 pj_assert(sevent.user.code == PJMEDIA_VID_DEV_CAP_FORMAT); 411 412 fmt = (pjmedia_format *)sevent.user.data1; 413 vfi = pjmedia_get_video_format_info( 414 pjmedia_video_format_mgr_instance(), 415 fmt->id); 416 if (!vfi || !sdl_info) { 417 strm->status = PJMEDIA_EVID_BADFORMAT; 418 break; 419 } 420 421 vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE); 422 strm->vafp.size = vfd->size; 423 strm->vafp.buffer = NULL; 424 if (vfi->apply_fmt(vfi, &strm->vafp) != PJ_SUCCESS) { 425 strm->status = PJMEDIA_EVID_BADFORMAT; 426 break; 427 } 428 429 strm->rect.w = (Uint16)vfd->size.w; 430 strm->rect.h = (Uint16)vfd->size.h; 431 432 /* Stop the stream */ 433 sdl_stream_stop((pjmedia_vid_dev_stream *)strm); 434 435 /* Initialize the display, requesting a software surface */ 436 strm->screen = SDL_SetVideoMode(strm->rect.w, 437 strm->rect.h, 0, 438 SDL_RESIZABLE | 439 SDL_SWSURFACE); 440 if (strm->screen == NULL) { 441 strm->status = PJMEDIA_EVID_SYSERR; 442 break; 443 } 444 445 if (strm->surf) 446 SDL_FreeSurface(strm->surf); 447 if (strm->overlay) 448 SDL_FreeYUVOverlay(strm->overlay); 449 450 if (vfi->color_model == PJMEDIA_COLOR_MODEL_RGB) { 451 strm->surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 452 strm->rect.w, 453 strm->rect.h, 454 vfi->bpp, 455 sdl_info->Rmask, 456 sdl_info->Gmask, 457 sdl_info->Bmask, 458 sdl_info->Amask); 459 if (strm->surf == NULL) { 460 strm->status = PJMEDIA_EVID_SYSERR; 461 break; 462 } 463 } else if (vfi->color_model == PJMEDIA_COLOR_MODEL_YUV) { 464 strm->overlay = SDL_CreateYUVOverlay( 465 strm->rect.w, 466 strm->rect.h, 467 sdl_info->sdl_format, 468 strm->screen); 469 if (strm->overlay == NULL) { 470 strm->status = PJMEDIA_EVID_SYSERR; 471 break; 472 } 473 } 474 475 /* Restart the stream */ 476 sdl_stream_start((pjmedia_vid_dev_stream *)strm); 477 478 strm->status = PJ_SUCCESS; 479 break; 480 } 481 400 482 case SDL_MOUSEBUTTONDOWN: 401 483 pevent.event_type = PJMEDIA_EVENT_MOUSEBUTTONDOWN; … … 413 495 pjmedia_vid_dev_stream_start(&strm->base); 414 496 break; 497 415 498 case SDL_VIDEORESIZE: 416 499 pevent.event_type = PJMEDIA_EVENT_WINDOW_RESIZE; 417 if (strm->vid_cb.on_event_cb) 418 if ((*strm->vid_cb.on_event_cb)(&strm->base, 419 strm->user_data, 420 &pevent) != PJ_SUCCESS) 421 { 422 /* Application wants us to ignore this event */ 423 break; 424 } 425 /* TODO: move this to OUTPUT_RESIZE cap 426 strm->screen = SDL_SetVideoMode(sevent.resize.w, 427 sevent.resize.h, 428 0, SDL_RESIZABLE | 429 SDL_SWSURFACE); 430 */ 500 pevent.event_desc.resize.new_size.w = sevent.resize.w; 501 pevent.event_desc.resize.new_size.h = sevent.resize.h; 502 if (strm->vid_cb.on_event_cb) { 503 /** 504 * To process PJMEDIA_EVENT_WINDOW_RESIZE event, 505 * application should do this in the on_event_cb 506 * callback: 507 * 1. change the input frame size given to SDL 508 * to the new size. 509 * 2. call pjmedia_vid_dev_stream_set_cap() 510 * using PJMEDIA_VID_DEV_CAP_FORMAT capability 511 * and the new format size 512 */ 513 (*strm->vid_cb.on_event_cb)(&strm->base, 514 strm->user_data, 515 &pevent); 516 } 431 517 break; 518 432 519 case SDL_QUIT: 433 520 pevent.event_type = PJMEDIA_EVENT_WINDOW_CLOSE; … … 470 557 strm->screen = NULL; 471 558 goto on_return; 559 472 560 default: 473 561 break; … … 581 669 PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 582 670 583 if (cap ==PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW)671 if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) 584 672 { 585 673 return PJ_SUCCESS; 674 } else if (cap == PJMEDIA_VID_DEV_CAP_FORMAT) { 675 return PJ_SUCCESS; 586 676 } else { 587 677 return PJMEDIA_EVID_INVCAP; … … 600 690 PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 601 691 602 if (cap==PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) 603 { 692 if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 604 693 return PJ_SUCCESS; 694 } else if (cap == PJMEDIA_VID_DEV_CAP_FORMAT) { 695 SDL_Event sevent; 696 697 strm->status = PJ_TRUE; 698 sevent.type = SDL_USEREVENT; 699 sevent.user.code = PJMEDIA_VID_DEV_CAP_FORMAT; 700 sevent.user.data1 = (void *)pval; 701 SDL_PushEvent(&sevent); 702 703 while (strm->status == PJ_TRUE) 704 pj_thread_sleep(10); 705 706 if (strm->status != PJ_SUCCESS) { 707 pj_status_t status = strm->status; 708 709 /** 710 * Failed to change the output format. Try to revert 711 * to its original format. 712 */ 713 strm->status = PJ_TRUE; 714 sevent.user.data1 = &strm->param.fmt; 715 SDL_PushEvent(&sevent); 716 717 while (strm->status == PJ_TRUE) 718 pj_thread_sleep(10); 719 720 if (strm->status != PJ_SUCCESS) 721 /** 722 * This means that we failed to revert to our 723 * original state! 724 */ 725 status = PJMEDIA_EVID_ERR; 726 727 strm->status = status; 728 } else if (strm->status == PJ_SUCCESS) { 729 pj_memcpy(&strm->param.fmt, pval, sizeof(strm->param.fmt)); 730 } 731 732 return strm->status; 605 733 } 606 734 … … 707 835 if (!stream->is_quitting) { 708 836 sevent.type = SDL_USEREVENT; 837 sevent.user.code = PJMEDIA_EVENT_NONE; 709 838 SDL_PushEvent(&sevent); 710 839 pj_thread_join(stream->sdl_thread); -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/clock_thread.c
r3402 r3431 143 143 pjmedia_clock **p_clock) 144 144 { 145 return pjmedia_clock_create2(pool, 146 (unsigned)(samples_per_frame * USEC_IN_SEC / 147 channel_count / clock_rate), 148 clock_rate, options, cb, user_data, p_clock); 145 pjmedia_clock_param param; 146 147 param.usec_interval = (unsigned)(samples_per_frame * USEC_IN_SEC / 148 channel_count / clock_rate); 149 param.clock_rate = clock_rate; 150 return pjmedia_clock_create2(pool, ¶m, options, cb, 151 user_data, p_clock); 149 152 } 150 153 151 154 PJ_DEF(pj_status_t) pjmedia_clock_create2(pj_pool_t *pool, 152 unsigned usec_interval, 153 unsigned clock_rate, 155 const pjmedia_clock_param *param, 154 156 unsigned options, 155 157 pjmedia_clock_callback *cb, … … 160 162 pj_status_t status; 161 163 162 PJ_ASSERT_RETURN(pool && usec_interval && clock_rate && p_clock,163 164 PJ_ASSERT_RETURN(pool && param->usec_interval && param->clock_rate && 165 p_clock, PJ_EINVAL); 164 166 165 167 clock = PJ_POOL_ALLOC_T(pool, pjmedia_clock); … … 169 171 return status; 170 172 171 clock->interval.u64 = usec_interval * clock->freq.u64 / USEC_IN_SEC; 173 clock->interval.u64 = param->usec_interval * clock->freq.u64 / 174 USEC_IN_SEC; 172 175 clock->next_tick.u64 = 0; 173 176 clock->timestamp.u64 = 0; 174 177 clock->max_jump = MAX_JUMP_MSEC * clock->freq.u64 / 1000; 175 clock->timestamp_inc = (unsigned)(usec_interval * clock_rate / 178 clock->timestamp_inc = (unsigned)(param->usec_interval * 179 param->clock_rate / 176 180 USEC_IN_SEC); 177 181 clock->options = options; … … 203 207 204 208 205 206 209 /* 207 210 * Start the clock. … … 238 241 239 242 clock->running = PJ_FALSE; 243 244 return PJ_SUCCESS; 245 } 246 247 248 /* 249 * Update the clock. 250 */ 251 PJ_DEF(pj_status_t) pjmedia_clock_modify(pjmedia_clock *clock, 252 const pjmedia_clock_param *param) 253 { 254 clock->interval.u64 = param->usec_interval * clock->freq.u64 / 255 USEC_IN_SEC; 256 clock->timestamp_inc = (unsigned)(param->usec_interval * 257 param->clock_rate / 258 USEC_IN_SEC); 240 259 241 260 return PJ_SUCCESS; -
pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/videoport.c
r3420 r3431 19 19 #include <pjmedia/videoport.h> 20 20 #include <pjmedia/clock.h> 21 #include <pjmedia/vid_codec.h> 21 22 #include <pj/log.h> 22 23 #include <pj/pool.h> … … 64 65 pjmedia_frame *enc_frm_buf, 65 66 *dec_frm_buf; 67 pj_size_t enc_frm_buf_size, 68 dec_frm_buf_size; 66 69 67 70 pj_mutex_t *enc_frm_mutex, … … 183 186 184 187 if (vp->dir & PJMEDIA_DIR_ENCODING) { 185 status = pjmedia_clock_create2(pool, 186 PJMEDIA_PTIME(&vfd->fps), 187 prm->vidparam.clock_rate, 188 pjmedia_clock_param param; 189 190 param.usec_interval = PJMEDIA_PTIME(&vfd->fps); 191 param.clock_rate = prm->vidparam.clock_rate; 192 status = pjmedia_clock_create2(pool, ¶m, 188 193 PJMEDIA_CLOCK_NO_HIGHEST_PRIO, 189 194 &enc_clock_cb, vp, &vp->enc_clock); … … 193 198 194 199 if (vp->dir & PJMEDIA_DIR_DECODING) { 195 status = pjmedia_clock_create2(pool, 196 PJMEDIA_PTIME(&vfd->fps), 197 prm->vidparam.clock_rate, 200 pjmedia_clock_param param; 201 202 param.usec_interval = PJMEDIA_PTIME(&vfd->fps); 203 param.clock_rate = prm->vidparam.clock_rate; 204 status = pjmedia_clock_create2(pool, ¶m, 198 205 PJMEDIA_CLOCK_NO_HIGHEST_PRIO, 199 206 &dec_clock_cb, vp, &vp->dec_clock); … … 237 244 if (vp->dir & PJMEDIA_DIR_ENCODING) { 238 245 vp->enc_frm_buf = PJ_POOL_ZALLOC_T(pool, pjmedia_frame); 246 vp->enc_frm_buf_size = vafp.framebytes; 239 247 vp->enc_frm_buf->buf = pj_pool_alloc(pool, vafp.framebytes); 240 248 vp->enc_frm_buf->size = vafp.framebytes; … … 249 257 if (vp->dir & PJMEDIA_DIR_DECODING) { 250 258 vp->dec_frm_buf = PJ_POOL_ZALLOC_T(pool, pjmedia_frame); 259 vp->dec_frm_buf_size = vafp.framebytes; 251 260 vp->dec_frm_buf->buf = pj_pool_alloc(pool, vafp.framebytes); 252 261 vp->dec_frm_buf->size = vafp.framebytes; … … 463 472 */ 464 473 474 static pj_status_t detect_fmt_change(pjmedia_vid_port *vp, 475 pjmedia_frame *frame) 476 { 477 if (frame->bit_info & PJMEDIA_VID_CODEC_EVENT_FMT_CHANGED) { 478 const pjmedia_video_format_detail *vfd; 479 pjmedia_vid_event pevent; 480 pj_status_t status; 481 482 /* Retrieve the video format detail */ 483 vfd = pjmedia_format_get_video_format_detail( 484 &vp->client_port->info.fmt, PJ_TRUE); 485 if (!vfd) 486 return PJMEDIA_EVID_BADFORMAT; 487 pj_assert(vfd->fps.num); 488 489 status = pjmedia_vid_dev_stream_set_cap( 490 vp->strm, 491 PJMEDIA_VID_DEV_CAP_FORMAT, 492 &vp->client_port->info.fmt); 493 if (status != PJ_SUCCESS) { 494 PJ_LOG(3, (THIS_FILE, "failure in changing the format of the " 495 "video device")); 496 PJ_LOG(3, (THIS_FILE, "reverting to its original format: %s", 497 status != PJMEDIA_EVID_ERR ? "success" : 498 "failure")); 499 pjmedia_vid_port_stop(vp); 500 return status; 501 } 502 503 if (vp->stream_role == ROLE_PASSIVE) { 504 pjmedia_vid_param vid_param; 505 pjmedia_clock_param clock_param; 506 507 /** 508 * Initially, dec_frm_buf was allocated the biggest 509 * supported size, so we do not need to re-allocate 510 * the buffer here. 511 */ 512 /* Adjust the clock */ 513 pjmedia_vid_dev_stream_get_param(vp->strm, &vid_param); 514 clock_param.usec_interval = PJMEDIA_PTIME(&vfd->fps); 515 clock_param.clock_rate = vid_param.clock_rate; 516 pjmedia_clock_modify(vp->dec_clock, &clock_param); 517 } 518 519 /* Notify application of the format change. */ 520 pevent.event_type = PJMEDIA_EVENT_FMT_CHANGED; 521 pj_memcpy(&pevent.event_desc.fmt_change.new_format, 522 &vp->client_port->info.fmt, sizeof(pjmedia_format)); 523 if (vp->strm_cb.on_event_cb) 524 (*vp->strm_cb.on_event_cb)(vp->strm, vp->strm_cb_data, &pevent); 525 } 526 527 return PJ_SUCCESS; 528 } 529 465 530 static void enc_clock_cb(const pj_timestamp *ts, void *user_data) 466 531 { … … 478 543 return; 479 544 545 vp->enc_frm_buf->size = vp->enc_frm_buf_size; 480 546 status = pjmedia_vid_dev_stream_get_frame(vp->strm, vp->enc_frm_buf); 481 547 if (status != PJ_SUCCESS) … … 583 649 584 650 for (i = 0; i < ndrop; i++) { 651 vp->dec_frm_buf->size = vp->dec_frm_buf_size; 585 652 status = pjmedia_port_get_frame(vp->client_port, 586 653 vp->dec_frm_buf); … … 589 656 return; 590 657 } 658 659 status = detect_fmt_change(vp, vp->dec_frm_buf); 660 if (status != PJ_SUCCESS) 661 return; 662 591 663 pj_add_timestamp32(&vp->rend_clocksrc.timestamp, 592 664 frame_ts); … … 596 668 } 597 669 670 vp->dec_frm_buf->size = vp->dec_frm_buf_size; 598 671 status = pjmedia_port_get_frame(vp->client_port, vp->dec_frm_buf); 599 672 if (status != PJ_SUCCESS) { … … 604 677 pjmedia_clock_src_update(&vp->rend_clocksrc, NULL); 605 678 679 status = detect_fmt_change(vp, vp->dec_frm_buf); 680 if (status != PJ_SUCCESS) 681 return; 682 606 683 status = pjmedia_vid_dev_stream_put_frame(vp->strm, vp->dec_frm_buf); 607 684 } … … 623 700 624 701 if (vp->role==ROLE_ACTIVE) { 625 702 if (vp->client_port) 626 703 return pjmedia_port_put_frame(vp->client_port, frame); 627 704 } else { … … 642 719 643 720 if (vp->role==ROLE_ACTIVE) { 644 if (vp->client_port) 645 return pjmedia_port_get_frame(vp->client_port, frame); 721 if (vp->client_port) { 722 pj_status_t status; 723 724 status = pjmedia_port_get_frame(vp->client_port, frame); 725 if (status != PJ_SUCCESS) 726 return status; 727 728 return detect_fmt_change(vp, frame); 729 } 646 730 } else { 647 731 pj_mutex_lock(vp->dec_frm_mutex); -
pjproject/branches/projects/2.0-dev/pjmedia/src/test/vid_dev_test.c
r3425 r3431 144 144 145 145 /* Sleep while the webcam is being displayed... */ 146 for (i = 0; i < 50 && (!is_quitting); i++) { 146 for (i = 0; i < 15 && (!is_quitting); i++) { 147 #if VID_DEV_TEST_MAC_OS 148 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); 149 #endif 150 pj_thread_sleep(100); 151 } 152 153 /** 154 * Test the renderer's format capability if the device 155 * supports it. 156 */ 157 if (pjmedia_vid_dev_stream_get_cap(pjmedia_vid_port_get_stream(renderer), 158 PJMEDIA_VID_DEV_CAP_FORMAT, 159 ¶m.vidparam.fmt) == PJ_SUCCESS) 160 { 161 status = pjmedia_vid_port_stop(capture); 162 if (status != PJ_SUCCESS) { 163 rc = 170; goto on_return; 164 } 165 status = pjmedia_vid_port_disconnect(capture); 166 if (status != PJ_SUCCESS) { 167 rc = 180; goto on_return; 168 } 169 pjmedia_vid_port_destroy(capture); 170 171 param.vidparam.dir = PJMEDIA_DIR_CAPTURE; 172 param.active = PJ_TRUE; 173 pjmedia_format_init_video(¶m.vidparam.fmt, param.vidparam.fmt.id, 174 640, 480, 175 vfd->fps.num, vfd->fps.denum); 176 vfd = pjmedia_format_get_video_format_detail(¶m.vidparam.fmt, 177 PJ_TRUE); 178 if (vfd == NULL) { 179 rc = 185; goto on_return; 180 } 181 182 status = pjmedia_vid_port_create(pool, ¶m, &capture); 183 if (status != PJ_SUCCESS) { 184 rc = 190; goto on_return; 185 } 186 187 status = pjmedia_vid_port_connect( 188 capture, 189 pjmedia_vid_port_get_passive_port(renderer), 190 PJ_FALSE); 191 if (status != PJ_SUCCESS) { 192 rc = 200; goto on_return; 193 } 194 195 status = pjmedia_vid_dev_stream_set_cap( 196 pjmedia_vid_port_get_stream(renderer), 197 PJMEDIA_VID_DEV_CAP_FORMAT, 198 ¶m.vidparam.fmt); 199 if (status != PJ_SUCCESS) { 200 rc = 205; goto on_return; 201 } 202 203 status = pjmedia_vid_port_start(capture); 204 if (status != PJ_SUCCESS) { 205 rc = 210; goto on_return; 206 } 207 } 208 209 for (i = 0; i < 35 && (!is_quitting); i++) { 147 210 #if VID_DEV_TEST_MAC_OS 148 211 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); -
pjproject/branches/projects/2.0-dev/pjsip-apps/src/samples/vid_streamutil.c
r3425 r3431 598 598 if (play_file.file_name) { 599 599 pjmedia_video_format_detail *file_vfd; 600 pjmedia_clock_param *clock_param; 600 601 601 602 /* Create file player */ … … 669 670 670 671 /* Create player clock */ 671 status = pjmedia_clock_create2(pool, PJMEDIA_PTIME(&file_vfd->fps), 672 codec_info->clock_rate, 672 clock_param.usec_interval = PJMEDIA_PTIME(&file_vfd->fps); 673 clock_param.clock_rate = codec_info->clock_rate; 674 status = pjmedia_clock_create2(pool, &clock_param, 673 675 PJMEDIA_CLOCK_NO_HIGHEST_PRIO, 674 676 &clock_cb, &play_file, &play_clock);
Note: See TracChangeset
for help on using the changeset viewer.