Changeset 5939 for pjproject/trunk
- Timestamp:
- Mar 5, 2019 6:23:02 AM (5 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/Makefile
r5827 r5939 74 74 transport_ice.o transport_loop.o transport_srtp.o transport_udp.o \ 75 75 types.o vid_codec.o vid_codec_util.o \ 76 vid_port.o vid_stream.o vid_stream_info.o vid_ tee.o \76 vid_port.o vid_stream.o vid_stream_info.o vid_conf.o \ 77 77 wav_player.o wav_playlist.o wav_writer.o wave.o \ 78 78 wsola.o audiodev.o videodev.o -
pjproject/trunk/pjmedia/build/pjmedia.vcproj
r5820 r5939 7008 7008 </File> 7009 7009 <File 7010 RelativePath="..\src\pjmedia\vid_conf.c" 7011 > 7012 </File> 7013 <File 7010 7014 RelativePath="..\src\pjmedia\vid_port.c" 7011 7015 > … … 7697 7701 </File> 7698 7702 <File 7703 RelativePath="..\include\pjmedia\vid_conf.h" 7704 > 7705 </File> 7706 <File 7699 7707 RelativePath="..\include\pjmedia\vid_port.h" 7700 7708 > -
pjproject/trunk/pjmedia/include/pjmedia.h
r3664 r5939 69 69 #include <pjmedia/transport_srtp.h> 70 70 #include <pjmedia/transport_udp.h> 71 #include <pjmedia/vid_codec.h> 72 #include <pjmedia/vid_conf.h> 71 73 #include <pjmedia/vid_port.h> 72 #include <pjmedia/vid_codec.h>73 74 #include <pjmedia/vid_stream.h> 74 #include <pjmedia/vid_tee.h>75 //#include <pjmedia/vid_tee.h> 75 76 #include <pjmedia/wav_playlist.h> 76 77 #include <pjmedia/wav_port.h> -
pjproject/trunk/pjmedia/include/pjmedia/converter.h
r3664 r5939 124 124 125 125 /** 126 * Settings for pjmedia_converter_convert2(). 127 */ 128 typedef void pjmedia_converter_convert_setting; 129 130 131 /** 126 132 * Converter factory operation. 127 133 */ … … 158 164 { 159 165 /** 160 * Convert the buffer inthe source frame and save the result in the166 * Convert the buffer of the source frame and save the result in the 161 167 * buffer of the destination frame, according to conversion format that 162 168 * was specified when the converter was created. … … 165 171 * of calling this function directly. 166 172 * 167 * @param cv The converter instance.168 * @param src_frame The source frame.169 * @param dst_frame The destination frame.170 * 171 * @return PJ_SUCCESS if conversion has been performed172 * successfully.173 * @param cv The converter instance. 174 * @param src_frame The source frame. 175 * @param dst_frame The destination frame. 176 * 177 * @return PJ_SUCCESS if conversion has been performed 178 * successfully. 173 179 */ 174 180 pj_status_t (*convert)(pjmedia_converter *cv, … … 182 188 * of calling this function directly. 183 189 * 184 * @param cv The converter.190 * @param cv The converter. 185 191 */ 186 192 void (*destroy)(pjmedia_converter *cv); 193 194 /** 195 * Convert a region in the buffer of the source frame and put the result 196 * into a region in the buffer of the destination frame, according to 197 * conversion format that was specified when the converter was created. 198 * 199 * Note that application should use #pjmedia_converter_convert2() instead 200 * of calling this function directly. 201 * 202 * @param cv The converter instance. 203 * @param src_frame The source frame. 204 * @param src_frame_size The source frame size. 205 * @param src_reg_pos The source region position. 206 * @param dst_frame The destination frame. 207 * @param dst_frame_size The destination frame size. 208 * @param dst_reg_pos The destination region position. 209 * @param param This is unused for now and must be NULL. 210 * 211 * @return PJ_SUCCESS if conversion has been performed 212 * successfully. 213 */ 214 pj_status_t (*convert2)(pjmedia_converter *cv, 215 pjmedia_frame *src_frame, 216 const pjmedia_rect_size *src_frame_size, 217 const pjmedia_coord *src_pos, 218 pjmedia_frame *dst_frame, 219 const pjmedia_rect_size *dst_frame_size, 220 const pjmedia_coord *dst_pos, 221 pjmedia_converter_convert_setting 222 *param); 187 223 188 224 }; … … 303 339 pjmedia_frame *dst_frame); 304 340 341 342 /** 343 * Convert a region in the buffer of the source frame and put the result 344 * into a region in the buffer of the destination frame, according to 345 * conversion format that was specified when the converter was created. 346 * 347 * @param cv The converter instance. 348 * @param src_frame The source frame. 349 * @param src_frame_size The source frame size. 350 * @param src_reg_pos The source region position. 351 * @param dst_frame The destination frame. 352 * @param dst_frame_size The destination frame size. 353 * @param dst_reg_pos The destination region position. 354 * @param param This is unused for now and must be NULL. 355 * 356 * @return PJ_SUCCESS if conversion has been performed 357 * successfully. 358 */ 359 PJ_DECL(pj_status_t) pjmedia_converter_convert2( 360 pjmedia_converter *cv, 361 pjmedia_frame *src_frame, 362 const pjmedia_rect_size *src_frame_size, 363 const pjmedia_coord *src_pos, 364 pjmedia_frame *dst_frame, 365 const pjmedia_rect_size *dst_frame_size, 366 const pjmedia_coord *dst_pos, 367 pjmedia_converter_convert_setting 368 *param); 369 305 370 /** 306 371 * Destroy the converter. -
pjproject/trunk/pjmedia/include/pjmedia/signatures.h
r3664 r5939 198 198 #define PJMEDIA_SIG_IS_CLASS_VID_OTHER(s) ((s)>>24=='V' && (s)>>16=='O') 199 199 200 #define PJMEDIA_SIG_VID_CONF PJMEDIA_SIG_CLASS_VID_OTHER('C','F') 200 201 #define PJMEDIA_SIG_VID_PORT PJMEDIA_SIG_CLASS_VID_OTHER('P','O') 201 202 -
pjproject/trunk/pjmedia/include/pjmedia/vid_port.h
r4168 r5939 154 154 155 155 /** 156 * Subscribe media event notifications from the specified media port. 157 * Sample use case is that renderer video port needs to monitor stream port 158 * events so renderer can adjust its param whenever stream port detects 159 * format change. 160 * 161 * @param vid_port The video port. 162 * @param port The media port whose events to be monitored. 163 * 164 * @return PJ_SUCCESS on success or the appropriate error code. 165 */ 166 PJ_DECL(pj_status_t) pjmedia_vid_port_subscribe_event( 167 pjmedia_vid_port *vid_port, 168 pjmedia_port *port); 169 170 /** 156 171 * Connect the video port to a downstream (slave) media port. This operation 157 172 * is only valid for video ports created with active interface selected. -
pjproject/trunk/pjmedia/src/pjmedia/converter.c
r5378 r5939 192 192 } 193 193 194 194 PJ_DEF(pj_status_t) pjmedia_converter_convert2( 195 pjmedia_converter *cv, 196 pjmedia_frame *src_frame, 197 const pjmedia_rect_size *src_frame_size, 198 const pjmedia_coord *src_pos, 199 pjmedia_frame *dst_frame, 200 const pjmedia_rect_size *dst_frame_size, 201 const pjmedia_coord *dst_pos, 202 void *param) 203 { 204 if (!cv->op->convert2) 205 return PJ_ENOTSUP; 206 207 return (*cv->op->convert2)(cv, src_frame, src_frame_size, src_pos, 208 dst_frame, dst_frame_size, dst_pos, param); 209 } 210 -
pjproject/trunk/pjmedia/src/pjmedia/converter_libswscale.c
r5306 r5939 34 34 pjmedia_frame *src_frame, 35 35 pjmedia_frame *dst_frame); 36 static pj_status_t libswscale_conv_convert2( 37 pjmedia_converter *converter, 38 pjmedia_frame *src_frame, 39 const pjmedia_rect_size *src_frame_size, 40 const pjmedia_coord *src_pos, 41 pjmedia_frame *dst_frame, 42 const pjmedia_rect_size *dst_frame_size, 43 const pjmedia_coord *dst_pos, 44 pjmedia_converter_convert_setting 45 *param); 36 46 static void libswscale_conv_destroy(pjmedia_converter *converter); 37 47 … … 60 70 { 61 71 &libswscale_conv_convert, 62 &libswscale_conv_destroy 72 &libswscale_conv_destroy, 73 &libswscale_conv_convert2 63 74 }; 64 75 … … 165 176 } 166 177 178 static pj_status_t libswscale_conv_convert2( 179 pjmedia_converter *converter, 180 pjmedia_frame *src_frame, 181 const pjmedia_rect_size *src_frame_size, 182 const pjmedia_coord *src_pos, 183 pjmedia_frame *dst_frame, 184 const pjmedia_rect_size *dst_frame_size, 185 const pjmedia_coord *dst_pos, 186 pjmedia_converter_convert_setting 187 *param) 188 { 189 struct ffmpeg_converter *fcv = (struct ffmpeg_converter*)converter; 190 struct fmt_info *src = &fcv->src, 191 *dst = &fcv->dst; 192 int h; 193 unsigned j; 194 pjmedia_rect_size orig_src_size; 195 pjmedia_rect_size orig_dst_size; 196 197 PJ_UNUSED_ARG(param); 198 199 /* Save original conversion sizes */ 200 orig_src_size = src->apply_param.size; 201 orig_dst_size = dst->apply_param.size; 202 203 /* Set the first act buffer from src frame, and overwrite size. */ 204 src->apply_param.buffer = src_frame->buf; 205 src->apply_param.size = *src_frame_size; 206 (*src->fmt_info->apply_fmt)(src->fmt_info, &src->apply_param); 207 208 /* Set the last act buffer from dst frame, and overwrite size. */ 209 dst->apply_param.buffer = dst_frame->buf; 210 dst->apply_param.size = *dst_frame_size; 211 (*dst->fmt_info->apply_fmt)(dst->fmt_info, &dst->apply_param); 212 213 for (j = 0; j < src->fmt_info->plane_cnt; ++j) { 214 pjmedia_video_apply_fmt_param *ap = &src->apply_param; 215 int y = src_pos->y * ap->plane_bytes[j] / ap->strides[j] / 216 ap->size.h; 217 ap->planes[j] += y * ap->strides[j] + 218 src_pos->x * ap->strides[j] / ap->size.w; 219 } 220 221 for (j = 0; j < dst->fmt_info->plane_cnt; ++j) { 222 pjmedia_video_apply_fmt_param *ap = &dst->apply_param; 223 int y = dst_pos->y * ap->plane_bytes[j] / ap->strides[j] / 224 ap->size.h; 225 ap->planes[j] += y * ap->strides[j] + 226 dst_pos->x * ap->strides[j] / ap->size.w; 227 } 228 229 /* Return back the original conversion size */ 230 src->apply_param.size = orig_src_size; 231 dst->apply_param.size = orig_dst_size; 232 233 h = sws_scale(fcv->sws_ctx, 234 (const uint8_t* const *)src->apply_param.planes, 235 src->apply_param.strides, 236 0, src->apply_param.size.h, 237 dst->apply_param.planes, dst->apply_param.strides); 238 239 //sws_scale() return value can't be trusted? There are cases when 240 //sws_scale() returns zero but conversion seems to work okay. 241 //return h==(int)dst->apply_param.size.h ? PJ_SUCCESS : PJ_EUNKNOWN; 242 PJ_UNUSED_ARG(h); 243 244 return PJ_SUCCESS; 245 } 246 167 247 static void libswscale_conv_destroy(pjmedia_converter *converter) 168 248 { -
pjproject/trunk/pjmedia/src/pjmedia/converter_libyuv.c
r5378 r5939 37 37 pjmedia_frame *dst_frame); 38 38 39 static pj_status_t libyuv_conv_convert2( 40 pjmedia_converter *converter, 41 pjmedia_frame *src_frame, 42 const pjmedia_rect_size *src_frame_size, 43 const pjmedia_coord *src_pos, 44 pjmedia_frame *dst_frame, 45 const pjmedia_rect_size *dst_frame_size, 46 const pjmedia_coord *dst_pos, 47 void *param); 48 39 49 static void libyuv_conv_destroy(pjmedia_converter *converter); 40 50 … … 48 58 { 49 59 &libyuv_conv_convert, 50 &libyuv_conv_destroy 60 &libyuv_conv_destroy, 61 &libyuv_conv_convert2 51 62 }; 52 63 … … 347 358 348 359 /* Convert to I420 or BGRA if needed. */ 349 if ((src_id != PJMEDIA_FORMAT_I420) ||(src_id != PJMEDIA_FORMAT_BGRA)) {360 if ((src_id != PJMEDIA_FORMAT_I420) && (src_id != PJMEDIA_FORMAT_BGRA)) { 350 361 pj_uint32_t next_id = get_next_conv_fmt(src_id); 351 362 if (get_converter_map(src_id, next_id, src_size, dst_size, ++act_num, … … 359 370 360 371 /* Scale if needed */ 361 need_scale = ((src_size->w != dst_size->w) || 362 (src_size->h != dst_size->h)); 372 //need_scale = ((src_size->w != dst_size->w) || 373 //(src_size->h != dst_size->h)); 374 375 // Always enable scale, as this can be used for rendering a region of 376 // a frame to another region of similar/another frame. 377 need_scale = PJ_TRUE; 363 378 364 379 if (need_scale) { … … 623 638 } 624 639 640 static pj_status_t libyuv_conv_convert2( 641 pjmedia_converter *converter, 642 pjmedia_frame *src_frame, 643 const pjmedia_rect_size *src_frame_size, 644 const pjmedia_coord *src_pos, 645 pjmedia_frame *dst_frame, 646 const pjmedia_rect_size *dst_frame_size, 647 const pjmedia_coord *dst_pos, 648 pjmedia_converter_convert_setting 649 *param) 650 { 651 struct libyuv_converter *lconv = (struct libyuv_converter*)converter; 652 int i = 0; 653 fmt_info *src_info = &lconv->act[0].src_fmt_info; 654 fmt_info *dst_info = &lconv->act[lconv->act_num-1].dst_fmt_info; 655 pjmedia_rect_size orig_src_size; 656 pjmedia_rect_size orig_dst_size; 657 658 PJ_UNUSED_ARG(param); 659 660 /* Save original conversion sizes */ 661 orig_src_size = src_info->apply_param.size; 662 orig_dst_size = dst_info->apply_param.size; 663 664 /* Set the first act buffer from src frame, and overwrite size. */ 665 src_info->apply_param.buffer = src_frame->buf; 666 src_info->apply_param.size = *src_frame_size; 667 668 /* Set the last act buffer from dst frame, and overwrite size. */ 669 dst_info->apply_param.buffer = dst_frame->buf; 670 dst_info->apply_param.size = *dst_frame_size; 671 672 for (i=0;i<lconv->act_num;++i) { 673 /* Use destination info as the source info for the next act. */ 674 struct fmt_info *src_fmt_info = (i==0)? src_info : 675 &lconv->act[i-1].dst_fmt_info; 676 677 struct fmt_info *dst_fmt_info = &lconv->act[i].dst_fmt_info; 678 679 (*src_fmt_info->vid_fmt_info->apply_fmt)(src_fmt_info->vid_fmt_info, 680 &src_fmt_info->apply_param); 681 682 (*dst_fmt_info->vid_fmt_info->apply_fmt)(dst_fmt_info->vid_fmt_info, 683 &dst_fmt_info->apply_param); 684 685 /* For first and last acts, apply plane buffer offset and return back 686 * the original sizes. 687 */ 688 if (i == 0) { 689 pjmedia_video_apply_fmt_param *ap = &src_fmt_info->apply_param; 690 unsigned j; 691 for (j = 0; j < src_fmt_info->vid_fmt_info->plane_cnt; ++j) { 692 int y = src_pos->y * ap->plane_bytes[j] / ap->strides[j] / 693 ap->size.h; 694 ap->planes[j] += y * ap->strides[j] + src_pos->x * 695 ap->strides[j] / ap->size.w; 696 } 697 ap->size = orig_src_size; 698 } 699 if (i == lconv->act_num-1) { 700 pjmedia_video_apply_fmt_param *ap = &dst_fmt_info->apply_param; 701 unsigned j; 702 for (j = 0; j < dst_fmt_info->vid_fmt_info->plane_cnt; ++j) 703 { 704 int y = dst_pos->y * ap->plane_bytes[j] / ap->strides[j] / 705 ap->size.h; 706 ap->planes[j] += y * ap->strides[j] + dst_pos->x * 707 ap->strides[j] / ap->size.w; 708 } 709 ap->size = orig_dst_size; 710 } 711 712 switch (lconv->act[i].act_type) { 713 case CONV_PACK_TO_PACK: 714 (*lconv->act[i].method.conv_pack_to_pack)( 715 (const uint8*)src_fmt_info->apply_param.planes[0], 716 src_fmt_info->apply_param.strides[0], 717 dst_fmt_info->apply_param.planes[0], 718 dst_fmt_info->apply_param.strides[0], 719 dst_fmt_info->apply_param.size.w, 720 dst_fmt_info->apply_param.size.h); 721 break; 722 case CONV_PACK_TO_PLANAR: 723 (*lconv->act[i].method.conv_pack_to_planar)( 724 (const uint8*)src_fmt_info->apply_param.planes[0], 725 src_fmt_info->apply_param.strides[0], 726 dst_fmt_info->apply_param.planes[0], 727 dst_fmt_info->apply_param.strides[0], 728 dst_fmt_info->apply_param.planes[1], 729 dst_fmt_info->apply_param.strides[1], 730 dst_fmt_info->apply_param.planes[2], 731 dst_fmt_info->apply_param.strides[2], 732 dst_fmt_info->apply_param.size.w, 733 dst_fmt_info->apply_param.size.h); 734 break; 735 case CONV_PLANAR_TO_PACK: 736 (*lconv->act[i].method.conv_planar_to_pack)( 737 (const uint8*)src_fmt_info->apply_param.planes[0], 738 src_fmt_info->apply_param.strides[0], 739 (const uint8*)src_fmt_info->apply_param.planes[1], 740 src_fmt_info->apply_param.strides[1], 741 (const uint8*)src_fmt_info->apply_param.planes[2], 742 src_fmt_info->apply_param.strides[2], 743 dst_fmt_info->apply_param.planes[0], 744 dst_fmt_info->apply_param.strides[0], 745 dst_fmt_info->apply_param.size.w, 746 dst_fmt_info->apply_param.size.h); 747 break; 748 case CONV_PLANAR_TO_PLANAR: 749 (*lconv->act[i].method.conv_planar_to_planar)( 750 (const uint8*)src_fmt_info->apply_param.planes[0], 751 src_fmt_info->apply_param.strides[0], 752 (const uint8*)src_fmt_info->apply_param.planes[1], 753 src_fmt_info->apply_param.strides[1], 754 (const uint8*)src_fmt_info->apply_param.planes[2], 755 src_fmt_info->apply_param.strides[2], 756 dst_fmt_info->apply_param.planes[0], 757 dst_fmt_info->apply_param.strides[0], 758 dst_fmt_info->apply_param.planes[1], 759 dst_fmt_info->apply_param.strides[1], 760 dst_fmt_info->apply_param.planes[2], 761 dst_fmt_info->apply_param.strides[2], 762 dst_fmt_info->apply_param.size.w, 763 dst_fmt_info->apply_param.size.h); 764 break; 765 case SCALE_PACK: 766 (*lconv->act[i].method.scale_pack)( 767 (const uint8*)src_fmt_info->apply_param.planes[0], 768 src_fmt_info->apply_param.strides[0], 769 src_fmt_info->apply_param.size.w, 770 src_fmt_info->apply_param.size.h, 771 (uint8*)dst_fmt_info->apply_param.planes[0], 772 dst_fmt_info->apply_param.strides[0], 773 dst_fmt_info->apply_param.size.w, 774 dst_fmt_info->apply_param.size.h, 775 LIBYUV_FILTER_MODE); 776 break; 777 case SCALE_PLANAR: 778 (*lconv->act[i].method.scale_planar)( 779 (const uint8*)src_fmt_info->apply_param.planes[0], 780 src_fmt_info->apply_param.strides[0], 781 (const uint8*)src_fmt_info->apply_param.planes[1], 782 src_fmt_info->apply_param.strides[1], 783 (const uint8*)src_fmt_info->apply_param.planes[2], 784 src_fmt_info->apply_param.strides[2], 785 src_fmt_info->apply_param.size.w, 786 src_fmt_info->apply_param.size.h, 787 (uint8*)dst_fmt_info->apply_param.planes[0], 788 dst_fmt_info->apply_param.strides[0], 789 (uint8*)dst_fmt_info->apply_param.planes[1], 790 dst_fmt_info->apply_param.strides[1], 791 (uint8*)dst_fmt_info->apply_param.planes[2], 792 dst_fmt_info->apply_param.strides[2], 793 dst_fmt_info->apply_param.size.w, 794 dst_fmt_info->apply_param.size.h, 795 LIBYUV_FILTER_MODE); 796 break; 797 }; 798 } 799 return PJ_SUCCESS; 800 } 801 625 802 static void libyuv_conv_destroy(pjmedia_converter *converter) 626 803 { -
pjproject/trunk/pjmedia/src/pjmedia/vid_port.c
r5868 r5939 647 647 vp->pasv_port = pp = PJ_POOL_ZALLOC_T(pool, vid_pasv_port); 648 648 pp->vp = vp; 649 pp->base.get_frame = &vid_pasv_port_get_frame; 650 pp->base.put_frame = &vid_pasv_port_put_frame; 649 if (prm->vidparam.dir & PJMEDIA_DIR_CAPTURE) 650 pp->base.get_frame = &vid_pasv_port_get_frame; 651 if (prm->vidparam.dir & PJMEDIA_DIR_RENDER) 652 pp->base.put_frame = &vid_pasv_port_put_frame; 651 653 pjmedia_port_info_init2(&pp->base.info, &vp->dev_name, 652 654 PJMEDIA_SIG_VID_PORT, … … 730 732 } 731 733 734 735 PJ_DEF(pj_status_t) pjmedia_vid_port_subscribe_event( 736 pjmedia_vid_port *vp, 737 pjmedia_port *port) 738 { 739 PJ_ASSERT_RETURN(vp && port, PJ_EINVAL); 740 741 /* Subscribe to port's events */ 742 return pjmedia_event_subscribe(NULL, &client_port_event_cb, vp, port); 743 } 732 744 733 745 PJ_DEF(pj_status_t) pjmedia_vid_port_connect(pjmedia_vid_port *vp, … … 1001 1013 } 1002 1014 1003 if (vp-> stream_role == ROLE_PASSIVE) {1015 if (vp->role == ROLE_ACTIVE && vp->stream_role == ROLE_PASSIVE) { 1004 1016 pjmedia_clock_param clock_param; 1005 1017 … … 1017 1029 /* pjmedia_vid_port_start(vp); */ 1018 1030 pjmedia_vid_dev_stream_start(vp->strm); 1031 1032 /* Update passive port info from the video stream */ 1033 if (vp->role == ROLE_PASSIVE) { 1034 pjmedia_format_copy(&vp->pasv_port->base.info.fmt, 1035 &event->data.fmt_changed.new_fmt); 1036 } 1019 1037 } 1020 1038 -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
r5913 r5939 929 929 rtp_ts_len = stream->frame_ts_len; 930 930 931 /* Empty video frame? Just update RTP timestamp for now */ 932 if (frame->type==PJMEDIA_FRAME_TYPE_VIDEO && frame->size==0) { 933 pjmedia_rtp_encode_rtp(&channel->rtp, channel->pt, 1, 0, 934 rtp_ts_len, (const void**)&rtphdr, 935 &rtphdrlen); 936 return PJ_SUCCESS; 937 } 938 931 939 /* Init frame_out buffer. */ 932 940 pj_bzero(&frame_out, sizeof(frame_out)); -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_cli.c
r5659 r5939 103 103 #define CMD_VIDEO_CODEC ((CMD_VIDEO*10)+6) 104 104 #define CMD_VIDEO_WIN ((CMD_VIDEO*10)+7) 105 #define CMD_VIDEO_CONF ((CMD_VIDEO*10)+8) 105 106 106 107 /* video level 3 command */ … … 130 131 #define CMD_VIDEO_WIN_MOVE ((CMD_VIDEO_WIN*10)+5) 131 132 #define CMD_VIDEO_WIN_RESIZE ((CMD_VIDEO_WIN*10)+6) 133 #define CMD_VIDEO_CONF_LIST ((CMD_VIDEO_CONF*10)+1) 134 #define CMD_VIDEO_CONF_CONNECT ((CMD_VIDEO_CONF*10)+2) 135 #define CMD_VIDEO_CONF_DISCONNECT ((CMD_VIDEO_CONF*10)+3) 132 136 133 137 /* dynamic choice argument list */ … … 2466 2470 } 2467 2471 2472 static pj_status_t cmd_vid_conf_list() 2473 { 2474 pjsua_conf_port_id id[100]; 2475 unsigned count = PJ_ARRAY_SIZE(id); 2476 unsigned i; 2477 pj_status_t status; 2478 2479 status = pjsua_vid_conf_enum_ports(id, &count); 2480 if (status != PJ_SUCCESS) { 2481 PJ_PERROR(1,(THIS_FILE, status, 2482 "Failed enumerating video conf bridge ports")); 2483 return status; 2484 } 2485 2486 PJ_LOG(3,(THIS_FILE," Video conference has %d ports:\n", count)); 2487 PJ_LOG(3,(THIS_FILE," id name format rx tx \n")); 2488 PJ_LOG(3,(THIS_FILE," ------------------------------------------------------------------\n")); 2489 for (i=0; i<count; ++i) { 2490 char li_list[PJSUA_MAX_CALLS*4]; 2491 char tr_list[PJSUA_MAX_CALLS*4]; 2492 char s[32]; 2493 unsigned j; 2494 pjsua_vid_conf_port_info info; 2495 pjmedia_rect_size *size; 2496 pjmedia_ratio *fps; 2497 2498 pjsua_vid_conf_get_port_info(id[i], &info); 2499 size = &info.format.det.vid.size; 2500 fps = &info.format.det.vid.fps; 2501 2502 li_list[0] = '\0'; 2503 for (j=0; j<info.listener_cnt; ++j) { 2504 char s[10]; 2505 pj_ansi_snprintf(s, sizeof(s), "%d%s", 2506 info.listeners[j], 2507 (j==info.listener_cnt-1)?"":","); 2508 pj_ansi_strcat(li_list, s); 2509 } 2510 tr_list[0] = '\0'; 2511 for (j=0; j<info.transmitter_cnt; ++j) { 2512 char s[10]; 2513 pj_ansi_snprintf(s, sizeof(s), "%d%s", info.transmitters[j], 2514 (j==info.transmitter_cnt-1)?"":","); 2515 pj_ansi_strcat(tr_list, s); 2516 } 2517 pjmedia_fourcc_name(info.format.id, s); 2518 s[4] = ' '; 2519 pj_ansi_snprintf(s+5, sizeof(s)-5, "%dx%d@%.1f", 2520 size->w, size->h, (float)(fps->num*1.0/fps->denum)); 2521 PJ_LOG(3,(THIS_FILE,"%3d %.*s%.*s %s%.*s %s%.*s %s\n", 2522 id[i], 2523 (int)info.name.slen, info.name.ptr, 2524 22-(int)info.name.slen, " ", 2525 s, 2526 20-pj_ansi_strlen(s), " ", 2527 tr_list, 2528 12-pj_ansi_strlen(tr_list), " ", 2529 li_list)); 2530 } 2531 return PJ_SUCCESS; 2532 } 2533 2534 static pj_status_t cmd_vid_conf_connect(pj_cli_cmd_val *cval, pj_bool_t connect) 2535 { 2536 int P, Q; 2537 2538 P = (int)pj_strtol(&cval->argv[1]); 2539 Q = (int)pj_strtol(&cval->argv[2]); 2540 if (connect) 2541 return pjsua_vid_conf_connect(P, Q, NULL); 2542 else 2543 return pjsua_vid_conf_disconnect(P, Q); 2544 } 2545 2546 2468 2547 /* Video handler */ 2469 2548 static pj_status_t cmd_video_handler(pj_cli_cmd_val *cval) … … 2545 2624 case CMD_VIDEO_WIN_RESIZE: 2546 2625 status = cmd_resize_vid_win(cval); 2626 break; 2627 case CMD_VIDEO_CONF_LIST: 2628 status = cmd_vid_conf_list(); 2629 break; 2630 case CMD_VIDEO_CONF_CONNECT: 2631 case CMD_VIDEO_CONF_DISCONNECT: 2632 status = cmd_vid_conf_connect(cval, (cmd_id==CMD_VIDEO_CONF_CONNECT)); 2547 2633 break; 2548 2634 } … … 3051 3137 " </CMD>" 3052 3138 " </CMD>" 3139 " <CMD name='conf' id='6008' desc='Video conference commands'>" 3140 " <CMD name='list' id='60081' desc='List all ports in video conference'/>" 3141 " <CMD name='cc' id='60082' desc='Connect ports in video conference'>" 3142 " <ARG name='source' type='int' desc='Source port ID'/>" 3143 " <ARG name='sink' type='int' desc='Sink port ID'/>" 3144 " </CMD>" 3145 " <CMD name='cd' id='60083' desc='Disconnect ports in video conference'>" 3146 " <ARG name='source' type='int' desc='Source port ID'/>" 3147 " <ARG name='sink' type='int' desc='Sink port ID'/>" 3148 " </CMD>" 3149 " </CMD>" 3053 3150 "</CMD>"; 3054 3151 -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_legacy.c
r5834 r5939 297 297 puts("| vid win move ID X Y Move window ID to position X,Y |"); 298 298 puts("| vid win resize ID w h Resize window ID to the specified width, height |"); 299 puts("| vid conf list List all video ports in video conference bridge |"); 300 puts("| vid conf cc P Q Connect port P to Q in the video conf bridge |"); 301 puts("| vid conf cd P Q Disconnect port P to Q in the video conf bridge |"); 299 302 puts("+=============================================================================+"); 300 303 printf("| Video will be %s in the next offer/answer %s |\n", … … 592 595 } else 593 596 goto on_error; 597 } else if (strcmp(argv[1], "conf")==0) { 598 pj_status_t status; 599 600 if (argc==3 && strcmp(argv[2], "list")==0) { 601 pjsua_conf_port_id id[100]; 602 unsigned count = PJ_ARRAY_SIZE(id); 603 604 status = pjsua_vid_conf_enum_ports(id, &count); 605 if (status != PJ_SUCCESS) { 606 PJ_PERROR(1,(THIS_FILE, status, 607 "Failed enumerating video conf bridge ports")); 608 } else { 609 unsigned i; 610 printf(" Video conference has %d ports:\n", count); 611 printf(" id name format rx tx \n"); 612 printf(" ------------------------------------------------------------------\n"); 613 for (i=0; i<count; ++i) { 614 char li_list[PJSUA_MAX_CALLS*4]; 615 char tr_list[PJSUA_MAX_CALLS*4]; 616 char s[32]; 617 unsigned j; 618 pjsua_vid_conf_port_info info; 619 pjmedia_rect_size *size; 620 pjmedia_ratio *fps; 621 622 pjsua_vid_conf_get_port_info(id[i], &info); 623 size = &info.format.det.vid.size; 624 fps = &info.format.det.vid.fps; 625 626 li_list[0] = '\0'; 627 for (j=0; j<info.listener_cnt; ++j) { 628 char s[10]; 629 pj_ansi_snprintf(s, sizeof(s), "%d%s", 630 info.listeners[j], 631 (j==info.listener_cnt-1)?"":","); 632 pj_ansi_strcat(li_list, s); 633 } 634 tr_list[0] = '\0'; 635 for (j=0; j<info.transmitter_cnt; ++j) { 636 char s[10]; 637 pj_ansi_snprintf(s, sizeof(s), "%d%s", 638 info.transmitters[j], 639 (j==info.transmitter_cnt-1)?"":","); 640 pj_ansi_strcat(tr_list, s); 641 } 642 pjmedia_fourcc_name(info.format.id, s); 643 s[4] = ' '; 644 pj_ansi_snprintf(s+5, sizeof(s)-5, "%dx%d@%.1f", 645 size->w, size->h, 646 (float)(fps->num*1.0/fps->denum)); 647 printf("%3d %.*s%.*s %s%.*s %s%.*s %s\n", 648 id[i], 649 (int)info.name.slen, info.name.ptr, 650 22-(int)info.name.slen, " ", 651 s, 652 20-pj_ansi_strlen(s), " ", 653 tr_list, 654 12-pj_ansi_strlen(tr_list), " ", 655 li_list); 656 } 657 } 658 } else if (argc==5 && strcmp(argv[2], "cc")==0) { 659 int P, Q; 660 P = atoi(argv[3]); 661 Q = atoi(argv[4]); 662 pjsua_vid_conf_connect(P, Q, NULL); 663 } else if (argc==5 && strcmp(argv[2], "cd")==0) { 664 int P, Q; 665 P = atoi(argv[3]); 666 Q = atoi(argv[4]); 667 pjsua_vid_conf_disconnect(P, Q); 668 } else { 669 goto on_error; 670 } 594 671 } else 595 672 goto on_error; -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r5923 r5939 4680 4680 pjsua_vid_win_id win_in; 4681 4681 4682 /** The video capture device for outgoing transmission, 4683 * if any, or PJMEDIA_VID_INVALID_DEV 4682 /** 4683 * The video conference port number for the call in decoding 4684 * direction. 4685 */ 4686 pjsua_conf_port_id dec_slot; 4687 4688 /** 4689 * The video conference port number for the call in encoding 4690 * direction. 4691 */ 4692 pjsua_conf_port_id enc_slot; 4693 4694 /** 4695 * The video capture device for outgoing transmission, 4696 * if any, or PJMEDIA_VID_INVALID_DEV 4684 4697 */ 4685 4698 pjmedia_vid_dev_index cap_dev; … … 5168 5181 */ 5169 5182 PJ_DECL(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id); 5183 5184 5185 /** 5186 * Get the video window associated with the call. Note that this function 5187 * will only evaluate the first video stream in the call, to query any other 5188 * video stream, use pjsua_call_get_info(). 5189 * 5190 * @param call_id Call identification. 5191 * 5192 * @return Video window, or PJSUA_INVALID_ID when the 5193 * media has not been established or is not active. 5194 */ 5195 PJ_DECL(pjsua_vid_win_id) pjsua_call_get_vid_win(pjsua_call_id call_id); 5196 5197 5198 /** 5199 * Get the video conference port identification associated with the call. 5200 * Note that this function will only evaluate the first video stream in 5201 * the call, to query any other video stream, use pjsua_call_get_info(). 5202 * 5203 * @param call_id Call identification. 5204 * @param dir Port direction to be queried. Valid values are 5205 * PJMEDIA_DIR_ENCODING and PJMEDIA_DIR_DECODING only. 5206 * 5207 * @return Conference port ID, or PJSUA_INVALID_ID when the 5208 * media has not been established or is not active. 5209 */ 5210 PJ_DECL(pjsua_conf_port_id) pjsua_call_get_vid_conf_port( 5211 pjsua_call_id call_id, 5212 pjmedia_dir dir); 5170 5213 5171 5214 /** … … 6704 6747 6705 6748 /** 6706 * This structure desc ibes information about a particular media port that6749 * This structure describes information about a particular media port that 6707 6750 * has been registered into the conference bridge. Application can query 6708 6751 * this info by calling #pjsua_conf_get_port_info(). … … 6741 6784 6742 6785 /** Array of listeners (in other words, ports where this port is 6743 * transmitting to .6786 * transmitting to). 6744 6787 */ 6745 6788 pjsua_conf_port_id listeners[PJSUA_MAX_CONF_PORTS]; … … 7808 7851 7809 7852 /** 7853 * Get video conference slot ID of the specified capture device, if any. 7854 * 7855 * @param id The capture device ID. 7856 * 7857 * @return The video conference slot ID of the specified capture 7858 * device ID, or PJSUA_INVALID_ID if preview has not been 7859 * started for the device. 7860 */ 7861 PJ_DECL(pjsua_conf_port_id) pjsua_vid_preview_get_vid_conf_port( 7862 pjmedia_vid_dev_index id); 7863 7864 /** 7810 7865 * Stop video preview. 7811 7866 * … … 7843 7898 */ 7844 7899 pjmedia_vid_dev_index rdr_dev; 7900 7901 /** 7902 * Renderer port ID in the video conference bridge. 7903 */ 7904 pjsua_conf_port_id slot_id; 7845 7905 7846 7906 /** … … 8018 8078 8019 8079 8080 /* 8081 * Video conference API 8082 */ 8083 8084 /** 8085 * This structure describes information about a particular video media port 8086 * that has been registered into the video conference bridge. Application 8087 * can query this info by calling #pjsua_vid_conf_get_port_info(). 8088 */ 8089 typedef struct pjsua_vid_conf_port_info 8090 { 8091 /** Conference port number. */ 8092 pjsua_conf_port_id slot_id; 8093 8094 /** Port name. */ 8095 pj_str_t name; 8096 8097 /** Format. */ 8098 pjmedia_format format; 8099 8100 /** Number of listeners in the array. */ 8101 unsigned listener_cnt; 8102 8103 /** Array of listeners (in other words, ports where this port is 8104 * transmitting to). 8105 */ 8106 pjsua_conf_port_id listeners[PJSUA_MAX_CONF_PORTS]; 8107 8108 /** Number of transmitters in the array. */ 8109 unsigned transmitter_cnt; 8110 8111 /** Array of transmitters (in other words, ports where this port is 8112 * receiving from). 8113 */ 8114 pjsua_conf_port_id transmitters[PJSUA_MAX_CONF_PORTS]; 8115 8116 } pjsua_vid_conf_port_info; 8117 8118 8119 /** 8120 * Get current number of active ports in the bridge. 8121 * 8122 * @return The number. 8123 */ 8124 PJ_DECL(unsigned) pjsua_vid_conf_get_active_ports(void); 8125 8126 8127 /** 8128 * Enumerate all video conference ports. 8129 * 8130 * @param id Array of conference port ID to be initialized. 8131 * @param count On input, specifies max elements in the array. 8132 * On return, it contains actual number of elements 8133 * that have been initialized. 8134 * 8135 * @return PJ_SUCCESS on success, or the appropriate error code. 8136 */ 8137 PJ_DECL(pj_status_t) pjsua_vid_conf_enum_ports(pjsua_conf_port_id id[], 8138 unsigned *count); 8139 8140 8141 /** 8142 * Get information about the specified video conference port 8143 * 8144 * @param port_id Port identification. 8145 * @param info Pointer to store the port info. 8146 * 8147 * @return PJ_SUCCESS on success, or the appropriate error code. 8148 */ 8149 PJ_DECL(pj_status_t) pjsua_vid_conf_get_port_info( 8150 pjsua_conf_port_id port_id, 8151 pjsua_vid_conf_port_info *info); 8152 8153 8154 /** 8155 * Add arbitrary video media port to PJSUA's video conference bridge. 8156 * Application can use this function to add the media port that it creates. 8157 * For media ports that are created by PJSUA-LIB (such as calls, AVI player), 8158 * PJSUA-LIB will automatically add the port to the bridge. 8159 * 8160 * @param pool Pool to use. 8161 * @param port Media port to be added to the bridge. 8162 * @param param Currently this is not used and must be set to NULL. 8163 * @param p_id Optional pointer to receive the conference 8164 * slot id. 8165 * 8166 * @return PJ_SUCCESS on success, or the appropriate error code. 8167 */ 8168 PJ_DECL(pj_status_t) pjsua_vid_conf_add_port(pj_pool_t *pool, 8169 pjmedia_port *port, 8170 const void *param, 8171 pjsua_conf_port_id *p_id); 8172 8173 8174 /** 8175 * Remove arbitrary slot from the video conference bridge. Application should 8176 * only call this function if it registered the port manually with previous 8177 * call to #pjsua_vid_conf_add_port(). 8178 * 8179 * @param port_id The slot id of the port to be removed. 8180 * 8181 * @return PJ_SUCCESS on success, or the appropriate error code. 8182 */ 8183 PJ_DECL(pj_status_t) pjsua_vid_conf_remove_port(pjsua_conf_port_id port_id); 8184 8185 8186 /** 8187 * Establish unidirectional video flow from souce to sink. One source 8188 * may transmit to multiple destinations/sink. And if multiple 8189 * sources are transmitting to the same sink, the video will be mixed 8190 * together (currently, each source will be resized down so all sources will 8191 * occupy the same portion in the sink video frame). Source and sink may 8192 * refer to the same ID, effectively looping the media. 8193 * 8194 * If bidirectional media flow is desired, application needs to call 8195 * this function twice, with the second one having the arguments 8196 * reversed. 8197 * 8198 * @param source Port ID of the source media/transmitter. 8199 * @param sink Port ID of the destination media/received. 8200 * @param param Currently this is not used and must be set to NULL. 8201 * 8202 * @return PJ_SUCCESS on success, or the appropriate error code. 8203 */ 8204 PJ_DECL(pj_status_t) pjsua_vid_conf_connect(pjsua_conf_port_id source, 8205 pjsua_conf_port_id sink, 8206 const void *param); 8207 8208 8209 /** 8210 * Disconnect video flow from the source to destination port. 8211 * 8212 * @param source Port ID of the source media/transmitter. 8213 * @param sink Port ID of the destination media/received. 8214 * 8215 * @return PJ_SUCCESS on success, or the appropriate error code. 8216 */ 8217 PJ_DECL(pj_status_t) pjsua_vid_conf_disconnect(pjsua_conf_port_id source, 8218 pjsua_conf_port_id sink); 8219 8220 8020 8221 8021 8222 /* end of VIDEO API */ -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
r5923 r5939 60 60 struct { 61 61 pjmedia_vid_stream *stream; /**< The video stream. */ 62 pjsua_conf_port_id strm_enc_slot; /**< Stream encode slot */ 63 pjsua_conf_port_id strm_dec_slot; /**< Stream decode slot */ 62 64 pjsua_vid_win_id cap_win_id;/**< The video capture window */ 63 65 pjsua_vid_win_id rdr_win_id;/**< The video render window */ … … 404 406 pjmedia_vid_port *vp_cap; /**< Capture vidport. */ 405 407 pjmedia_vid_port *vp_rend; /**< Renderer vidport */ 406 pjmedia_port *tee; /**< Video tee */ 408 pjsua_conf_port_id cap_slot; /**< Capturer conf slot */ 409 pjsua_conf_port_id rend_slot; /**< Renderer conf slot */ 407 410 pjmedia_vid_dev_index preview_cap_id;/**< Capture dev id */ 408 411 pj_bool_t preview_running;/**< Preview is started*/ … … 513 516 /* For keeping video device settings */ 514 517 #if PJSUA_HAS_VIDEO 518 pjmedia_vid_conf *vid_conf; 515 519 pj_uint32_t vid_caps[PJMEDIA_VID_DEV_MAX_DEVS]; 516 520 pjmedia_vid_dev_param vid_param[PJMEDIA_VID_DEV_MAX_DEVS]; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r5937 r5939 153 153 call_med->strm.v.cap_win_id = PJSUA_INVALID_ID; 154 154 call_med->strm.v.rdr_win_id = PJSUA_INVALID_ID; 155 call_med->strm.v.strm_dec_slot = PJSUA_INVALID_ID; 156 call_med->strm.v.strm_enc_slot = PJSUA_INVALID_ID; 155 157 call_med->call = call; 156 158 call_med->idx = i; … … 2224 2226 info->media[info->media_cnt].stream.vid.win_in = 2225 2227 call_med->strm.v.rdr_win_id; 2228 2229 info->media[info->media_cnt].stream.vid.dec_slot = 2230 call_med->strm.v.strm_dec_slot; 2231 info->media[info->media_cnt].stream.vid.enc_slot = 2232 call_med->strm.v.strm_enc_slot; 2226 2233 2227 2234 if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) { -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r5923 r5939 1477 1477 call_med->last_req_keyframe = now; 1478 1478 } 1479 } 1480 } 1481 break; 1482 1483 case PJMEDIA_EVENT_FMT_CHANGED: 1484 if (call_med->strm.v.rdr_win_id != PJSUA_INVALID_ID) { 1485 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.rdr_win_id]; 1486 if (event->src == w->vp_rend) { 1487 /* Renderer just changed format, reconnect stream */ 1488 pjsua_vid_conf_disconnect(call_med->strm.v.strm_dec_slot, 1489 w->rend_slot); 1490 pjsua_vid_conf_connect(call_med->strm.v.strm_dec_slot, 1491 w->rend_slot, NULL); 1479 1492 } 1480 1493 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
r5842 r5939 27 27 28 28 #define ENABLE_EVENT 1 29 #define VID_TEE_MAX_PORT (PJSUA_MAX_CALLS + 1)30 29 31 30 #define PJSUA_SHOW_WINDOW 1 … … 66 65 PJ_PERROR(1,(THIS_FILE, status, 67 66 "Error creating PJMEDIA video codec manager")); 67 goto on_error; 68 } 69 70 status = pjmedia_vid_conf_create(pjsua_var.pool, NULL, 71 &pjsua_var.vid_conf); 72 if (status != PJ_SUCCESS) { 73 PJ_PERROR(1,(THIS_FILE, status, 74 "Error creating PJMEDIA video conference bridge")); 68 75 goto on_error; 69 76 } … … 139 146 pjsua_var.win[i].pool = NULL; 140 147 } 148 } 149 150 if (pjsua_var.vid_conf) { 151 pjmedia_vid_conf_destroy(pjsua_var.vid_conf); 152 pjsua_var.vid_conf = NULL; 141 153 } 142 154 … … 515 527 } 516 528 529 /* 530 * Get video conference slot ID of the specified capture device. 531 */ 532 PJ_DEF(pjsua_conf_port_id) pjsua_vid_preview_get_vid_conf_port( 533 pjmedia_vid_dev_index id) 534 { 535 pjsua_vid_win_id wid; 536 pjsua_vid_win *w; 537 538 wid = vid_preview_get_win(id, PJ_TRUE); 539 if (wid == PJSUA_INVALID_ID) 540 return PJSUA_INVALID_ID; 541 542 w = &pjsua_var.win[wid]; 543 return w->cap_slot; 544 } 545 546 517 547 PJ_DEF(void) pjsua_vid_win_reset(pjsua_vid_win_id wid) 518 548 { … … 528 558 529 559 /* Allocate and initialize pjsua video window: 530 * - If the type is preview , video capture, tee, and render531 * will be instantiated .532 * - If the type is stream , only rendererwill be created.560 * - If the type is preview: capture port and render port 561 * will be instantiated, and connected via conf. 562 * - If the type is stream: only render port will be created. 533 563 */ 534 564 static pj_status_t create_vid_win(pjsua_vid_win_type type, … … 673 703 674 704 /* Create capture video port */ 675 vp_param.active = PJ_ TRUE;705 vp_param.active = PJ_FALSE; 676 706 vp_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; 677 707 … … 703 733 fmt = &fmt_; 704 734 705 /* Create video tee */ 706 status = pjmedia_vid_tee_create(w->pool, fmt, VID_TEE_MAX_PORT, 707 &w->tee); 708 if (status != PJ_SUCCESS) 709 goto on_error; 710 711 /* Connect capturer to the video tee */ 712 status = pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 735 /* Register capturer to the video conf */ 736 status = pjsua_vid_conf_add_port( 737 w->pool, 738 pjmedia_vid_port_get_passive_port(w->vp_cap), 739 NULL, &w->cap_slot); 713 740 if (status != PJ_SUCCESS) 714 741 goto on_error; … … 739 766 goto on_error; 740 767 741 vp_param.active = (w->type == PJSUA_WND_TYPE_STREAM);768 vp_param.active = PJ_FALSE; 742 769 vp_param.vidparam.dir = PJMEDIA_DIR_RENDER; 743 770 vp_param.vidparam.fmt = *fmt; … … 756 783 goto on_error; 757 784 758 /* For preview window, connect capturer & renderer (via tee) */ 785 /* Register renderer to the video conf */ 786 status = pjsua_vid_conf_add_port( 787 w->pool, 788 pjmedia_vid_port_get_passive_port(w->vp_rend), 789 NULL, &w->rend_slot); 790 if (status != PJ_SUCCESS) 791 goto on_error; 792 793 /* For preview window, connect capturer & renderer (via conf) */ 759 794 if (w->type == PJSUA_WND_TYPE_PREVIEW) { 760 pjmedia_port *rend_port; 761 762 rend_port = pjmedia_vid_port_get_passive_port(w->vp_rend); 763 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, rend_port); 795 status = pjsua_vid_conf_connect(w->cap_slot, w->rend_slot, NULL); 764 796 if (status != PJ_SUCCESS) 765 797 goto on_error; … … 799 831 800 832 if (w->vp_cap) { 833 pjsua_vid_conf_remove_port(w->cap_slot); 801 834 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 802 835 w->vp_cap); 803 836 pjmedia_vid_port_stop(w->vp_cap); 804 pjmedia_vid_port_disconnect(w->vp_cap);805 837 pjmedia_vid_port_destroy(w->vp_cap); 806 838 } 807 839 if (w->vp_rend) { 840 pjsua_vid_conf_remove_port(w->rend_slot); 808 841 pjmedia_event_unsubscribe(NULL, &call_media_on_event, NULL, 809 842 w->vp_rend); … … 811 844 pjmedia_vid_port_destroy(w->vp_rend); 812 845 } 813 if (w->tee) {814 pjmedia_port_destroy(w->tee);815 }816 846 pjsua_vid_win_reset(wid); 817 847 … … 850 880 call_med->strm.v.rdr_dev = acc->cfg.vid_rend_dev; 851 881 call_med->strm.v.cap_dev = acc->cfg.vid_cap_dev; 882 call_med->strm.v.strm_dec_slot = PJSUA_INVALID_ID; 883 call_med->strm.v.strm_enc_slot = PJSUA_INVALID_ID; 852 884 if (call_med->strm.v.rdr_dev == PJMEDIA_VID_DEFAULT_RENDER_DEV) { 853 885 pjmedia_vid_dev_info info; … … 979 1011 pj_log_push_indent(); 980 1012 1013 /* Retrieve stream decoding port */ 981 1014 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 982 1015 PJMEDIA_DIR_DECODING, … … 1010 1043 #endif 1011 1044 1012 /* Connect renderer to stream */ 1013 status = pjmedia_vid_port_connect(w->vp_rend, media_port, 1014 PJ_FALSE); 1045 /* Register renderer to stream events */ 1046 pjmedia_vid_port_subscribe_event(w->vp_rend, media_port); 1047 1048 /* Register stream decoding to conf, using tmp_pool should be fine 1049 * as bridge will create its own pool (using tmp_pool factory). 1050 */ 1051 status = pjsua_vid_conf_add_port(tmp_pool, media_port, NULL, 1052 &call_med->strm.v.strm_dec_slot); 1053 if (status != PJ_SUCCESS) { 1054 pj_log_pop_indent(); 1055 goto on_error; 1056 } 1057 1058 /* Connect stream to renderer (via conf) */ 1059 status = pjsua_vid_conf_connect(call_med->strm.v.strm_dec_slot, 1060 w->rend_slot, NULL); 1015 1061 if (status != PJ_SUCCESS) { 1016 1062 pj_log_pop_indent(); … … 1042 1088 pj_log_push_indent(); 1043 1089 1090 /* Retrieve stream encoding port */ 1044 1091 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 1045 1092 PJMEDIA_DIR_ENCODING, … … 1079 1126 #endif 1080 1127 1081 /* Connect stream to capturer (via video window tee) */ 1082 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port); 1128 /* Register stream encoding to conf, using tmp_pool should be fine 1129 * as bridge will create its own pool (using tmp_pool factory). 1130 */ 1131 status = pjsua_vid_conf_add_port(tmp_pool, media_port, NULL, 1132 &call_med->strm.v.strm_enc_slot); 1133 if (status != PJ_SUCCESS) { 1134 pj_log_pop_indent(); 1135 goto on_error; 1136 } 1137 1138 /* Connect capturer to stream encoding (via conf) */ 1139 status = pjsua_vid_conf_connect(w->cap_slot, 1140 call_med->strm.v.strm_enc_slot, 1141 NULL); 1083 1142 if (status != PJ_SUCCESS) { 1084 1143 pj_log_pop_indent(); … … 1133 1192 pj_log_push_indent(); 1134 1193 1194 /* Unregister video stream ports (encode+decode) from conference */ 1195 pjsua_vid_conf_remove_port(call_med->strm.v.strm_enc_slot); 1196 pjsua_vid_conf_remove_port(call_med->strm.v.strm_dec_slot); 1197 1135 1198 pjmedia_vid_stream_send_rtcp_bye(strm); 1136 1199 1137 1200 if (call_med->strm.v.cap_win_id != PJSUA_INVALID_ID) { 1138 pjmedia_port *media_port;1139 1201 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.cap_win_id]; 1140 pj_status_t status; 1141 1142 /* Stop the capture before detaching stream and unsubscribing event */ 1143 pjmedia_vid_port_stop(w->vp_cap); 1144 1145 /* Disconnect video stream from capture device */ 1146 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 1147 PJMEDIA_DIR_ENCODING, 1148 &media_port); 1149 if (status == PJ_SUCCESS) { 1150 pjmedia_vid_tee_remove_dst_port(w->tee, media_port); 1151 } 1152 1153 /* Unsubscribe event */ 1202 1203 /* Unsubscribe event */ 1154 1204 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 1155 1205 w->vp_cap); 1156 1206 1157 /* Re-start capture again, if it is used by other stream */ 1158 if (w->ref_cnt > 1) 1159 pjmedia_vid_port_start(w->vp_cap); 1160 1207 /* Decrement ref count of preview video window */ 1161 1208 dec_vid_win(call_med->strm.v.cap_win_id); 1162 1209 call_med->strm.v.cap_win_id = PJSUA_INVALID_ID; … … 1166 1213 pjsua_vid_win *w = &pjsua_var.win[call_med->strm.v.rdr_win_id]; 1167 1214 1168 /* Stop the render before unsubscribing event */1215 /* Unsubscribe event, but stop the render first */ 1169 1216 pjmedia_vid_port_stop(w->vp_rend); 1170 1217 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 1171 1218 w->vp_rend); 1172 1219 1220 /* Decrement ref count of stream video window */ 1173 1221 dec_vid_win(call_med->strm.v.rdr_win_id); 1174 1222 call_med->strm.v.rdr_win_id = PJSUA_INVALID_ID; … … 1432 1480 1433 1481 wi->rdr_dev = vparam.rend_id; 1482 wi->slot_id = w->rend_slot; 1434 1483 wi->hwnd = vparam.window; 1435 1484 wi->show = !vparam.window_hide; … … 2043 2092 w->preview_cap_id = cap_dev; 2044 2093 call_med->strm.v.cap_dev = cap_dev; 2094 /* Yay, change capturer done! */ 2045 2095 return PJ_SUCCESS; 2046 2096 } 2047 2097 2048 /* No it doesn't support fast switching. Do slow switching then.. */ 2098 /* Oh no, it doesn't support fast switching. Do normal change then, 2099 * i.e: remove the old and create a new capture. 2100 */ 2049 2101 status = pjmedia_vid_stream_get_port(call_med->strm.v.stream, 2050 2102 PJMEDIA_DIR_ENCODING, &media_port); … … 2055 2107 w->vp_cap); 2056 2108 2057 /* temporarily disconnect while we operate on the tee. */ 2058 pjmedia_vid_port_disconnect(w->vp_cap); 2059 2060 /* = Detach stream port from the old capture device's tee = */ 2061 status = pjmedia_vid_tee_remove_dst_port(w->tee, media_port); 2062 if (status != PJ_SUCCESS) { 2063 /* Something wrong, assume that media_port has been removed 2064 * and continue. 2065 */ 2066 PJ_PERROR(4,(THIS_FILE, status, 2067 "Warning: call %d: unable to remove video from tee", 2068 call->index)); 2069 } 2070 2071 /* Reconnect again immediately. We're done with w->tee */ 2072 pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 2109 /* Disconnect the old capture device to stream encoding port */ 2110 status = pjsua_vid_conf_disconnect(w->cap_slot, 2111 call_med->strm.v.strm_enc_slot); 2112 if (status != PJ_SUCCESS) 2113 return status; 2114 2073 2115 2074 2116 /* = Attach stream port to the new capture device = */ … … 2098 2140 inc_vid_win(new_wid); 2099 2141 new_w = &pjsua_var.win[new_wid]; 2100 2101 /* Connect stream to capturer (via video window tee) */2102 status = pjmedia_vid_tee_add_dst_port2(new_w->tee, 0, media_port);2103 if (status != PJ_SUCCESS)2104 goto on_error;2105 2142 2106 2143 if (new_w->vp_rend) { … … 2123 2160 } 2124 2161 2162 /* Connect capturer to stream encoding port (via conf) */ 2163 status = pjsua_vid_conf_connect(new_w->cap_slot, 2164 call_med->strm.v.strm_enc_slot, 2165 NULL); 2166 if (status != PJ_SUCCESS) 2167 goto on_error; 2168 2125 2169 /* Finally */ 2126 2170 call_med->strm.v.cap_dev = cap_dev; … … 2139 2183 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, 2140 2184 new_w->vp_cap); 2141 /* Disconnect media port from the new capturer */ 2142 pjmedia_vid_tee_remove_dst_port(new_w->tee, media_port); 2185 2143 2186 /* Release the new capturer */ 2144 2187 dec_vid_win(new_wid); … … 2146 2189 2147 2190 /* Revert back to the old capturer */ 2148 pjmedia_vid_port_disconnect(w->vp_cap); 2149 status = pjmedia_vid_tee_add_dst_port2(w->tee, 0, media_port); 2150 pjmedia_vid_port_connect(w->vp_cap, w->tee, PJ_FALSE); 2191 status = pjsua_vid_conf_connect(w->cap_slot, 2192 call_med->strm.v.strm_enc_slot, NULL); 2151 2193 if (status != PJ_SUCCESS) 2152 2194 return status; … … 2372 2414 } 2373 2415 2416 2417 /***************************************************************************** 2418 * Video conference 2419 */ 2420 2421 /* 2422 * Get current number of active ports in the bridge. 2423 */ 2424 PJ_DEF(unsigned) pjsua_vid_conf_get_active_ports(void) 2425 { 2426 return pjmedia_vid_conf_get_port_count(pjsua_var.vid_conf); 2427 } 2428 2429 2430 /* 2431 * Enumerate all video conference ports. 2432 */ 2433 PJ_DEF(pj_status_t) pjsua_vid_conf_enum_ports( pjsua_conf_port_id id[], 2434 unsigned *count) 2435 { 2436 return pjmedia_vid_conf_enum_ports(pjsua_var.vid_conf, 2437 (unsigned*)id, count); 2438 } 2439 2440 2441 /* 2442 * Get information about the specified video conference port 2443 */ 2444 PJ_DEF(pj_status_t) pjsua_vid_conf_get_port_info( 2445 pjsua_conf_port_id port_id, 2446 pjsua_vid_conf_port_info *info) 2447 { 2448 pjmedia_vid_conf_port_info cinfo; 2449 unsigned i; 2450 pj_status_t status; 2451 2452 status = pjmedia_vid_conf_get_port_info(pjsua_var.vid_conf, 2453 (unsigned)port_id, &cinfo); 2454 if (status != PJ_SUCCESS) 2455 return status; 2456 2457 pj_bzero(info, sizeof(*info)); 2458 info->slot_id = port_id; 2459 info->name = cinfo.name; 2460 pjmedia_format_copy(&info->format, &cinfo.format); 2461 2462 /* Build array of listeners */ 2463 info->listener_cnt = cinfo.listener_cnt; 2464 for (i=0; i<cinfo.listener_cnt; ++i) { 2465 info->listeners[i] = cinfo.listener_slots[i]; 2466 } 2467 2468 /* Build array of transmitters */ 2469 info->transmitter_cnt = cinfo.transmitter_cnt; 2470 for (i=0; i<cinfo.transmitter_cnt; ++i) { 2471 info->transmitters[i] = cinfo.transmitter_slots[i]; 2472 } 2473 2474 return PJ_SUCCESS; 2475 2476 } 2477 2478 2479 /* 2480 * Add arbitrary video media port to PJSUA's video conference bridge. 2481 */ 2482 PJ_DEF(pj_status_t) pjsua_vid_conf_add_port( pj_pool_t *pool, 2483 pjmedia_port *port, 2484 const void *param, 2485 pjsua_conf_port_id *p_id) 2486 { 2487 pj_status_t status; 2488 2489 PJ_UNUSED_ARG(param); 2490 2491 status = pjmedia_vid_conf_add_port(pjsua_var.vid_conf, pool, 2492 port, NULL, NULL, (unsigned*)p_id); 2493 if (status != PJ_SUCCESS) { 2494 if (p_id) 2495 *p_id = PJSUA_INVALID_ID; 2496 } 2497 2498 return status; 2499 } 2500 2501 2502 /* 2503 * Remove arbitrary slot from the video conference bridge. 2504 */ 2505 PJ_DEF(pj_status_t) pjsua_vid_conf_remove_port(pjsua_conf_port_id id) 2506 { 2507 return pjmedia_vid_conf_remove_port(pjsua_var.vid_conf, (unsigned)id); 2508 } 2509 2510 2511 /* 2512 * Establish unidirectional video flow from souce to sink. 2513 */ 2514 PJ_DEF(pj_status_t) pjsua_vid_conf_connect( pjsua_conf_port_id source, 2515 pjsua_conf_port_id sink, 2516 const void *param) 2517 { 2518 PJ_UNUSED_ARG(param); 2519 return pjmedia_vid_conf_connect_port(pjsua_var.vid_conf, source, sink, 2520 NULL); 2521 } 2522 2523 2524 /* 2525 * Disconnect video flow from the source to destination port. 2526 */ 2527 PJ_DEF(pj_status_t) pjsua_vid_conf_disconnect(pjsua_conf_port_id source, 2528 pjsua_conf_port_id sink) 2529 { 2530 return pjmedia_vid_conf_disconnect_port(pjsua_var.vid_conf, source, sink); 2531 } 2532 2533 /* 2534 * Get the video window associated with the call. 2535 */ 2536 PJ_DEF(pjsua_vid_win_id) pjsua_call_get_vid_win(pjsua_call_id call_id) 2537 { 2538 pjsua_call *call; 2539 pjsua_vid_win_id wid = PJSUA_INVALID_ID; 2540 unsigned i; 2541 2542 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2543 PJ_EINVAL); 2544 2545 /* Use PJSUA_LOCK() instead of acquire_call(): 2546 * https://trac.pjsip.org/repos/ticket/1371 2547 */ 2548 PJSUA_LOCK(); 2549 2550 if (!pjsua_call_is_active(call_id)) 2551 goto on_return; 2552 2553 call = &pjsua_var.calls[call_id]; 2554 for (i = 0; i < call->med_cnt; ++i) { 2555 if (call->media[i].type == PJMEDIA_TYPE_VIDEO && 2556 (call->media[i].dir & PJMEDIA_DIR_DECODING)) 2557 { 2558 wid = call->media[i].strm.v.rdr_win_id; 2559 break; 2560 } 2561 } 2562 2563 on_return: 2564 PJSUA_UNLOCK(); 2565 2566 return wid; 2567 } 2568 2569 2570 /* 2571 * Get the video conference port identification associated with the call. 2572 */ 2573 PJ_DEF(pjsua_conf_port_id) pjsua_call_get_vid_conf_port( 2574 pjsua_call_id call_id, 2575 pjmedia_dir dir) 2576 { 2577 pjsua_call *call; 2578 pjsua_conf_port_id port_id = PJSUA_INVALID_ID; 2579 unsigned i; 2580 2581 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2582 PJ_EINVAL); 2583 PJ_ASSERT_RETURN(dir==PJMEDIA_DIR_ENCODING || dir==PJMEDIA_DIR_DECODING, 2584 PJ_EINVAL); 2585 2586 /* Use PJSUA_LOCK() instead of acquire_call(): 2587 * https://trac.pjsip.org/repos/ticket/1371 2588 */ 2589 PJSUA_LOCK(); 2590 2591 if (!pjsua_call_is_active(call_id)) 2592 goto on_return; 2593 2594 call = &pjsua_var.calls[call_id]; 2595 for (i = 0; i < call->med_cnt; ++i) { 2596 if (call->media[i].type == PJMEDIA_TYPE_VIDEO && 2597 (call->media[i].dir & dir)) 2598 { 2599 port_id = (dir==PJMEDIA_DIR_ENCODING)? 2600 call->media[i].strm.v.strm_enc_slot : 2601 call->media[i].strm.v.strm_dec_slot; 2602 break; 2603 } 2604 } 2605 2606 on_return: 2607 PJSUA_UNLOCK(); 2608 2609 return port_id; 2610 } 2611 2612 2374 2613 #endif /* PJSUA_HAS_VIDEO */ 2375 2614
Note: See TracChangeset
for help on using the changeset viewer.