Changeset 3664 for pjproject/trunk/pjsip-apps/src/samples/simpleua.c
- Timestamp:
- Jul 19, 2011 3:42:28 AM (13 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk
- Property svn:mergeinfo changed
-
pjproject/trunk/pjsip-apps/src/samples/simpleua.c
r3553 r3664 68 68 69 69 /* Settings */ 70 #define AF pj_AF_INET()/* Change to pj_AF_INET6() for IPv6.70 #define AF pj_AF_INET() /* Change to pj_AF_INET6() for IPv6. 71 71 * PJ_HAS_IPV6 must be enabled and 72 72 * your system must support IPv6. */ 73 #define SIP_PORT 5060 /* Listening SIP port */ 74 #define RTP_PORT 4000 /* RTP port */ 73 #if 0 74 #define SIP_PORT 5080 /* Listening SIP port */ 75 #define RTP_PORT 5000 /* RTP port */ 76 #else 77 #define SIP_PORT 5060 /* Listening SIP port */ 78 #define RTP_PORT 4000 /* RTP port */ 79 #endif 80 81 #define MAX_MEDIA_CNT 2 /* Media count, set to 1 for audio 82 * only or 2 for audio and video */ 75 83 76 84 /* … … 83 91 84 92 static pjmedia_endpt *g_med_endpt; /* Media endpoint. */ 85 static pjmedia_transport_info g_med_tpinfo; /* Socket info for media */ 86 static pjmedia_transport *g_med_transport;/* Media stream transport */ 93 94 static pjmedia_transport_info g_med_tpinfo[MAX_MEDIA_CNT]; 95 /* Socket info for media */ 96 static pjmedia_transport *g_med_transport[MAX_MEDIA_CNT]; 97 /* Media stream transport */ 98 static pjmedia_sock_info g_sock_info[MAX_MEDIA_CNT]; 99 /* Socket info array */ 87 100 88 101 /* Call variables: */ 89 102 static pjsip_inv_session *g_inv; /* Current invite session. */ 90 static pjmedia_session *g_med_session; /* Call's media session. */ 91 static pjmedia_snd_port *g_snd_player; /* Call's sound player */ 92 static pjmedia_snd_port *g_snd_rec; /* Call's sound recorder. */ 93 103 static pjmedia_stream *g_med_stream; /* Call's audio stream. */ 104 static pjmedia_snd_port *g_snd_port; /* Sound device. */ 105 106 #if PJMEDIA_HAS_VIDEO 107 static pjmedia_vid_stream *g_med_vstream; /* Call's video stream. */ 108 static pjmedia_vid_port *g_vid_capturer;/* Call's video capturer. */ 109 static pjmedia_vid_port *g_vid_renderer;/* Call's video renderer. */ 110 #endif /* PJMEDIA_HAS_VIDEO */ 94 111 95 112 /* … … 137 154 138 155 156 /* Notification on incoming messages */ 157 static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata) 158 { 159 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n" 160 "%.*s\n" 161 "--end msg--", 162 rdata->msg_info.len, 163 pjsip_rx_data_get_info(rdata), 164 rdata->tp_info.transport->type_name, 165 rdata->pkt_info.src_name, 166 rdata->pkt_info.src_port, 167 (int)rdata->msg_info.len, 168 rdata->msg_info.msg_buf)); 169 170 /* Always return false, otherwise messages will not get processed! */ 171 return PJ_FALSE; 172 } 173 174 /* Notification on outgoing messages */ 175 static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata) 176 { 177 178 /* Important note: 179 * tp_info field is only valid after outgoing messages has passed 180 * transport layer. So don't try to access tp_info when the module 181 * has lower priority than transport layer. 182 */ 183 184 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n" 185 "%.*s\n" 186 "--end msg--", 187 (tdata->buf.cur - tdata->buf.start), 188 pjsip_tx_data_get_info(tdata), 189 tdata->tp_info.transport->type_name, 190 tdata->tp_info.dst_name, 191 tdata->tp_info.dst_port, 192 (int)(tdata->buf.cur - tdata->buf.start), 193 tdata->buf.start)); 194 195 /* Always return success, otherwise message will not get sent! */ 196 return PJ_SUCCESS; 197 } 198 199 /* The module instance. */ 200 static pjsip_module msg_logger = 201 { 202 NULL, NULL, /* prev, next. */ 203 { "mod-msg-log", 13 }, /* Name. */ 204 -1, /* Id */ 205 PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */ 206 NULL, /* load() */ 207 NULL, /* start() */ 208 NULL, /* stop() */ 209 NULL, /* unload() */ 210 &logging_on_rx_msg, /* on_rx_request() */ 211 &logging_on_rx_msg, /* on_rx_response() */ 212 &logging_on_tx_msg, /* on_tx_request. */ 213 &logging_on_tx_msg, /* on_tx_response() */ 214 NULL, /* on_tsx_state() */ 215 216 }; 217 139 218 140 219 /* … … 146 225 int main(int argc, char *argv[]) 147 226 { 227 pj_pool_t *pool; 148 228 pj_status_t status; 229 unsigned i; 149 230 150 231 /* Must init PJLIB first: */ … … 152 233 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 153 234 235 pj_log_set_level(5); 154 236 155 237 /* Then init PJLIB-UTIL: */ … … 263 345 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 264 346 347 /* 348 * Register message logger module. 349 */ 350 status = pjsip_endpt_register_module( g_endpt, &msg_logger); 351 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 352 265 353 266 354 /* … … 285 373 #endif 286 374 375 376 /* Init video subsystem */ 377 #if PJMEDIA_HAS_VIDEO 378 pool = pjmedia_endpt_create_pool(g_med_endpt, "Video subsystem", 512, 512); 379 status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL); 380 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 381 status = pjmedia_converter_mgr_create(pool, NULL); 382 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 383 status = pjmedia_vid_codec_mgr_create(pool, NULL); 384 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 385 status = pjmedia_vid_dev_subsys_init(&cp.factory); 386 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 387 388 # if PJMEDIA_HAS_FFMPEG_CODEC 389 /* Init ffmpeg video codecs */ 390 status = pjmedia_codec_ffmpeg_init(NULL, &cp.factory); 391 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); 392 # endif /* PJMEDIA_HAS_FFMPEG_CODEC */ 393 394 #endif /* PJMEDIA_HAS_VIDEO */ 287 395 288 396 /* … … 291 399 * opt to re-use the same media transport for subsequent calls. 292 400 */ 293 status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL, 294 RTP_PORT, 0, &g_med_transport); 295 if (status != PJ_SUCCESS) { 296 app_perror(THIS_FILE, "Unable to create media transport", status); 297 return 1; 298 } 299 300 /* 301 * Get socket info (address, port) of the media transport. We will 302 * need this info to create SDP (i.e. the address and port info in 303 * the SDP). 304 */ 305 pjmedia_transport_info_init(&g_med_tpinfo); 306 pjmedia_transport_get_info(g_med_transport, &g_med_tpinfo); 307 401 for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) { 402 status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL, 403 RTP_PORT + i*2, 0, 404 &g_med_transport[i]); 405 if (status != PJ_SUCCESS) { 406 app_perror(THIS_FILE, "Unable to create media transport", status); 407 return 1; 408 } 409 410 /* 411 * Get socket info (address, port) of the media transport. We will 412 * need this info to create SDP (i.e. the address and port info in 413 * the SDP). 414 */ 415 pjmedia_transport_info_init(&g_med_tpinfo[i]); 416 pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]); 417 418 pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info, 419 sizeof(pjmedia_sock_info)); 420 } 308 421 309 422 /* … … 361 474 362 475 /* Get the SDP body to be put in the outgoing INVITE, by asking 363 * media endpoint to create one for us. The SDP will contain all 364 * codecs that have been registered to it (in this case, only 365 * PCMA and PCMU), plus telephony event. 476 * media endpoint to create one for us. 366 477 */ 367 478 status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */ 368 479 dlg->pool, /* pool. */ 369 1, /* # of streams */ 370 &g_med_tpinfo.sock_info, 371 /* RTP sock info */ 480 MAX_MEDIA_CNT, /* # of streams */ 481 g_sock_info, /* RTP sock info */ 372 482 &local_sdp); /* the SDP result */ 373 483 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); … … 440 550 /* On exit, dump current memory usage: */ 441 551 dump_pool_usage(THIS_FILE, &cp); 552 553 /* Destroy audio ports. Destroy the audio port first 554 * before the stream since the audio port has threads 555 * that get/put frames to the stream. 556 */ 557 if (g_snd_port) 558 pjmedia_snd_port_destroy(g_snd_port); 559 560 /* Destroy video ports */ 561 #if PJMEDIA_HAS_VIDEO 562 if (g_vid_capturer) 563 pjmedia_vid_port_destroy(g_vid_capturer); 564 if (g_vid_renderer) 565 pjmedia_vid_port_destroy(g_vid_renderer); 566 #endif 567 568 /* Destroy streams */ 569 if (g_med_stream) 570 pjmedia_stream_destroy(g_med_stream); 571 #if PJMEDIA_HAS_VIDEO 572 if (g_med_vstream) 573 pjmedia_vid_stream_destroy(g_med_vstream); 574 #endif 575 576 /* Destroy media transports */ 577 for (i = 0; i < MAX_MEDIA_CNT; ++i) { 578 if (g_med_transport[i]) 579 pjmedia_transport_close(g_med_transport[i]); 580 } 581 582 /* Deinit ffmpeg codec */ 583 #if PJMEDIA_HAS_FFMPEG_CODEC 584 pjmedia_codec_ffmpeg_deinit(); 585 #endif 586 587 /* Deinit pjmedia endpoint */ 588 if (g_med_endpt) 589 pjmedia_endpt_destroy(g_med_endpt); 590 591 /* Deinit pjsip endpoint */ 592 if (g_endpt) 593 pjsip_endpt_destroy(g_endpt); 594 595 /* Release pool */ 596 pj_pool_release(pool); 442 597 443 598 return 0; … … 575 730 */ 576 731 577 status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 1, 578 &g_med_tpinfo.sock_info, 579 &local_sdp); 732 status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool, 733 MAX_MEDIA_CNT, g_sock_info, &local_sdp); 580 734 PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE); 581 735 … … 640 794 pj_status_t status) 641 795 { 642 pjmedia_s ession_info sess_info;796 pjmedia_stream_info stream_info; 643 797 const pjmedia_sdp_session *local_sdp; 644 798 const pjmedia_sdp_session *remote_sdp; … … 663 817 664 818 665 /* Create session info based on the two SDPs. 666 * We only support one stream per session for now. 667 */ 668 status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt, 669 1, &sess_info, 670 local_sdp, remote_sdp); 819 /* Create stream info based on the media audio SDP. */ 820 status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool, 821 g_med_endpt, 822 local_sdp, remote_sdp, 0); 671 823 if (status != PJ_SUCCESS) { 672 app_perror( THIS_FILE, "Unable to create media session",status);824 app_perror(THIS_FILE,"Unable to create audio stream info",status); 673 825 return; 674 826 } 675 827 676 /* If required, we can also change some settings in the s essioninfo,828 /* If required, we can also change some settings in the stream info, 677 829 * (such as jitter buffer settings, codec settings, etc) before we 678 * create the s ession.679 */ 680 681 /* Create new media session, passing the two SDPs, and also the830 * create the stream. 831 */ 832 833 /* Create new audio media stream, passing the stream info, and also the 682 834 * media socket that we created earlier. 683 * The media session is active immediately. 684 */ 685 status = pjmedia_session_create( g_med_endpt, &sess_info, 686 &g_med_transport, NULL, &g_med_session ); 835 */ 836 status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info, 837 g_med_transport[0], NULL, &g_med_stream); 687 838 if (status != PJ_SUCCESS) { 688 app_perror( THIS_FILE, "Unable to create media session", status);839 app_perror( THIS_FILE, "Unable to create audio stream", status); 689 840 return; 690 841 } 691 842 692 693 /* Get the media port interface of the first stream in the session. 843 /* Start the audio stream */ 844 status = pjmedia_stream_start(g_med_stream); 845 if (status != PJ_SUCCESS) { 846 app_perror( THIS_FILE, "Unable to start audio stream", status); 847 return; 848 } 849 850 /* Get the media port interface of the audio stream. 694 851 * Media port interface is basicly a struct containing get_frame() and 695 852 * put_frame() function. With this media port interface, we can attach … … 697 854 * player/recorder device. 698 855 */ 699 pjmedia_session_get_port(g_med_session, 0, &media_port); 700 701 702 703 /* Create a sound Player device and connect the media port to the 704 * sound device. 705 */ 706 status = pjmedia_snd_port_create_player( 707 inv->pool, /* pool */ 708 -1, /* sound dev id */ 709 media_port->info.clock_rate, /* clock rate */ 710 media_port->info.channel_count, /* channel count */ 711 media_port->info.samples_per_frame, /* samples per frame*/ 712 media_port->info.bits_per_sample, /* bits per sample */ 713 0, /* options */ 714 &g_snd_player); 856 pjmedia_stream_get_port(g_med_stream, &media_port); 857 858 /* Create sound port */ 859 pjmedia_snd_port_create(inv->pool, 860 PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, 861 PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV, 862 PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */ 863 PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */ 864 PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/ 865 PJMEDIA_PIA_BITS(&media_port->info),/* bits per sample */ 866 0, 867 &g_snd_port); 868 715 869 if (status != PJ_SUCCESS) { 716 app_perror( THIS_FILE, "Unable to create sound p layer", status);870 app_perror( THIS_FILE, "Unable to create sound port", status); 717 871 PJ_LOG(3,(THIS_FILE, "%d %d %d %d", 718 media_port->info.clock_rate,/* clock rate */719 media_port->info.channel_count,/* channel count */720 media_port->info.samples_per_frame, /* samples per frame*/721 media_port->info.bits_per_sample/* bits per sample */872 PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */ 873 PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */ 874 PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/ 875 PJMEDIA_PIA_BITS(&media_port->info) /* bits per sample */ 722 876 )); 723 877 return; 724 878 } 725 879 726 status = pjmedia_snd_port_connect(g_snd_player, media_port); 727 728 729 /* Create a sound recorder device and connect the media port to the 730 * sound device. 731 */ 732 status = pjmedia_snd_port_create_rec( 733 inv->pool, /* pool */ 734 -1, /* sound dev id */ 735 media_port->info.clock_rate, /* clock rate */ 736 media_port->info.channel_count, /* channel count */ 737 media_port->info.samples_per_frame, /* samples per frame*/ 738 media_port->info.bits_per_sample, /* bits per sample */ 739 0, /* options */ 740 &g_snd_rec); 741 if (status != PJ_SUCCESS) { 742 app_perror( THIS_FILE, "Unable to create sound recorder", status); 743 return; 744 } 745 746 status = pjmedia_snd_port_connect(g_snd_rec, media_port); 880 status = pjmedia_snd_port_connect(g_snd_port, media_port); 881 882 883 /* Get the media port interface of the second stream in the session, 884 * which is video stream. With this media port interface, we can attach 885 * the port directly to a renderer/capture video device. 886 */ 887 #if PJMEDIA_HAS_VIDEO 888 if (local_sdp->media_count > 1) { 889 pjmedia_vid_stream_info vstream_info; 890 pjmedia_vid_port_param vport_param; 891 892 pjmedia_vid_port_param_default(&vport_param); 893 894 /* Create stream info based on the media video SDP. */ 895 status = pjmedia_vid_stream_info_from_sdp(&vstream_info, 896 inv->dlg->pool, g_med_endpt, 897 local_sdp, remote_sdp, 1); 898 if (status != PJ_SUCCESS) { 899 app_perror(THIS_FILE,"Unable to create video stream info",status); 900 return; 901 } 902 903 /* If required, we can also change some settings in the stream info, 904 * (such as jitter buffer settings, codec settings, etc) before we 905 * create the video stream. 906 */ 907 908 /* Create new video media stream, passing the stream info, and also the 909 * media socket that we created earlier. 910 */ 911 status = pjmedia_vid_stream_create(g_med_endpt, NULL, &vstream_info, 912 g_med_transport[1], NULL, 913 &g_med_vstream); 914 if (status != PJ_SUCCESS) { 915 app_perror( THIS_FILE, "Unable to create video stream", status); 916 return; 917 } 918 919 /* Start the video stream */ 920 status = pjmedia_vid_stream_start(g_med_vstream); 921 if (status != PJ_SUCCESS) { 922 app_perror( THIS_FILE, "Unable to start video stream", status); 923 return; 924 } 925 926 if (vstream_info.dir & PJMEDIA_DIR_DECODING) { 927 status = pjmedia_vid_dev_default_param( 928 inv->pool, PJMEDIA_VID_DEFAULT_RENDER_DEV, 929 &vport_param.vidparam); 930 if (status != PJ_SUCCESS) { 931 app_perror(THIS_FILE, "Unable to get default param of video " 932 "renderer device", status); 933 return; 934 } 935 936 /* Get video stream port for decoding direction */ 937 pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_DECODING, 938 &media_port); 939 940 /* Set format */ 941 pjmedia_format_copy(&vport_param.vidparam.fmt, 942 &media_port->info.fmt); 943 vport_param.vidparam.dir = PJMEDIA_DIR_RENDER; 944 vport_param.active = PJ_TRUE; 945 946 /* Create renderer */ 947 status = pjmedia_vid_port_create(inv->pool, &vport_param, 948 &g_vid_renderer); 949 if (status != PJ_SUCCESS) { 950 app_perror(THIS_FILE, "Unable to create video renderer device", 951 status); 952 return; 953 } 954 955 /* Connect renderer to media_port */ 956 status = pjmedia_vid_port_connect(g_vid_renderer, media_port, 957 PJ_FALSE); 958 if (status != PJ_SUCCESS) { 959 app_perror(THIS_FILE, "Unable to connect renderer to stream", 960 status); 961 return; 962 } 963 } 964 965 /* Create capturer */ 966 if (vstream_info.dir & PJMEDIA_DIR_ENCODING) { 967 status = pjmedia_vid_dev_default_param( 968 inv->pool, PJMEDIA_VID_DEFAULT_CAPTURE_DEV, 969 &vport_param.vidparam); 970 if (status != PJ_SUCCESS) { 971 app_perror(THIS_FILE, "Unable to get default param of video " 972 "capture device", status); 973 return; 974 } 975 976 /* Get video stream port for decoding direction */ 977 pjmedia_vid_stream_get_port(g_med_vstream, PJMEDIA_DIR_ENCODING, 978 &media_port); 979 980 /* Get capturer format from stream info */ 981 pjmedia_format_copy(&vport_param.vidparam.fmt, 982 &media_port->info.fmt); 983 vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; 984 vport_param.active = PJ_TRUE; 985 986 /* Create capturer */ 987 status = pjmedia_vid_port_create(inv->pool, &vport_param, 988 &g_vid_capturer); 989 if (status != PJ_SUCCESS) { 990 app_perror(THIS_FILE, "Unable to create video capture device", 991 status); 992 return; 993 } 994 995 /* Connect capturer to media_port */ 996 status = pjmedia_vid_port_connect(g_vid_capturer, media_port, 997 PJ_FALSE); 998 if (status != PJ_SUCCESS) { 999 app_perror(THIS_FILE, "Unable to connect capturer to stream", 1000 status); 1001 return; 1002 } 1003 } 1004 1005 /* Start streaming */ 1006 if (g_vid_renderer) { 1007 status = pjmedia_vid_port_start(g_vid_renderer); 1008 if (status != PJ_SUCCESS) { 1009 app_perror(THIS_FILE, "Unable to start video renderer", 1010 status); 1011 return; 1012 } 1013 } 1014 if (g_vid_capturer) { 1015 status = pjmedia_vid_port_start(g_vid_capturer); 1016 if (status != PJ_SUCCESS) { 1017 app_perror(THIS_FILE, "Unable to start video capturer", 1018 status); 1019 return; 1020 } 1021 } 1022 } 1023 #endif /* PJMEDIA_HAS_VIDEO */ 747 1024 748 1025 /* Done with media. */
Note: See TracChangeset
for help on using the changeset viewer.