- Timestamp:
- May 18, 2018 2:29:04 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-codec/vid_toolbox.m
r5625 r5793 35 35 36 36 #if (defined(PJ_DARWINOS) && PJ_DARWINOS != 0 && TARGET_OS_IPHONE) 37 #import <UIKit/UIKit.h> 38 37 39 # define DEFAULT_WIDTH 352 38 40 # define DEFAULT_HEIGHT 288 … … 480 482 } 481 483 482 static pj_status_t vtool_codec_open(pjmedia_vid_codec *codec, 483 pjmedia_vid_codec_param *codec_param ) 484 { 485 vtool_codec_data *vtool_data; 486 pjmedia_vid_codec_param *param; 487 pjmedia_h264_packetizer_cfg pktz_cfg; 488 pjmedia_vid_codec_h264_fmtp h264_fmtp; 489 pj_status_t status; 490 CMVideoCodecType codec_type; 484 485 static OSStatus create_encoder(vtool_codec_data *vtool_data) 486 { 487 pjmedia_vid_codec_param *param = vtool_data->prm; 491 488 CFDictionaryRef supported_prop; 492 489 OSStatus ret; 493 490 494 PJ_ASSERT_RETURN(codec && codec_param, PJ_EINVAL); 495 496 PJ_LOG(5,(THIS_FILE, "Opening codec..")); 497 498 vtool_data = (vtool_codec_data*) codec->codec_data; 499 vtool_data->prm = pjmedia_vid_codec_param_clone( vtool_data->pool, 500 codec_param); 501 param = vtool_data->prm; 502 503 /* Parse remote fmtp */ 504 pj_bzero(&h264_fmtp, sizeof(h264_fmtp)); 505 status = pjmedia_vid_codec_h264_parse_fmtp(¶m->enc_fmtp, &h264_fmtp); 506 if (status != PJ_SUCCESS) 507 return status; 508 509 /* Apply SDP fmtp to format in codec param */ 510 if (!param->ignore_fmtp) { 511 status = pjmedia_vid_codec_h264_apply_fmtp(param); 512 if (status != PJ_SUCCESS) 513 return status; 514 } 515 516 pj_bzero(&pktz_cfg, sizeof(pktz_cfg)); 517 pktz_cfg.mtu = param->enc_mtu; 518 pktz_cfg.unpack_nal_start = 4; 519 /* Packetization mode */ 520 if (h264_fmtp.packetization_mode == 0) 521 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL; 522 else if (h264_fmtp.packetization_mode == 1) 523 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 524 else 525 return PJ_ENOTSUP; 526 /* Video Toolbox encoder doesn't support setting maximum slice size, 527 * so we cannot use single NAL mode since the NAL size likely 528 * exceeds the MTU. 529 */ 530 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 531 532 status = pjmedia_h264_packetizer_create(vtool_data->pool, &pktz_cfg, 533 &vtool_data->pktz); 534 if (status != PJ_SUCCESS) 535 return status; 536 537 vtool_data->whole = (param->packing == PJMEDIA_VID_PACKING_WHOLE); 538 if (1) { 539 /* Init format info and apply-param of encoder */ 540 const pjmedia_video_format_info *enc_vfi; 541 pjmedia_video_apply_fmt_param enc_vafp; 542 543 enc_vfi = pjmedia_get_video_format_info(NULL,codec_param->dec_fmt.id); 544 if (!enc_vfi) 545 return PJ_EINVAL; 546 547 pj_bzero(&enc_vafp, sizeof(enc_vafp)); 548 enc_vafp.size = codec_param->enc_fmt.det.vid.size; 549 enc_vafp.buffer = NULL; 550 status = (*enc_vfi->apply_fmt)(enc_vfi, &enc_vafp); 551 if (status != PJ_SUCCESS) 552 return status; 553 554 vtool_data->enc_wxh = codec_param->enc_fmt.det.vid.size.w * 555 codec_param->enc_fmt.det.vid.size.h; 556 vtool_data->enc_input_size = enc_vafp.framebytes; 557 if (!vtool_data->whole) { 558 vtool_data->enc_buf_size = (unsigned)enc_vafp.framebytes; 559 vtool_data->enc_buf = pj_pool_alloc(vtool_data->pool, 560 vtool_data->enc_buf_size); 561 } 491 /* Destroy if initialized before */ 492 if (vtool_data->enc) { 493 VTCompressionSessionInvalidate(vtool_data->enc); 494 CFRelease(vtool_data->enc); 495 vtool_data->enc = NULL; 562 496 } 563 497 564 498 /* Create encoder session */ 565 codec_type = kCMVideoCodecType_H264;566 499 ret = VTCompressionSessionCreate(NULL, (int)param->enc_fmt.det.vid.size.w, 567 500 (int)param->enc_fmt.det.vid.size.h, … … 571 504 if (ret != noErr) { 572 505 PJ_LOG(4,(THIS_FILE, "VTCompressionCreate failed, ret=%d", ret)); 573 return PJMEDIA_CODEC_EFAILED;506 return ret; 574 507 } 575 508 … … 626 559 627 560 VTCompressionSessionPrepareToEncodeFrames(vtool_data->enc); 628 561 562 return ret; 563 } 564 565 566 static pj_status_t vtool_codec_open(pjmedia_vid_codec *codec, 567 pjmedia_vid_codec_param *codec_param ) 568 { 569 vtool_codec_data *vtool_data; 570 pjmedia_vid_codec_param *param; 571 pjmedia_h264_packetizer_cfg pktz_cfg; 572 pjmedia_vid_codec_h264_fmtp h264_fmtp; 573 pj_status_t status; 574 OSStatus ret; 575 576 PJ_ASSERT_RETURN(codec && codec_param, PJ_EINVAL); 577 578 PJ_LOG(5,(THIS_FILE, "Opening codec..")); 579 580 vtool_data = (vtool_codec_data*) codec->codec_data; 581 vtool_data->prm = pjmedia_vid_codec_param_clone( vtool_data->pool, 582 codec_param); 583 param = vtool_data->prm; 584 585 /* Parse remote fmtp */ 586 pj_bzero(&h264_fmtp, sizeof(h264_fmtp)); 587 status = pjmedia_vid_codec_h264_parse_fmtp(¶m->enc_fmtp, &h264_fmtp); 588 if (status != PJ_SUCCESS) 589 return status; 590 591 /* Apply SDP fmtp to format in codec param */ 592 if (!param->ignore_fmtp) { 593 status = pjmedia_vid_codec_h264_apply_fmtp(param); 594 if (status != PJ_SUCCESS) 595 return status; 596 } 597 598 pj_bzero(&pktz_cfg, sizeof(pktz_cfg)); 599 pktz_cfg.mtu = param->enc_mtu; 600 pktz_cfg.unpack_nal_start = 4; 601 /* Packetization mode */ 602 if (h264_fmtp.packetization_mode == 0) 603 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL; 604 else if (h264_fmtp.packetization_mode == 1) 605 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 606 else 607 return PJ_ENOTSUP; 608 /* Video Toolbox encoder doesn't support setting maximum slice size, 609 * so we cannot use single NAL mode since the NAL size likely 610 * exceeds the MTU. 611 */ 612 pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED; 613 614 status = pjmedia_h264_packetizer_create(vtool_data->pool, &pktz_cfg, 615 &vtool_data->pktz); 616 if (status != PJ_SUCCESS) 617 return status; 618 619 vtool_data->whole = (param->packing == PJMEDIA_VID_PACKING_WHOLE); 620 if (1) { 621 /* Init format info and apply-param of encoder */ 622 const pjmedia_video_format_info *enc_vfi; 623 pjmedia_video_apply_fmt_param enc_vafp; 624 625 enc_vfi = pjmedia_get_video_format_info(NULL,codec_param->dec_fmt.id); 626 if (!enc_vfi) 627 return PJ_EINVAL; 628 629 pj_bzero(&enc_vafp, sizeof(enc_vafp)); 630 enc_vafp.size = codec_param->enc_fmt.det.vid.size; 631 enc_vafp.buffer = NULL; 632 status = (*enc_vfi->apply_fmt)(enc_vfi, &enc_vafp); 633 if (status != PJ_SUCCESS) 634 return status; 635 636 vtool_data->enc_wxh = codec_param->enc_fmt.det.vid.size.w * 637 codec_param->enc_fmt.det.vid.size.h; 638 vtool_data->enc_input_size = enc_vafp.framebytes; 639 if (!vtool_data->whole) { 640 vtool_data->enc_buf_size = (unsigned)enc_vafp.framebytes; 641 vtool_data->enc_buf = pj_pool_alloc(vtool_data->pool, 642 vtool_data->enc_buf_size); 643 } 644 } 645 646 /* Create encoder */ 647 ret = create_encoder(vtool_data); 648 if (ret != noErr) 649 return PJMEDIA_CODEC_EFAILED; 650 629 651 /* If available, use the "sprop-parameter-sets" fmtp from remote SDP 630 652 * to create the decoder. … … 737 759 NSDictionary *frm_prop = NULL; 738 760 OSStatus ret; 761 #if TARGET_OS_IPHONE 762 UIApplicationState state; 763 #endif 739 764 740 765 PJ_ASSERT_RETURN(codec && input && out_size && output && has_more, 741 766 PJ_EINVAL); 767 768 #if TARGET_OS_IPHONE 769 /* Skip encoding if app is not active, i.e. in the bg. */ 770 state = [UIApplication sharedApplication].applicationState; 771 if (state != UIApplicationStateActive) { 772 *has_more = PJ_FALSE; 773 output->size = 0; 774 output->type = PJMEDIA_FRAME_TYPE_NONE; 775 776 return PJ_SUCCESS; 777 } 778 #endif 742 779 743 780 vtool_data = (vtool_codec_data*) codec->codec_data; … … 810 847 (__bridge CFDictionaryRef)frm_prop, 811 848 NULL, NULL); 849 if (ret == kVTInvalidSessionErr) { 850 /* Reset compression session */ 851 ret = create_encoder(vtool_data); 852 PJ_LOG(3,(THIS_FILE, "Encoder needs to be reset [1]: %s (%d)", 853 (ret == noErr? "success": "fail"), ret)); 854 if (ret == noErr) { 855 /* Retry encoding the frame after successful encoder reset. */ 856 ret = VTCompressionSessionEncodeFrame(vtool_data->enc, image_buf, 857 ts, dur, 858 (__bridge CFDictionaryRef) 859 frm_prop, 860 NULL, NULL); 861 } 862 } 863 812 864 if (ret != noErr) { 813 865 PJ_LOG(4,(THIS_FILE, "Failed to encode frame %d", ret)); … … 819 871 ts.flags = kCMTimeFlags_Indefinite; 820 872 ret = VTCompressionSessionCompleteFrames(vtool_data->enc, ts); 873 if (ret == kVTInvalidSessionErr) { 874 /* Reset compression session */ 875 ret = create_encoder(vtool_data); 876 PJ_LOG(3,(THIS_FILE, "Encoder needs to be reset [2]: %s (%d)", 877 (ret == noErr? "success": "fail"), ret)); 878 if (ret == PJ_SUCCESS) { 879 /* Retry finishing the encoding after successful encoder reset. */ 880 ret = VTCompressionSessionCompleteFrames(vtool_data->enc, ts); 881 } 882 } 883 821 884 if (ret != noErr) { 822 885 PJ_LOG(4,(THIS_FILE, "Failed to complete encoding %d", ret)); … … 990 1053 } 991 1054 992 if (!vtool_data->dec || 1055 if (!vtool_data->dec || !vtool_data->dec_format || 993 1056 !CMFormatDescriptionEqual(dec_format, vtool_data->dec_format)) 994 1057 { … … 1049 1112 pj_bool_t decode_whole = DECODE_WHOLE; 1050 1113 OSStatus ret; 1114 #if TARGET_OS_IPHONE 1115 UIApplicationState state; 1116 #endif 1051 1117 1052 1118 PJ_ASSERT_RETURN(codec && count && packets && out_size && output, 1053 1119 PJ_EINVAL); 1054 1120 PJ_ASSERT_RETURN(output->buf, PJ_EINVAL); 1121 1122 #if TARGET_OS_IPHONE 1123 /* Skip decoding if app is not active, i.e. in the bg. */ 1124 state = [UIApplication sharedApplication].applicationState; 1125 if (state != UIApplicationStateActive) { 1126 output->type = PJMEDIA_FRAME_TYPE_NONE; 1127 output->size = 0; 1128 output->timestamp = packets[0].timestamp; 1129 return PJ_SUCCESS; 1130 } 1131 #endif 1055 1132 1056 1133 vtool_data = (vtool_codec_data*) codec->codec_data; … … 1200 1277 vtool_data->dec, sample_buf, 0, 1201 1278 NULL, NULL); 1279 if (ret == kVTInvalidSessionErr) { 1280 if (vtool_data->dec_format) 1281 CFRelease(vtool_data->dec_format); 1282 vtool_data->dec_format = NULL; 1283 ret = create_decoder(vtool_data); 1284 PJ_LOG(3,(THIS_FILE, "Decoder needs to be reset: %s (%d)", 1285 (ret == noErr? "success": "fail"), ret)); 1286 1287 if (ret == noErr) { 1288 /* Retry decoding the frame after successful reset */ 1289 ret = VTDecompressionSessionDecodeFrame( 1290 vtool_data->dec, sample_buf, 0, 1291 NULL, NULL); 1292 } 1293 } 1294 1202 1295 if (ret != noErr) { 1203 1296 PJ_LOG(5,(THIS_FILE, "Failed to decode frame %d of size "
Note: See TracChangeset
for help on using the changeset viewer.