Changeset 3736 for pjproject/trunk/pjmedia/src/pjmedia-videodev/qt_dev.m
- Timestamp:
- Aug 29, 2011 8:36:59 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-videodev/qt_dev.m
r3722 r3736 66 66 }; 67 67 68 @interface VOutDelegate: NSObject 68 struct qt_stream; 69 typedef void (*func_ptr)(struct qt_stream *strm); 70 71 @interface QTDelegate: NSObject 69 72 { 70 73 @public 71 struct qt_stream *stream; 72 } 74 struct qt_stream *strm; 75 func_ptr func; 76 } 77 78 - (void)run_func; 73 79 @end 74 80 … … 91 97 pj_thread_t *cap_thread; 92 98 93 NSAutoreleasePool *apool; 99 struct qt_factory *qf; 100 pj_status_t status; 101 pj_bool_t is_running; 102 pj_bool_t cap_exited; 103 94 104 QTCaptureSession *cap_session; 95 105 QTCaptureDeviceInput *dev_input; 96 106 QTCaptureDecompressedVideoOutput *video_output; 97 VOutDelegate *vout_delegate;107 QTDelegate *qt_delegate; 98 108 }; 99 109 … … 325 335 } 326 336 327 @implementation VOutDelegate 337 static qt_fmt_info* get_qt_format_info(pjmedia_format_id id) 338 { 339 unsigned i; 340 341 for (i = 0; i < PJ_ARRAY_SIZE(qt_fmts); i++) { 342 if (qt_fmts[i].pjmedia_format == id) 343 return &qt_fmts[i]; 344 } 345 346 return NULL; 347 } 348 349 @implementation QTDelegate 328 350 - (void)captureOutput:(QTCaptureOutput *)captureOutput 329 351 didOutputVideoFrame:(CVImageBufferRef)videoFrame … … 334 356 pjmedia_frame frame; 335 357 336 if (stream->cap_thread_initialized == 0 || !pj_thread_is_registered()) 358 if (!strm->is_running) { 359 strm->cap_exited = PJ_TRUE; 360 return; 361 } 362 363 if (strm->cap_thread_initialized == 0 || !pj_thread_is_registered()) 337 364 { 338 pj_thread_register("qt_cap", str eam->cap_thread_desc,339 &str eam->cap_thread);340 str eam->cap_thread_initialized = 1;365 pj_thread_register("qt_cap", strm->cap_thread_desc, 366 &strm->cap_thread); 367 strm->cap_thread_initialized = 1; 341 368 PJ_LOG(5,(THIS_FILE, "Capture thread started")); 342 369 } … … 349 376 frame.size = size; 350 377 frame.bit_info = 0; 351 frame.timestamp.u64 = stream->cap_frame_ts.u64; 352 353 if (stream->vid_cb.capture_cb) 354 (*stream->vid_cb.capture_cb)(&stream->base, stream->user_data, 355 &frame); 356 357 stream->cap_frame_ts.u64 += stream->cap_ts_inc; 358 } 378 frame.timestamp.u64 = strm->cap_frame_ts.u64; 379 380 if (strm->vid_cb.capture_cb) 381 (*strm->vid_cb.capture_cb)(&strm->base, strm->user_data, &frame); 382 383 strm->cap_frame_ts.u64 += strm->cap_ts_inc; 384 } 385 386 - (void)run_func 387 { 388 (*func)(strm); 389 } 390 359 391 @end 360 392 361 static qt_fmt_info* get_qt_format_info(pjmedia_format_id id) 362 { 363 unsigned i; 364 365 for (i = 0; i < PJ_ARRAY_SIZE(qt_fmts); i++) { 366 if (qt_fmts[i].pjmedia_format == id) 367 return &qt_fmts[i]; 368 } 369 370 return NULL; 393 static void init_qt(struct qt_stream *strm) 394 { 395 const pjmedia_video_format_detail *vfd; 396 qt_fmt_info *qfi = get_qt_format_info(strm->param.fmt.id); 397 BOOL success = NO; 398 NSError *error; 399 400 if (!qfi) { 401 strm->status = PJMEDIA_EVID_BADFORMAT; 402 return; 403 } 404 405 strm->cap_session = [[QTCaptureSession alloc] init]; 406 if (!strm->cap_session) { 407 strm->status = PJ_ENOMEM; 408 return; 409 } 410 411 /* Open video device */ 412 QTCaptureDevice *videoDevice = 413 [QTCaptureDevice deviceWithUniqueID: 414 [NSString stringWithCString: 415 strm->qf->dev_info[strm->param.cap_id].dev_id 416 encoding: 417 [NSString defaultCStringEncoding]]]; 418 if (!videoDevice || ![videoDevice open:&error]) { 419 strm->status = PJMEDIA_EVID_SYSERR; 420 return; 421 } 422 423 /* Add the video device to the session as a device input */ 424 strm->dev_input = [[QTCaptureDeviceInput alloc] 425 initWithDevice:videoDevice]; 426 success = [strm->cap_session addInput:strm->dev_input error:&error]; 427 if (!success) { 428 strm->status = PJMEDIA_EVID_SYSERR; 429 return; 430 } 431 432 strm->video_output = [[QTCaptureDecompressedVideoOutput alloc] init]; 433 success = [strm->cap_session addOutput:strm->video_output 434 error:&error]; 435 if (!success) { 436 strm->status = PJMEDIA_EVID_SYSERR; 437 return; 438 } 439 440 vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, 441 PJ_TRUE); 442 [strm->video_output setPixelBufferAttributes: 443 [NSDictionary dictionaryWithObjectsAndKeys: 444 [NSNumber numberWithInt:qfi->qt_format], 445 kCVPixelBufferPixelFormatTypeKey, 446 [NSNumber numberWithInt:vfd->size.w], 447 kCVPixelBufferWidthKey, 448 [NSNumber numberWithInt:vfd->size.h], 449 kCVPixelBufferHeightKey, nil]]; 450 451 pj_assert(vfd->fps.num); 452 strm->cap_ts_inc = PJMEDIA_SPF2(strm->param.clock_rate, &vfd->fps, 1); 453 454 if ([strm->video_output 455 respondsToSelector:@selector(setMinimumVideoFrameInterval)]) 456 { 457 [strm->video_output setMinimumVideoFrameInterval: 458 (1.0f * vfd->fps.denum / (double)vfd->fps.num)]; 459 } 460 461 strm->qt_delegate = [[QTDelegate alloc]init]; 462 strm->qt_delegate->strm = strm; 463 [strm->video_output setDelegate:strm->qt_delegate]; 464 } 465 466 static void run_func_on_main_thread(struct qt_stream *strm, func_ptr func) 467 { 468 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 469 QTDelegate *delg = [[QTDelegate alloc] init]; 470 471 delg->strm = strm; 472 delg->func = func; 473 [delg performSelectorOnMainThread:@selector(run_func) 474 withObject:nil waitUntilDone:YES]; 475 476 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); 477 478 [delg release]; 479 [pool release]; 371 480 } 372 481 … … 384 493 const pjmedia_video_format_info *vfi; 385 494 pj_status_t status = PJ_SUCCESS; 386 BOOL success = NO;387 NSError *error;388 495 389 496 PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL); … … 406 513 pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 407 514 strm->user_data = user_data; 408 strm-> apool = [[NSAutoreleasePool alloc]init];409 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_ COLORBAR);515 strm->qf = qf; 516 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_QT); 410 517 411 518 /* Create capture stream here */ 412 if (param->dir & PJMEDIA_DIR_CAPTURE) { 413 const pjmedia_video_format_detail *vfd; 414 qt_fmt_info *qfi = get_qt_format_info(param->fmt.id); 415 416 if (!qfi) { 417 status = PJMEDIA_EVID_BADFORMAT; 418 goto on_error; 419 } 420 421 strm->cap_session = [[QTCaptureSession alloc] init]; 422 if (!strm->cap_session) { 423 status = PJ_ENOMEM; 424 goto on_error; 425 } 426 427 /* Open video device */ 428 QTCaptureDevice *videoDevice = 429 [QTCaptureDevice deviceWithUniqueID: 430 [NSString stringWithCString: 431 qf->dev_info[param->cap_id].dev_id 432 encoding: 433 [NSString defaultCStringEncoding]]]; 434 if (!videoDevice || ![videoDevice open:&error]) { 435 status = PJMEDIA_EVID_SYSERR; 436 goto on_error; 437 } 438 439 /* Add the video device to the session as a device input */ 440 strm->dev_input = [[QTCaptureDeviceInput alloc] 441 initWithDevice:videoDevice]; 442 success = [strm->cap_session addInput:strm->dev_input error:&error]; 443 if (!success) { 444 status = PJMEDIA_EVID_SYSERR; 445 goto on_error; 446 } 447 448 strm->video_output = [[QTCaptureDecompressedVideoOutput alloc] init]; 449 success = [strm->cap_session addOutput:strm->video_output 450 error:&error]; 451 if (!success) { 452 status = PJMEDIA_EVID_SYSERR; 453 goto on_error; 454 } 455 456 vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, 457 PJ_TRUE); 458 [strm->video_output setPixelBufferAttributes: 459 [NSDictionary dictionaryWithObjectsAndKeys: 460 [NSNumber numberWithInt: 461 qfi->qt_format], 462 kCVPixelBufferPixelFormatTypeKey, 463 [NSNumber numberWithInt: 464 vfd->size.w], 465 kCVPixelBufferWidthKey, 466 [NSNumber numberWithInt: 467 vfd->size.h], 468 kCVPixelBufferHeightKey, nil]]; 469 470 pj_assert(vfd->fps.num); 471 strm->cap_ts_inc = PJMEDIA_SPF2(strm->param.clock_rate, &vfd->fps, 1); 472 473 if ([strm->video_output 474 respondsToSelector:@selector(setMinimumVideoFrameInterval)]) 475 { 476 [strm->video_output setMinimumVideoFrameInterval: 477 (1.0f * vfd->fps.denum / 478 (double)vfd->fps.num)]; 479 } 480 481 strm->vout_delegate = [[VOutDelegate alloc]init]; 482 strm->vout_delegate->stream = strm; 483 [strm->video_output setDelegate:strm->vout_delegate]; 519 if (param->dir & PJMEDIA_DIR_CAPTURE) { 520 strm->status = PJ_SUCCESS; 521 run_func_on_main_thread(strm, init_qt); 522 if ((status = strm->status) != PJ_SUCCESS) 523 goto on_error; 484 524 } 485 525 … … 562 602 } 563 603 604 static void start_qt(struct qt_stream *strm) 605 { 606 [strm->cap_session startRunning]; 607 } 608 609 static void stop_qt(struct qt_stream *strm) 610 { 611 [strm->cap_session stopRunning]; 612 } 613 564 614 /* API: Start stream. */ 565 615 static pj_status_t qt_stream_start(pjmedia_vid_dev_stream *strm) … … 572 622 573 623 if (stream->cap_session) { 574 [stream->cap_session startRunning];624 run_func_on_main_thread(stream, start_qt); 575 625 576 626 if (![stream->cap_session isRunning]) 577 return PJ _EUNKNOWN;578 579 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);627 return PJMEDIA_EVID_NOTREADY; 628 629 stream->is_running = PJ_TRUE; 580 630 } 581 631 … … 592 642 PJ_LOG(4, (THIS_FILE, "Stopping qt video stream")); 593 643 594 if (stream->cap_session && [stream->cap_session isRunning]) 595 [stream->cap_session stopRunning]; 596 597 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); 598 599 return PJ_SUCCESS; 600 } 601 644 if (stream->cap_session && [stream->cap_session isRunning]) { 645 int i; 646 647 stream->cap_exited = PJ_FALSE; 648 run_func_on_main_thread(stream, stop_qt); 649 650 stream->is_running = PJ_FALSE; 651 for (i = 50; i >= 0 && !stream->cap_exited; i--) { 652 pj_thread_sleep(10); 653 } 654 } 655 656 return PJ_SUCCESS; 657 } 658 659 static void destroy_qt(struct qt_stream *strm) 660 { 661 if (strm->dev_input && [[strm->dev_input device] isOpen]) 662 [[strm->dev_input device] close]; 663 664 if (strm->cap_session) { 665 [strm->cap_session release]; 666 strm->cap_session = NULL; 667 } 668 if (strm->dev_input) { 669 [strm->dev_input release]; 670 strm->dev_input = NULL; 671 } 672 if (strm->qt_delegate) { 673 [strm->qt_delegate release]; 674 strm->qt_delegate = NULL; 675 } 676 if (strm->video_output) { 677 [strm->video_output release]; 678 strm->video_output = NULL; 679 } 680 } 602 681 603 682 /* API: Destroy stream. */ … … 609 688 610 689 qt_stream_stop(strm); 611 612 if (stream->dev_input && [[stream->dev_input device] isOpen]) 613 [[stream->dev_input device] close]; 614 615 if (stream->cap_session) { 616 [stream->cap_session release]; 617 stream->cap_session = NULL; 618 } 619 if (stream->dev_input) { 620 [stream->dev_input release]; 621 stream->dev_input = NULL; 622 } 623 if (stream->vout_delegate) { 624 [stream->vout_delegate release]; 625 stream->vout_delegate = NULL; 626 } 627 if (stream->video_output) { 628 [stream->video_output release]; 629 stream->video_output = NULL; 630 } 631 632 // [stream->apool release]; 690 691 run_func_on_main_thread(stream, destroy_qt); 692 633 693 pj_pool_release(stream->pool); 634 694
Note: See TracChangeset
for help on using the changeset viewer.