- Timestamp:
- Mar 17, 2011 4:34:43 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/2.0-dev/pjsip/src/pjsua-lib/pjsua_media.c
r3392 r3457 275 275 #endif /* PJMEDIA_HAS_L16_CODEC */ 276 276 277 #if PJMEDIA_HAS_VIDEO 278 status = pjmedia_video_format_mgr_create(pjsua_var.pool, 64, 0, NULL); 279 if (status != PJ_SUCCESS) { 280 pjsua_perror(THIS_FILE, "Error creating PJMEDIA video format manager", 281 status); 282 return status; 283 } 284 285 status = pjmedia_converter_mgr_create(pjsua_var.pool, NULL); 286 if (status != PJ_SUCCESS) { 287 pjsua_perror(THIS_FILE, "Error creating PJMEDIA converter manager", 288 status); 289 return status; 290 } 291 292 status = pjmedia_vid_codec_mgr_create(pjsua_var.pool, NULL); 293 if (status != PJ_SUCCESS) { 294 pjsua_perror(THIS_FILE, "Error creating PJMEDIA video codec manager", 295 status); 296 return status; 297 } 298 299 status = pjmedia_vid_subsys_init(&pjsua_var.cp.factory); 300 if (status != PJ_SUCCESS) { 301 pjsua_perror(THIS_FILE, "Error creating PJMEDIA video subsystem", 302 status); 303 return status; 304 } 305 #endif 306 307 #if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_FFMPEG_CODEC 308 /* Init ffmpeg video codecs */ 309 status = pjmedia_codec_ffmpeg_init(NULL, &pjsua_var.cp.factory); 310 if (status != PJ_SUCCESS) { 311 pjsua_perror(THIS_FILE, "Error initializing ffmpeg library", 312 status); 313 return status; 314 } 315 #endif 277 316 278 317 /* Save additional conference bridge parameters for future … … 339 378 340 379 341 /*342 * Create RTP and RTCP socket pair, and possibly resolve their public343 * address via STUN.344 */345 static pj_status_t create_rtp_rtcp_sock(const pjsua_transport_config *cfg,346 pjmedia_sock_info *skinfo)347 {348 enum {349 RTP_RETRY = 100350 };351 int i;352 pj_sockaddr_in bound_addr;353 pj_sockaddr_in mapped_addr[2];354 pj_status_t status = PJ_SUCCESS;355 char addr_buf[PJ_INET6_ADDRSTRLEN+2];356 pj_sock_t sock[2];357 358 /* Make sure STUN server resolution has completed */359 status = resolve_stun_server(PJ_TRUE);360 if (status != PJ_SUCCESS) {361 pjsua_perror(THIS_FILE, "Error resolving STUN server", status);362 return status;363 }364 365 if (next_rtp_port == 0)366 next_rtp_port = (pj_uint16_t)cfg->port;367 368 for (i=0; i<2; ++i)369 sock[i] = PJ_INVALID_SOCKET;370 371 bound_addr.sin_addr.s_addr = PJ_INADDR_ANY;372 if (cfg->bound_addr.slen) {373 status = pj_sockaddr_in_set_str_addr(&bound_addr, &cfg->bound_addr);374 if (status != PJ_SUCCESS) {375 pjsua_perror(THIS_FILE, "Unable to resolve transport bind address",376 status);377 return status;378 }379 }380 381 /* Loop retry to bind RTP and RTCP sockets. */382 for (i=0; i<RTP_RETRY; ++i, next_rtp_port += 2) {383 384 /* Create RTP socket. */385 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[0]);386 if (status != PJ_SUCCESS) {387 pjsua_perror(THIS_FILE, "socket() error", status);388 return status;389 }390 391 /* Apply QoS to RTP socket, if specified */392 status = pj_sock_apply_qos2(sock[0], cfg->qos_type,393 &cfg->qos_params,394 2, THIS_FILE, "RTP socket");395 396 /* Bind RTP socket */397 status=pj_sock_bind_in(sock[0], pj_ntohl(bound_addr.sin_addr.s_addr),398 next_rtp_port);399 if (status != PJ_SUCCESS) {400 pj_sock_close(sock[0]);401 sock[0] = PJ_INVALID_SOCKET;402 continue;403 }404 405 /* Create RTCP socket. */406 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[1]);407 if (status != PJ_SUCCESS) {408 pjsua_perror(THIS_FILE, "socket() error", status);409 pj_sock_close(sock[0]);410 return status;411 }412 413 /* Apply QoS to RTCP socket, if specified */414 status = pj_sock_apply_qos2(sock[1], cfg->qos_type,415 &cfg->qos_params,416 2, THIS_FILE, "RTCP socket");417 418 /* Bind RTCP socket */419 status=pj_sock_bind_in(sock[1], pj_ntohl(bound_addr.sin_addr.s_addr),420 (pj_uint16_t)(next_rtp_port+1));421 if (status != PJ_SUCCESS) {422 pj_sock_close(sock[0]);423 sock[0] = PJ_INVALID_SOCKET;424 425 pj_sock_close(sock[1]);426 sock[1] = PJ_INVALID_SOCKET;427 continue;428 }429 430 /*431 * If we're configured to use STUN, then find out the mapped address,432 * and make sure that the mapped RTCP port is adjacent with the RTP.433 */434 if (pjsua_var.stun_srv.addr.sa_family != 0) {435 char ip_addr[32];436 pj_str_t stun_srv;437 438 pj_ansi_strcpy(ip_addr,439 pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));440 stun_srv = pj_str(ip_addr);441 442 status=pjstun_get_mapped_addr(&pjsua_var.cp.factory, 2, sock,443 &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),444 &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),445 mapped_addr);446 if (status != PJ_SUCCESS) {447 pjsua_perror(THIS_FILE, "STUN resolve error", status);448 goto on_error;449 }450 451 #if PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT452 if (pj_ntohs(mapped_addr[1].sin_port) ==453 pj_ntohs(mapped_addr[0].sin_port)+1)454 {455 /* Success! */456 break;457 }458 459 pj_sock_close(sock[0]);460 sock[0] = PJ_INVALID_SOCKET;461 462 pj_sock_close(sock[1]);463 sock[1] = PJ_INVALID_SOCKET;464 #else465 if (pj_ntohs(mapped_addr[1].sin_port) !=466 pj_ntohs(mapped_addr[0].sin_port)+1)467 {468 PJ_LOG(4,(THIS_FILE,469 "Note: STUN mapped RTCP port %d is not adjacent"470 " to RTP port %d",471 pj_ntohs(mapped_addr[1].sin_port),472 pj_ntohs(mapped_addr[0].sin_port)));473 }474 /* Success! */475 break;476 #endif477 478 } else if (cfg->public_addr.slen) {479 480 status = pj_sockaddr_in_init(&mapped_addr[0], &cfg->public_addr,481 (pj_uint16_t)next_rtp_port);482 if (status != PJ_SUCCESS)483 goto on_error;484 485 status = pj_sockaddr_in_init(&mapped_addr[1], &cfg->public_addr,486 (pj_uint16_t)(next_rtp_port+1));487 if (status != PJ_SUCCESS)488 goto on_error;489 490 break;491 492 } else {493 494 if (bound_addr.sin_addr.s_addr == 0) {495 pj_sockaddr addr;496 497 /* Get local IP address. */498 status = pj_gethostip(pj_AF_INET(), &addr);499 if (status != PJ_SUCCESS)500 goto on_error;501 502 bound_addr.sin_addr.s_addr = addr.ipv4.sin_addr.s_addr;503 }504 505 for (i=0; i<2; ++i) {506 pj_sockaddr_in_init(&mapped_addr[i], NULL, 0);507 mapped_addr[i].sin_addr.s_addr = bound_addr.sin_addr.s_addr;508 }509 510 mapped_addr[0].sin_port=pj_htons((pj_uint16_t)next_rtp_port);511 mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(next_rtp_port+1));512 break;513 }514 }515 516 if (sock[0] == PJ_INVALID_SOCKET) {517 PJ_LOG(1,(THIS_FILE,518 "Unable to find appropriate RTP/RTCP ports combination"));519 goto on_error;520 }521 522 523 skinfo->rtp_sock = sock[0];524 pj_memcpy(&skinfo->rtp_addr_name,525 &mapped_addr[0], sizeof(pj_sockaddr_in));526 527 skinfo->rtcp_sock = sock[1];528 pj_memcpy(&skinfo->rtcp_addr_name,529 &mapped_addr[1], sizeof(pj_sockaddr_in));530 531 PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s",532 pj_sockaddr_print(&skinfo->rtp_addr_name, addr_buf,533 sizeof(addr_buf), 3)));534 PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s",535 pj_sockaddr_print(&skinfo->rtcp_addr_name, addr_buf,536 sizeof(addr_buf), 3)));537 538 next_rtp_port += 2;539 return PJ_SUCCESS;540 541 on_error:542 for (i=0; i<2; ++i) {543 if (sock[i] != PJ_INVALID_SOCKET)544 pj_sock_close(sock[i]);545 }546 return status;547 }548 549 380 /* Check if sound device is idle. */ 550 381 static void check_snd_dev_idle() … … 579 410 * there is no active call. 580 411 */ 581 if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) && 412 if ((pjsua_var.snd_port!=NULL || pjsua_var.null_snd!=NULL) && 582 413 pjsua_var.snd_idle_timer.id == PJ_FALSE && 583 414 pjmedia_conf_get_connect_count(pjsua_var.mconf) == 0 && … … 591 422 592 423 pjsua_var.snd_idle_timer.id = PJ_TRUE; 593 pjsip_endpt_schedule_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer, 424 pjsip_endpt_schedule_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer, 594 425 &delay); 595 426 } … … 605 436 PJSUA_LOCK(); 606 437 if (entry->id) { 607 PJ_LOG(4,(THIS_FILE,"Closing sound device after idle for %d seconds", 438 PJ_LOG(4,(THIS_FILE,"Closing sound device after idle for %d seconds", 608 439 pjsua_var.media_cfg.snd_auto_close_time)); 609 440 … … 623 454 pj_status_t status; 624 455 456 #if DISABLED_FOR_TICKET_1185 625 457 /* Create media for calls, if none is specified */ 626 if (pjsua_var.calls[0].med _tp == NULL) {458 if (pjsua_var.calls[0].media[0].tp == NULL) { 627 459 pjsua_transport_config transport_cfg; 628 460 … … 635 467 return status; 636 468 } 637 638 pj_timer_entry_init(&pjsua_var.snd_idle_timer, PJ_FALSE, NULL, 469 #endif 470 471 pj_timer_entry_init(&pjsua_var.snd_idle_timer, PJ_FALSE, NULL, 639 472 &close_snd_timer_cb); 640 473 641 474 /* Perform NAT detection */ 642 pjsua_detect_nat_type(); 475 status = pjsua_detect_nat_type(); 476 if (status != PJ_SUCCESS) { 477 PJ_PERROR(1,(THIS_FILE, status, "NAT type detection failed")); 478 } 643 479 644 480 return PJ_SUCCESS; … … 685 521 /* Close media transports */ 686 522 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 687 if (pjsua_var.calls[i].med_tp_st != PJSUA_MED_TP_IDLE) { 688 pjsua_media_channel_deinit(i); 689 } 690 if (pjsua_var.calls[i].med_tp && pjsua_var.calls[i].med_tp_auto_del) { 691 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 692 } 693 pjsua_var.calls[i].med_tp = NULL; 523 unsigned strm_idx; 524 pjsua_call *call = &pjsua_var.calls[i]; 525 for (strm_idx=0; strm_idx<call->med_cnt; ++strm_idx) { 526 pjsua_call_media *call_med = &call->media[strm_idx]; 527 if (call_med->tp_st != PJSUA_MED_TP_IDLE) { 528 pjsua_media_channel_deinit(i); 529 } 530 if (call_med->tp && call_med->tp_auto_del) { 531 pjmedia_transport_close(call_med->tp); 532 } 533 call_med->tp = NULL; 534 } 694 535 } 695 536 696 537 /* Destroy media endpoint. */ 697 538 if (pjsua_var.med_endpt) { 539 540 /* Videodev */ 541 # if PJMEDIA_HAS_VIDEO 542 pjmedia_vid_subsys_shutdown(); 543 # endif 544 545 /* ffmpeg */ 546 # if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_FFMPEG_CODEC 547 pjmedia_codec_ffmpeg_deinit(); 548 # endif 698 549 699 550 /* Shutdown all codecs: */ … … 745 596 } 746 597 747 598 /* 599 * Create RTP and RTCP socket pair, and possibly resolve their public 600 * address via STUN. 601 */ 602 static pj_status_t create_rtp_rtcp_sock(const pjsua_transport_config *cfg, 603 pjmedia_sock_info *skinfo) 604 { 605 enum { 606 RTP_RETRY = 100 607 }; 608 int i; 609 pj_sockaddr_in bound_addr; 610 pj_sockaddr_in mapped_addr[2]; 611 pj_status_t status = PJ_SUCCESS; 612 char addr_buf[PJ_INET6_ADDRSTRLEN+2]; 613 pj_sock_t sock[2]; 614 615 /* Make sure STUN server resolution has completed */ 616 status = resolve_stun_server(PJ_TRUE); 617 if (status != PJ_SUCCESS) { 618 pjsua_perror(THIS_FILE, "Error resolving STUN server", status); 619 return status; 620 } 621 622 if (next_rtp_port == 0) 623 next_rtp_port = (pj_uint16_t)cfg->port; 624 625 if (next_rtp_port == 0) 626 next_rtp_port = (pj_uint16_t)40000; 627 628 for (i=0; i<2; ++i) 629 sock[i] = PJ_INVALID_SOCKET; 630 631 bound_addr.sin_addr.s_addr = PJ_INADDR_ANY; 632 if (cfg->bound_addr.slen) { 633 status = pj_sockaddr_in_set_str_addr(&bound_addr, &cfg->bound_addr); 634 if (status != PJ_SUCCESS) { 635 pjsua_perror(THIS_FILE, "Unable to resolve transport bind address", 636 status); 637 return status; 638 } 639 } 640 641 /* Loop retry to bind RTP and RTCP sockets. */ 642 for (i=0; i<RTP_RETRY; ++i, next_rtp_port += 2) { 643 644 /* Create RTP socket. */ 645 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[0]); 646 if (status != PJ_SUCCESS) { 647 pjsua_perror(THIS_FILE, "socket() error", status); 648 return status; 649 } 650 651 /* Apply QoS to RTP socket, if specified */ 652 status = pj_sock_apply_qos2(sock[0], cfg->qos_type, 653 &cfg->qos_params, 654 2, THIS_FILE, "RTP socket"); 655 656 /* Bind RTP socket */ 657 status=pj_sock_bind_in(sock[0], pj_ntohl(bound_addr.sin_addr.s_addr), 658 next_rtp_port); 659 if (status != PJ_SUCCESS) { 660 pj_sock_close(sock[0]); 661 sock[0] = PJ_INVALID_SOCKET; 662 continue; 663 } 664 665 /* Create RTCP socket. */ 666 status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[1]); 667 if (status != PJ_SUCCESS) { 668 pjsua_perror(THIS_FILE, "socket() error", status); 669 pj_sock_close(sock[0]); 670 return status; 671 } 672 673 /* Apply QoS to RTCP socket, if specified */ 674 status = pj_sock_apply_qos2(sock[1], cfg->qos_type, 675 &cfg->qos_params, 676 2, THIS_FILE, "RTCP socket"); 677 678 /* Bind RTCP socket */ 679 status=pj_sock_bind_in(sock[1], pj_ntohl(bound_addr.sin_addr.s_addr), 680 (pj_uint16_t)(next_rtp_port+1)); 681 if (status != PJ_SUCCESS) { 682 pj_sock_close(sock[0]); 683 sock[0] = PJ_INVALID_SOCKET; 684 685 pj_sock_close(sock[1]); 686 sock[1] = PJ_INVALID_SOCKET; 687 continue; 688 } 689 690 /* 691 * If we're configured to use STUN, then find out the mapped address, 692 * and make sure that the mapped RTCP port is adjacent with the RTP. 693 */ 694 if (pjsua_var.stun_srv.addr.sa_family != 0) { 695 char ip_addr[32]; 696 pj_str_t stun_srv; 697 698 pj_ansi_strcpy(ip_addr, 699 pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr)); 700 stun_srv = pj_str(ip_addr); 701 702 status=pjstun_get_mapped_addr(&pjsua_var.cp.factory, 2, sock, 703 &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), 704 &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), 705 mapped_addr); 706 if (status != PJ_SUCCESS) { 707 pjsua_perror(THIS_FILE, "STUN resolve error", status); 708 goto on_error; 709 } 710 711 #if PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT 712 if (pj_ntohs(mapped_addr[1].sin_port) == 713 pj_ntohs(mapped_addr[0].sin_port)+1) 714 { 715 /* Success! */ 716 break; 717 } 718 719 pj_sock_close(sock[0]); 720 sock[0] = PJ_INVALID_SOCKET; 721 722 pj_sock_close(sock[1]); 723 sock[1] = PJ_INVALID_SOCKET; 724 #else 725 if (pj_ntohs(mapped_addr[1].sin_port) != 726 pj_ntohs(mapped_addr[0].sin_port)+1) 727 { 728 PJ_LOG(4,(THIS_FILE, 729 "Note: STUN mapped RTCP port %d is not adjacent" 730 " to RTP port %d", 731 pj_ntohs(mapped_addr[1].sin_port), 732 pj_ntohs(mapped_addr[0].sin_port))); 733 } 734 /* Success! */ 735 break; 736 #endif 737 738 } else if (cfg->public_addr.slen) { 739 740 status = pj_sockaddr_in_init(&mapped_addr[0], &cfg->public_addr, 741 (pj_uint16_t)next_rtp_port); 742 if (status != PJ_SUCCESS) 743 goto on_error; 744 745 status = pj_sockaddr_in_init(&mapped_addr[1], &cfg->public_addr, 746 (pj_uint16_t)(next_rtp_port+1)); 747 if (status != PJ_SUCCESS) 748 goto on_error; 749 750 break; 751 752 } else { 753 754 if (bound_addr.sin_addr.s_addr == 0) { 755 pj_sockaddr addr; 756 757 /* Get local IP address. */ 758 status = pj_gethostip(pj_AF_INET(), &addr); 759 if (status != PJ_SUCCESS) 760 goto on_error; 761 762 bound_addr.sin_addr.s_addr = addr.ipv4.sin_addr.s_addr; 763 } 764 765 for (i=0; i<2; ++i) { 766 pj_sockaddr_in_init(&mapped_addr[i], NULL, 0); 767 mapped_addr[i].sin_addr.s_addr = bound_addr.sin_addr.s_addr; 768 } 769 770 mapped_addr[0].sin_port=pj_htons((pj_uint16_t)next_rtp_port); 771 mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(next_rtp_port+1)); 772 break; 773 } 774 } 775 776 if (sock[0] == PJ_INVALID_SOCKET) { 777 PJ_LOG(1,(THIS_FILE, 778 "Unable to find appropriate RTP/RTCP ports combination")); 779 goto on_error; 780 } 781 782 783 skinfo->rtp_sock = sock[0]; 784 pj_memcpy(&skinfo->rtp_addr_name, 785 &mapped_addr[0], sizeof(pj_sockaddr_in)); 786 787 skinfo->rtcp_sock = sock[1]; 788 pj_memcpy(&skinfo->rtcp_addr_name, 789 &mapped_addr[1], sizeof(pj_sockaddr_in)); 790 791 PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s", 792 pj_sockaddr_print(&skinfo->rtp_addr_name, addr_buf, 793 sizeof(addr_buf), 3))); 794 PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s", 795 pj_sockaddr_print(&skinfo->rtcp_addr_name, addr_buf, 796 sizeof(addr_buf), 3))); 797 798 next_rtp_port += 2; 799 return PJ_SUCCESS; 800 801 on_error: 802 for (i=0; i<2; ++i) { 803 if (sock[i] != PJ_INVALID_SOCKET) 804 pj_sock_close(sock[i]); 805 } 806 return status; 807 } 808 809 /* Create normal UDP media transports */ 810 static pj_status_t create_udp_media_transport(const pjsua_transport_config *cfg, 811 pjsua_call_media *call_med) 812 { 813 pjmedia_sock_info skinfo; 814 pj_status_t status; 815 816 status = create_rtp_rtcp_sock(cfg, &skinfo); 817 if (status != PJ_SUCCESS) { 818 pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket", 819 status); 820 goto on_error; 821 } 822 823 status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL, 824 &skinfo, 0, &call_med->tp); 825 if (status != PJ_SUCCESS) { 826 pjsua_perror(THIS_FILE, "Unable to create media transport", 827 status); 828 goto on_error; 829 } 830 831 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING, 832 pjsua_var.media_cfg.tx_drop_pct); 833 834 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING, 835 pjsua_var.media_cfg.rx_drop_pct); 836 837 return PJ_SUCCESS; 838 839 on_error: 840 if (call_med->tp) 841 pjmedia_transport_close(call_med->tp); 842 843 return status; 844 } 845 846 #if DISABLED_FOR_TICKET_1185 748 847 /* Create normal UDP media transports */ 749 848 static pj_status_t create_udp_media_transports(pjsua_transport_config *cfg) 750 849 { 751 850 unsigned i; 752 pjmedia_sock_info skinfo;753 851 pj_status_t status; 754 852 755 /* Create each media transport */ 756 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 757 758 status = create_rtp_rtcp_sock(cfg, &skinfo); 759 if (status != PJ_SUCCESS) { 760 pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket", 761 status); 762 goto on_error; 763 } 764 765 status = pjmedia_transport_udp_attach(pjsua_var.med_endpt, NULL, 766 &skinfo, 0, 767 &pjsua_var.calls[i].med_tp); 768 if (status != PJ_SUCCESS) { 769 pjsua_perror(THIS_FILE, "Unable to create media transport", 770 status); 771 goto on_error; 772 } 773 774 pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp, 775 PJMEDIA_DIR_ENCODING, 776 pjsua_var.media_cfg.tx_drop_pct); 777 778 pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp, 779 PJMEDIA_DIR_DECODING, 780 pjsua_var.media_cfg.rx_drop_pct); 781 853 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) { 854 pjsua_call *call = &pjsua_var.calls[i]; 855 unsigned strm_idx; 856 857 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 858 pjsua_call_media *call_med = &call->media[strm_idx]; 859 860 status = create_udp_media_transport(cfg, &call_med->tp); 861 if (status != PJ_SUCCESS) 862 goto on_error; 863 } 782 864 } 783 865 … … 785 867 786 868 on_error: 787 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 788 if (pjsua_var.calls[i].med_tp != NULL) { 789 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 790 pjsua_var.calls[i].med_tp = NULL; 791 } 792 } 793 869 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) { 870 pjsua_call *call = &pjsua_var.calls[i]; 871 unsigned strm_idx; 872 873 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 874 pjsua_call_media *call_med = &call->media[strm_idx]; 875 876 if (call_med->tp) { 877 pjmedia_transport_close(call_med->tp); 878 call_med->tp = NULL; 879 } 880 } 881 } 794 882 return status; 795 883 } 796 884 #endif 797 885 798 886 /* This callback is called when ICE negotiation completes */ … … 801 889 pj_status_t result) 802 890 { 803 unsigned id; 804 pj_bool_t found = PJ_FALSE; 805 806 /* Find call which has this media transport */ 807 808 PJSUA_LOCK(); 809 810 for (id=0; id<pjsua_var.ua_cfg.max_calls; ++id) { 811 if (pjsua_var.calls[id].med_tp == tp || 812 pjsua_var.calls[id].med_orig == tp) 813 { 814 found = PJ_TRUE; 815 break; 816 } 817 } 818 819 PJSUA_UNLOCK(); 820 821 if (!found) 891 pjsua_call_media *call_med = (pjsua_call_media*)tp->user_data; 892 893 if (!call_med) 822 894 return; 823 895 824 896 switch (op) { 825 897 case PJ_ICE_STRANS_OP_INIT: 826 pjsua_var.calls[id].med_tp_ready = result;898 call_med->tp_ready = result; 827 899 break; 828 900 case PJ_ICE_STRANS_OP_NEGOTIATION: 829 901 if (result != PJ_SUCCESS) { 830 pjsua_var.calls[id].media_st= PJSUA_CALL_MEDIA_ERROR;831 pjsua_var.calls[id].media_dir = PJMEDIA_DIR_NONE;832 833 if ( pjsua_var.ua_cfg.cb.on_call_media_state) {834 pjsua_var.ua_cfg.cb.on_call_media_state( id);902 call_med->state = PJSUA_CALL_MEDIA_ERROR; 903 call_med->dir = PJMEDIA_DIR_NONE; 904 905 if (call_med->call && pjsua_var.ua_cfg.cb.on_call_media_state) { 906 pjsua_var.ua_cfg.cb.on_call_media_state(call_med->call->index); 835 907 } 836 } else {908 } else if (call_med->call) { 837 909 /* Send UPDATE if default transport address is different than 838 910 * what was advertised (ticket #881) … … 854 926 if (ii && ii->role==PJ_ICE_SESS_ROLE_CONTROLLING && 855 927 pj_sockaddr_cmp(&tpinfo.sock_info.rtp_addr_name, 856 & pjsua_var.calls[id].med_rtp_addr))928 &call_med->rtp_addr)) 857 929 { 858 930 pj_bool_t use_update; … … 861 933 pjsip_dialog *dlg; 862 934 863 dlg = pjsua_var.calls[id].inv->dlg;935 dlg = call_med->call->inv->dlg; 864 936 support_update = pjsip_dlg_remote_has_cap(dlg, PJSIP_H_ALLOW, 865 937 NULL, &STR_UPDATE); … … 868 940 PJ_LOG(4,(THIS_FILE, 869 941 "ICE default transport address has changed for " 870 "call %d, sending %s", id,942 "call %d, sending %s", call_med->call->index, 871 943 (use_update ? "UPDATE" : "re-INVITE"))); 872 944 873 945 if (use_update) 874 pjsua_call_update( id, 0, NULL);946 pjsua_call_update(call_med->call->index, 0, NULL); 875 947 else 876 pjsua_call_reinvite( id, 0, NULL);948 pjsua_call_reinvite(call_med->call->index, 0, NULL); 877 949 } 878 950 } … … 881 953 if (result != PJ_SUCCESS) { 882 954 PJ_PERROR(4,(THIS_FILE, result, 883 "ICE keep alive failure for transport %d", id)); 955 "ICE keep alive failure for transport %d:%d", 956 call_med->call->index, call_med->idx)); 884 957 } 885 958 if (pjsua_var.ua_cfg.cb.on_ice_transport_error) { 959 pjsua_call_id id = call_med->call->index; 886 960 (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result, 887 961 NULL); … … 919 993 920 994 /* Create ICE media transports (when ice is enabled) */ 921 static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) 995 static pj_status_t create_ice_media_transport( 996 const pjsua_transport_config *cfg, 997 pjsua_call_media *call_med) 922 998 { 923 999 char stunip[PJ_INET6_ADDRSTRLEN]; 924 1000 pj_ice_strans_cfg ice_cfg; 925 unsigned i; 1001 pjmedia_ice_cb ice_cb; 1002 char name[32]; 1003 unsigned comp_cnt; 926 1004 pj_status_t status; 927 1005 … … 980 1058 } 981 1059 982 /* Create each media transport */ 983 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 984 pjmedia_ice_cb ice_cb; 985 char name[32]; 986 unsigned comp_cnt; 987 988 pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb)); 989 ice_cb.on_ice_complete = &on_ice_complete; 990 pj_ansi_snprintf(name, sizeof(name), "icetp%02d", i); 991 pjsua_var.calls[i].med_tp_ready = PJ_EPENDING; 992 993 comp_cnt = 1; 994 if (PJMEDIA_ADVERTISE_RTCP && !pjsua_var.media_cfg.ice_no_rtcp) 995 ++comp_cnt; 996 997 status = pjmedia_ice_create(pjsua_var.med_endpt, name, comp_cnt, 998 &ice_cfg, &ice_cb, 999 &pjsua_var.calls[i].med_tp); 1000 if (status != PJ_SUCCESS) { 1001 pjsua_perror(THIS_FILE, "Unable to create ICE media transport", 1002 status); 1003 goto on_error; 1004 } 1005 1006 /* Wait until transport is initialized, or time out */ 1007 PJSUA_UNLOCK(); 1008 while (pjsua_var.calls[i].med_tp_ready == PJ_EPENDING) { 1009 pjsua_handle_events(100); 1010 } 1011 PJSUA_LOCK(); 1012 if (pjsua_var.calls[i].med_tp_ready != PJ_SUCCESS) { 1013 pjsua_perror(THIS_FILE, "Error initializing ICE media transport", 1014 pjsua_var.calls[i].med_tp_ready); 1015 status = pjsua_var.calls[i].med_tp_ready; 1016 goto on_error; 1017 } 1018 1019 pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp, 1020 PJMEDIA_DIR_ENCODING, 1021 pjsua_var.media_cfg.tx_drop_pct); 1022 1023 pjmedia_transport_simulate_lost(pjsua_var.calls[i].med_tp, 1024 PJMEDIA_DIR_DECODING, 1025 pjsua_var.media_cfg.rx_drop_pct); 1026 } 1060 pj_bzero(&ice_cb, sizeof(pjmedia_ice_cb)); 1061 ice_cb.on_ice_complete = &on_ice_complete; 1062 pj_ansi_snprintf(name, sizeof(name), "icetp%02d", call_med->idx); 1063 call_med->tp_ready = PJ_EPENDING; 1064 1065 comp_cnt = 1; 1066 if (PJMEDIA_ADVERTISE_RTCP && !pjsua_var.media_cfg.ice_no_rtcp) 1067 ++comp_cnt; 1068 1069 status = pjmedia_ice_create(pjsua_var.med_endpt, name, comp_cnt, 1070 &ice_cfg, &ice_cb, &call_med->tp); 1071 if (status != PJ_SUCCESS) { 1072 pjsua_perror(THIS_FILE, "Unable to create ICE media transport", 1073 status); 1074 goto on_error; 1075 } 1076 1077 /* Wait until transport is initialized, or time out */ 1078 PJSUA_UNLOCK(); 1079 while (call_med->tp_ready == PJ_EPENDING) { 1080 pjsua_handle_events(100); 1081 } 1082 PJSUA_LOCK(); 1083 if (call_med->tp_ready != PJ_SUCCESS) { 1084 pjsua_perror(THIS_FILE, "Error initializing ICE media transport", 1085 call_med->tp_ready); 1086 status = call_med->tp_ready; 1087 goto on_error; 1088 } 1089 1090 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_ENCODING, 1091 pjsua_var.media_cfg.tx_drop_pct); 1092 1093 pjmedia_transport_simulate_lost(call_med->tp, PJMEDIA_DIR_DECODING, 1094 pjsua_var.media_cfg.rx_drop_pct); 1027 1095 1028 1096 return PJ_SUCCESS; 1029 1097 1030 1098 on_error: 1031 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 1032 if (pjsua_var.calls[i].med_tp != NULL) { 1033 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 1034 pjsua_var.calls[i].med_tp = NULL; 1035 } 1099 if (call_med->tp != NULL) { 1100 pjmedia_transport_close(call_med->tp); 1101 call_med->tp = NULL; 1036 1102 } 1037 1103 … … 1039 1105 } 1040 1106 1041 1042 /* 1043 * Create UDP media transports for all the calls. This function creates 1107 #if DISABLED_FOR_TICKET_1185 1108 /* Create ICE media transports (when ice is enabled) */ 1109 static pj_status_t create_ice_media_transports(pjsua_transport_config *cfg) 1110 { 1111 unsigned i; 1112 pj_status_t status; 1113 1114 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) { 1115 pjsua_call *call = &pjsua_var.calls[i]; 1116 unsigned strm_idx; 1117 1118 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 1119 pjsua_call_media *call_med = &call->media[strm_idx]; 1120 1121 status = create_ice_media_transport(cfg, call_med); 1122 if (status != PJ_SUCCESS) 1123 goto on_error; 1124 } 1125 } 1126 1127 return PJ_SUCCESS; 1128 1129 on_error: 1130 for (i=0; i < pjsua_var.ua_cfg.max_calls; ++i) { 1131 pjsua_call *call = &pjsua_var.calls[i]; 1132 unsigned strm_idx; 1133 1134 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 1135 pjsua_call_media *call_med = &call->media[strm_idx]; 1136 1137 if (call_med->tp) { 1138 pjmedia_transport_close(call_med->tp); 1139 call_med->tp = NULL; 1140 } 1141 } 1142 } 1143 return status; 1144 } 1145 #endif 1146 1147 #if DISABLED_FOR_TICKET_1185 1148 /* 1149 * Create media transports for all the calls. This function creates 1044 1150 * one UDP media transport for each call. 1045 1151 */ … … 1059 1165 /* Delete existing media transports */ 1060 1166 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 1061 if (pjsua_var.calls[i].med_tp != NULL && 1062 pjsua_var.calls[i].med_tp_auto_del) 1063 { 1064 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 1065 pjsua_var.calls[i].med_tp = NULL; 1066 pjsua_var.calls[i].med_orig = NULL; 1167 pjsua_call *call = &pjsua_var.calls[i]; 1168 unsigned strm_idx; 1169 1170 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 1171 pjsua_call_media *call_med = &call->media[strm_idx]; 1172 1173 if (call_med->tp && call_med->tp_auto_del) { 1174 pjmedia_transport_close(call_med->tp); 1175 call_med->tp = NULL; 1176 call_med->tp_orig = NULL; 1177 } 1067 1178 } 1068 1179 } … … 1080 1191 /* Set media transport auto_delete to True */ 1081 1192 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 1082 pjsua_var.calls[i].med_tp_auto_del = PJ_TRUE; 1193 pjsua_call *call = &pjsua_var.calls[i]; 1194 unsigned strm_idx; 1195 1196 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 1197 pjsua_call_media *call_med = &call->media[strm_idx]; 1198 1199 call_med->tp_auto_del = PJ_TRUE; 1200 } 1083 1201 } 1084 1202 … … 1101 1219 /* Assign the media transports */ 1102 1220 for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 1103 if (pjsua_var.calls[i].med_tp != NULL && 1104 pjsua_var.calls[i].med_tp_auto_del) 1105 { 1106 pjmedia_transport_close(pjsua_var.calls[i].med_tp); 1107 } 1108 1109 pjsua_var.calls[i].med_tp = tp[i].transport; 1110 pjsua_var.calls[i].med_tp_auto_del = auto_delete; 1221 pjsua_call *call = &pjsua_var.calls[i]; 1222 unsigned strm_idx; 1223 1224 for (strm_idx=0; strm_idx < call->med_cnt; ++strm_idx) { 1225 pjsua_call_media *call_med = &call->media[strm_idx]; 1226 1227 if (call_med->tp && call_med->tp_auto_del) { 1228 pjmedia_transport_close(call_med->tp); 1229 call_med->tp = NULL; 1230 call_med->tp_orig = NULL; 1231 } 1232 } 1233 1234 PJ_TODO(remove_pjsua_media_transports_attach); 1235 1236 call->media[0].tp = tp[i].transport; 1237 call->media[0].tp_auto_del = auto_delete; 1111 1238 } 1112 1239 1113 1240 return PJ_SUCCESS; 1114 1241 } 1115 1116 1117 static int find_audio_index(const pjmedia_sdp_session *sdp, 1118 pj_bool_t prefer_srtp) 1242 #endif 1243 1244 /* Go through the list of media in the SDP, find acceptable media, and 1245 * sort them based on the "quality" of the media, and store the indexes 1246 * in the specified array. Media with the best quality will be listed 1247 * first in the array. The quality factors considered currently is 1248 * encryption. 1249 */ 1250 static void sort_media(const pjmedia_sdp_session *sdp, 1251 const pj_str_t *type, 1252 pjmedia_srtp_use use_srtp, 1253 pj_uint8_t midx[], 1254 unsigned *p_count) 1119 1255 { 1120 1256 unsigned i; 1121 int audio_idx = -1; 1122 1123 for (i=0; i<sdp->media_count; ++i) { 1257 unsigned count = 0; 1258 int score[PJSUA_MAX_CALL_MEDIA]; 1259 1260 pj_assert(*p_count >= PJSUA_MAX_CALL_MEDIA); 1261 1262 *p_count = 0; 1263 pj_bzero(score, sizeof(score)); 1264 1265 /* Score each media */ 1266 for (i=0; i<sdp->media_count && count<PJSUA_MAX_CALL_MEDIA; ++i) { 1124 1267 const pjmedia_sdp_media *m = sdp->media[i]; 1125 1268 1126 /* Skip if media is not audio */ 1127 if (pj_stricmp2(&m->desc.media, "audio") != 0) 1269 /* Skip different media */ 1270 if (pj_stricmp(&m->desc.media, type) != 0) { 1271 score[count++] = -22000; 1128 1272 continue; 1129 1130 /* Skip if media is disabled */ 1273 } 1274 1275 /* Supported transports */ 1276 if (pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) { 1277 switch (use_srtp) { 1278 case PJMEDIA_SRTP_MANDATORY: 1279 case PJMEDIA_SRTP_OPTIONAL: 1280 ++score[i]; 1281 break; 1282 case PJMEDIA_SRTP_DISABLED: 1283 --score[i]; 1284 break; 1285 } 1286 } else if (pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) { 1287 switch (use_srtp) { 1288 case PJMEDIA_SRTP_MANDATORY: 1289 --score[i]; 1290 break; 1291 case PJMEDIA_SRTP_OPTIONAL: 1292 /* No change in score */ 1293 break; 1294 case PJMEDIA_SRTP_DISABLED: 1295 ++score[i]; 1296 break; 1297 } 1298 } else { 1299 score[i] -= 10; 1300 } 1301 1302 /* Is media disabled? */ 1131 1303 if (m->desc.port == 0) 1132 continue; 1133 1134 /* Skip if transport is not supported */ 1135 if (pj_stricmp2(&m->desc.transport, "RTP/AVP") != 0 && 1136 pj_stricmp2(&m->desc.transport, "RTP/SAVP") != 0) 1137 { 1138 continue; 1139 } 1140 1141 if (audio_idx == -1) { 1142 audio_idx = i; 1304 score[i] -= 10; 1305 1306 /* Is media inactive? */ 1307 if (pjmedia_sdp_media_find_attr2(m, "inactive", NULL)) 1308 score[i] -= 10; 1309 1310 ++count; 1311 } 1312 1313 /* Created sorted list based on quality */ 1314 for (i=0; i<count; ++i) { 1315 unsigned j; 1316 int best = 0; 1317 1318 for (j=1; j<count; ++j) { 1319 if (score[j] > score[best]) 1320 best = j; 1321 } 1322 /* Don't put media with negative score, that media is unacceptable 1323 * for us. 1324 */ 1325 if (score[best] >= 0) { 1326 midx[*p_count] = (pj_uint8_t)best; 1327 (*p_count)++; 1328 } 1329 1330 score[best] = -22000; 1331 1332 } 1333 } 1334 1335 /* Initialize the media line */ 1336 static pj_status_t pjsua_call_media_init(pjsua_call_media *call_med, 1337 pjmedia_type type, 1338 const pjsua_transport_config *tcfg, 1339 int security_level, 1340 int *sip_err_code) 1341 { 1342 pjsua_acc *acc = &pjsua_var.acc[call_med->call->acc_id]; 1343 pj_status_t status; 1344 1345 /* 1346 * Note: this function may be called when the media already exists 1347 * (e.g. in reinvites, updates, etc.) 1348 */ 1349 call_med->type = type; 1350 1351 /* Create the media transport for initial call. This is blocking for now */ 1352 if (call_med->tp == NULL) { 1353 if (pjsua_var.media_cfg.enable_ice) { 1354 status = create_ice_media_transport(tcfg, call_med); 1143 1355 } else { 1144 /* We've found multiple candidates. This could happen 1145 * e.g. when remote is offering both RTP/SAVP and RTP/AVP, 1146 * or when remote for some reason offers two audio. 1147 */ 1148 1149 if (prefer_srtp && 1150 pj_stricmp2(&m->desc.transport, "RTP/SAVP")==0) 1151 { 1152 /* Prefer RTP/SAVP when our media transport is SRTP */ 1153 audio_idx = i; 1154 break; 1155 } else if (!prefer_srtp && 1156 pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) 1157 { 1158 /* Prefer RTP/AVP when our media transport is NOT SRTP */ 1159 audio_idx = i; 1356 status = create_udp_media_transport(tcfg, call_med); 1357 } 1358 1359 if (status != PJ_SUCCESS) { 1360 PJ_PERROR(1,(THIS_FILE, status, "Error creating media transport")); 1361 return status; 1362 } 1363 } 1364 1365 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1366 /* This function may be called when SRTP transport already exists 1367 * (e.g: in re-invite, update), don't need to destroy/re-create. 1368 */ 1369 if (!call_med->tp_orig || call_med->tp == call_med->tp_orig) { 1370 pjmedia_srtp_setting srtp_opt; 1371 pjmedia_transport *srtp = NULL; 1372 1373 /* Check if SRTP requires secure signaling */ 1374 if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) { 1375 if (security_level < acc->cfg.srtp_secure_signaling) { 1376 if (sip_err_code) 1377 *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1378 status = PJSIP_ESESSIONINSECURE; 1379 goto on_error; 1160 1380 } 1161 1381 } 1162 } 1163 1164 return audio_idx; 1165 } 1166 1382 1383 /* Always create SRTP adapter */ 1384 pjmedia_srtp_setting_default(&srtp_opt); 1385 srtp_opt.close_member_tp = PJ_FALSE; 1386 /* If media session has been ever established, let's use remote's 1387 * preference in SRTP usage policy, especially when it is stricter. 1388 */ 1389 if (call_med->rem_srtp_use > acc->cfg.use_srtp) 1390 srtp_opt.use = call_med->rem_srtp_use; 1391 else 1392 srtp_opt.use = acc->cfg.use_srtp; 1393 1394 status = pjmedia_transport_srtp_create(pjsua_var.med_endpt, 1395 call_med->tp, 1396 &srtp_opt, &srtp); 1397 if (status != PJ_SUCCESS) { 1398 if (sip_err_code) 1399 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; 1400 goto on_error; 1401 } 1402 1403 /* Set SRTP as current media transport */ 1404 call_med->tp_orig = call_med->tp; 1405 call_med->tp = srtp; 1406 } 1407 #else 1408 call->tp_orig = call->tp; 1409 PJ_UNUSED_ARG(security_level); 1410 #endif 1411 1412 return PJ_SUCCESS; 1413 1414 on_error: 1415 if (call_med->tp) { 1416 pjmedia_transport_close(call_med->tp); 1417 call_med->tp = NULL; 1418 } 1419 return status; 1420 } 1167 1421 1168 1422 pj_status_t pjsua_media_channel_init(pjsua_call_id call_id, … … 1173 1427 int *sip_err_code) 1174 1428 { 1429 const pj_str_t STR_AUDIO = { "audio", 5 }; 1430 const pj_str_t STR_VIDEO = { "video", 5 }; 1175 1431 pjsua_call *call = &pjsua_var.calls[call_id]; 1432 pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 1433 pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; 1434 unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); 1435 pj_uint8_t mvididx[PJSUA_MAX_CALL_MEDIA]; 1436 unsigned mvidcnt = PJ_ARRAY_SIZE(mvididx); 1437 pjmedia_type media_types[PJSUA_MAX_CALL_MEDIA]; 1438 unsigned mi; 1176 1439 pj_status_t status; 1177 1440 1178 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)1179 pjsua_acc *acc = &pjsua_var.acc[call->acc_id];1180 pjmedia_srtp_setting srtp_opt;1181 pjmedia_transport *srtp = NULL;1182 #endif1183 1184 1441 PJ_UNUSED_ARG(role); 1185 1442 1443 if (pjsua_get_state() != PJSUA_STATE_RUNNING) 1444 return PJ_EBUSY; 1445 1446 #if DISABLED_FOR_TICKET_1185 1186 1447 /* Return error if media transport has not been created yet 1187 1448 * (e.g. application is starting) 1188 1449 */ 1189 if (call->med_tp == NULL) { 1190 if (sip_err_code) 1191 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; 1192 return PJ_EBUSY; 1193 } 1194 1195 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1196 /* This function may be called when SRTP transport already exists 1197 * (e.g: in re-invite, update), don't need to destroy/re-create. 1198 */ 1199 if (!call->med_orig || call->med_tp == call->med_orig) { 1200 1201 /* Check if SRTP requires secure signaling */ 1202 if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) { 1203 if (security_level < acc->cfg.srtp_secure_signaling) { 1204 if (sip_err_code) 1205 *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1206 return PJSIP_ESESSIONINSECURE; 1207 } 1208 } 1209 1210 /* Always create SRTP adapter */ 1211 pjmedia_srtp_setting_default(&srtp_opt); 1212 srtp_opt.close_member_tp = PJ_FALSE; 1213 /* If media session has been ever established, let's use remote's 1214 * preference in SRTP usage policy, especially when it is stricter. 1215 */ 1216 if (call->rem_srtp_use > acc->cfg.use_srtp) 1217 srtp_opt.use = call->rem_srtp_use; 1218 else 1219 srtp_opt.use = acc->cfg.use_srtp; 1220 1221 status = pjmedia_transport_srtp_create(pjsua_var.med_endpt, 1222 call->med_tp, 1223 &srtp_opt, &srtp); 1224 if (status != PJ_SUCCESS) { 1225 if (sip_err_code) 1226 *sip_err_code = PJSIP_SC_INTERNAL_SERVER_ERROR; 1227 return status; 1228 } 1229 1230 /* Set SRTP as current media transport */ 1231 call->med_orig = call->med_tp; 1232 call->med_tp = srtp; 1233 } 1234 #else 1235 call->med_orig = call->med_tp; 1236 PJ_UNUSED_ARG(security_level); 1450 for (i=0; i<call->med_cnt; ++i) { 1451 if (call->media[i].tp == NULL) { 1452 return PJ_EBUSY; 1453 } 1454 } 1237 1455 #endif 1238 1456 1239 /* Find out which media line in SDP that we support. If we are offerer, 1240 * audio will be initialized at index 0 in SDP. 1241 */ 1242 if (rem_sdp == NULL) { 1243 call->audio_idx = 0; 1244 } 1245 /* Otherwise find out the candidate audio media line in SDP */ 1246 else { 1247 pj_bool_t srtp_active; 1248 1249 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1250 srtp_active = acc->cfg.use_srtp; 1251 #else 1252 srtp_active = PJ_FALSE; 1253 #endif 1254 1255 /* Media count must have been checked */ 1256 pj_assert(rem_sdp->media_count != 0); 1257 1258 call->audio_idx = find_audio_index(rem_sdp, srtp_active); 1259 } 1260 1261 /* Reject offer if we couldn't find a good m=audio line in offer */ 1262 if (call->audio_idx < 0) { 1457 if (rem_sdp) { 1458 sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, 1459 maudidx, &maudcnt); 1460 1461 if (maudcnt==0) { 1462 /* Expecting audio in the offer */ 1463 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 1464 pjsua_media_channel_deinit(call_id); 1465 return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); 1466 } 1467 1468 sort_media(rem_sdp, &STR_VIDEO, acc->cfg.use_srtp, 1469 mvididx, &mvidcnt); 1470 mvidcnt = (mvidcnt < acc->cfg.max_video_cnt) ? 1471 mvidcnt : acc->cfg.max_video_cnt; 1472 1473 } else { 1474 maudcnt = acc->cfg.max_audio_cnt; 1475 for (mi=0; mi<maudcnt; ++mi) { 1476 maudidx[mi] = mi; 1477 media_types[mi] = PJMEDIA_TYPE_AUDIO; 1478 } 1479 mvidcnt = acc->cfg.max_video_cnt; 1480 for (mi=0; mi<mvidcnt; ++mi) { 1481 media_types[maudcnt + mi] = PJMEDIA_TYPE_VIDEO; 1482 } 1483 } 1484 1485 call->med_cnt = maudcnt + mvidcnt; 1486 1487 if (call->med_cnt == 0) { 1488 /* Expecting at least one media */ 1263 1489 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 1264 1490 pjsua_media_channel_deinit(call_id); … … 1266 1492 } 1267 1493 1268 PJ_LOG(4,(THIS_FILE, "Media index %d selected for call %d", 1494 /* Initialize each media line */ 1495 for (mi=0; mi < call->med_cnt; ++mi) { 1496 pjsua_call_media *call_med = &call->media[mi]; 1497 pj_bool_t enabled = PJ_FALSE; 1498 pjmedia_type media_type = PJMEDIA_TYPE_NONE; 1499 1500 if (rem_sdp) { 1501 if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_AUDIO)) { 1502 media_type = PJMEDIA_TYPE_AUDIO; 1503 if (pj_memchr(maudidx, mi, maudcnt * sizeof(maudidx[0]))) { 1504 enabled = PJ_TRUE; 1505 } 1506 } 1507 else if (!pj_stricmp(&rem_sdp->media[mi]->desc.media, &STR_VIDEO)) { 1508 media_type = PJMEDIA_TYPE_VIDEO; 1509 if (pj_memchr(mvididx, mi, mvidcnt * sizeof(mvididx[0]))) { 1510 enabled = PJ_TRUE; 1511 } 1512 } 1513 1514 } else { 1515 enabled = PJ_TRUE; 1516 media_type = media_types[mi]; 1517 } 1518 1519 if (enabled) { 1520 status = pjsua_call_media_init(call_med, media_type, 1521 &acc->cfg.rtp_cfg, 1522 security_level, sip_err_code); 1523 if (status != PJ_SUCCESS) { 1524 pjsua_media_channel_deinit(call_id); 1525 return status; 1526 } 1527 } else { 1528 /* By convention, the media is inactive if transport is NULL */ 1529 if (call_med->tp) { 1530 pjmedia_transport_close(call_med->tp); 1531 call_med->tp = NULL; 1532 } 1533 } 1534 } 1535 1536 call->audio_idx = maudidx[0]; 1537 1538 PJ_LOG(4,(THIS_FILE, "Media index %d selected for audio call %d", 1269 1539 call->audio_idx, call->index)); 1270 1540 1271 /* Create the media transport */ 1272 status = pjmedia_transport_media_create(call->med_tp, tmp_pool, 0, 1273 rem_sdp, call->audio_idx); 1274 if (status != PJ_SUCCESS) { 1275 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1276 pjsua_media_channel_deinit(call_id); 1277 return status; 1278 } 1279 1280 call->med_tp_st = PJSUA_MED_TP_INIT; 1541 /* Tell the media transport of a new offer/answer session */ 1542 for (mi=0; mi < call->med_cnt; ++mi) { 1543 pjsua_call_media *call_med = &call->media[mi]; 1544 1545 /* Note: tp may be NULL if this media line is inactive */ 1546 if (call_med->tp) { 1547 status = pjmedia_transport_media_create(call_med->tp, 1548 tmp_pool, 0, 1549 rem_sdp, mi); 1550 if (status != PJ_SUCCESS) { 1551 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1552 pjsua_media_channel_deinit(call_id); 1553 return status; 1554 } 1555 1556 call_med->tp_st = PJSUA_MED_TP_INIT; 1557 } 1558 } 1559 1281 1560 return PJ_SUCCESS; 1282 1561 } … … 1286 1565 const pjmedia_sdp_session *rem_sdp, 1287 1566 pjmedia_sdp_session **p_sdp, 1288 int *sip_status_code) 1289 { 1290 enum { MAX_MEDIA = 1 }; 1567 int *sip_err_code) 1568 { 1569 const pj_str_t STR_AUDIO = { "audio", 5 }; 1570 enum { MAX_MEDIA = PJSUA_MAX_CALL_MEDIA }; 1291 1571 pjmedia_sdp_session *sdp; 1292 pj media_transport_info tpinfo;1572 pj_sockaddr origin; 1293 1573 pjsua_call *call = &pjsua_var.calls[call_id]; 1574 pjsua_acc *acc = &pjsua_var.acc[call->acc_id]; 1294 1575 pjmedia_sdp_neg_state sdp_neg_state = PJMEDIA_SDP_NEG_STATE_NULL; 1576 unsigned mi; 1295 1577 pj_status_t status; 1296 1578 1297 /* Return error if media transport has not been created yet 1298 * (e.g. application is starting) 1579 if (pjsua_get_state() != PJSUA_STATE_RUNNING) 1580 return PJ_EBUSY; 1581 1582 if (rem_sdp) { 1583 pj_uint8_t maudidx[PJSUA_MAX_CALL_MEDIA]; 1584 unsigned maudcnt = PJ_ARRAY_SIZE(maudidx); 1585 1586 sort_media(rem_sdp, &STR_AUDIO, acc->cfg.use_srtp, 1587 maudidx, &maudcnt); 1588 1589 if (maudcnt==0) { 1590 /* Expecting audio in the offer */ 1591 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 1592 pjsua_media_channel_deinit(call_id); 1593 return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE_HERE); 1594 } 1595 1596 call->audio_idx = maudidx[0]; 1597 } else { 1598 /* Audio is first in our offer, by convention */ 1599 call->audio_idx = 0; 1600 } 1601 1602 /* Create media if it's not created. This could happen when call is 1603 * currently on-hold (with the old style hold) 1299 1604 */ 1300 if (call->med_tp == NULL) { 1301 return PJ_EBUSY; 1302 } 1303 1304 if (rem_sdp && rem_sdp->media_count != 0) { 1305 pj_bool_t srtp_active; 1306 1307 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1308 srtp_active = pjsua_var.acc[call->acc_id].cfg.use_srtp; 1309 #else 1310 srtp_active = PJ_FALSE; 1311 #endif 1312 1313 call->audio_idx = find_audio_index(rem_sdp, srtp_active); 1314 if (call->audio_idx == -1) { 1315 /* No audio in the offer. We can't accept this */ 1316 PJ_LOG(4,(THIS_FILE, 1317 "Unable to accept SDP offer without audio for call %d", 1318 call_id)); 1319 return PJMEDIA_SDP_EINMEDIA; 1320 } 1321 } 1322 1323 /* Media index must have been determined before */ 1324 pj_assert(call->audio_idx != -1); 1325 1326 /* Create media if it's not created. This could happen when call is 1327 * currently on-hold 1328 */ 1329 if (call->med_tp_st == PJSUA_MED_TP_IDLE) { 1605 if (call->media[call->audio_idx].tp == NULL) { 1330 1606 pjsip_role_e role; 1331 1607 role = (rem_sdp ? PJSIP_ROLE_UAS : PJSIP_ROLE_UAC); 1332 1608 status = pjsua_media_channel_init(call_id, role, call->secure_level, 1333 pool, rem_sdp, sip_ status_code);1609 pool, rem_sdp, sip_err_code); 1334 1610 if (status != PJ_SUCCESS) 1335 1611 return status; … … 1340 1616 sdp_neg_state = pjmedia_sdp_neg_get_state(call->inv->neg); 1341 1617 1342 /* Get media socket info */ 1343 pjmedia_transport_info_init(&tpinfo); 1344 pjmedia_transport_get_info(call->med_tp, &tpinfo); 1345 1346 /* Create SDP */ 1347 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, MAX_MEDIA, 1348 &tpinfo.sock_info, &sdp); 1349 if (status != PJ_SUCCESS) { 1350 if (sip_status_code) *sip_status_code = 500; 1618 /* Get one address to use in the origin field */ 1619 pj_bzero(&origin, sizeof(origin)); 1620 for (mi=0; mi<call->med_cnt; ++mi) { 1621 pjmedia_transport_info tpinfo; 1622 1623 if (call->media[mi].tp == NULL) 1624 continue; 1625 1626 pjmedia_transport_info_init(&tpinfo); 1627 pjmedia_transport_get_info(call->media[mi].tp, &tpinfo); 1628 pj_sockaddr_cp(&origin, &tpinfo.sock_info.rtp_addr_name); 1629 break; 1630 } 1631 1632 /* Create the base (blank) SDP */ 1633 status = pjmedia_endpt_create_base_sdp(pjsua_var.med_endpt, pool, NULL, 1634 &origin, &sdp); 1635 if (status != PJ_SUCCESS) 1351 1636 return status; 1352 } 1353 1354 /* If we're answering or updating the session with a new offer, 1355 * and the selected media is not the first media 1356 * in SDP, then fill in the unselected media with with zero port. 1357 * Otherwise we'll crash in transport_encode_sdp() because the media 1358 * lines are not aligned between offer and answer. 1359 */ 1360 if (call->audio_idx != 0 && 1361 (rem_sdp || sdp_neg_state==PJMEDIA_SDP_NEG_STATE_DONE)) 1362 { 1363 unsigned i; 1364 const pjmedia_sdp_session *ref_sdp = rem_sdp; 1365 1366 if (!ref_sdp) { 1367 /* We are updating session with a new offer */ 1368 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, 1369 &ref_sdp); 1370 pj_assert(status == PJ_SUCCESS); 1371 } 1372 1373 for (i=0; i<ref_sdp->media_count; ++i) { 1374 const pjmedia_sdp_media *ref_m = ref_sdp->media[i]; 1375 pjmedia_sdp_media *m; 1376 1377 if ((int)i == call->audio_idx) 1378 continue; 1379 1380 m = pjmedia_sdp_media_clone_deactivate(pool, ref_m); 1381 if (i==sdp->media_count) 1382 sdp->media[sdp->media_count++] = m; 1383 else { 1384 pj_array_insert(sdp->media, sizeof(sdp->media[0]), 1385 sdp->media_count, i, &m); 1386 ++sdp->media_count; 1637 1638 /* Process each media line */ 1639 for (mi=0; mi<call->med_cnt; ++mi) { 1640 pjsua_call_media *call_med = &call->media[mi]; 1641 pjmedia_sdp_media *m = NULL; 1642 pjmedia_transport_info tpinfo; 1643 1644 if (call_med->tp == NULL) { 1645 /* 1646 * This media is deactivated. Just create a valid SDP with zero 1647 * port. 1648 */ 1649 m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 1650 m->desc.transport = pj_str("RTP/AVP"); 1651 m->desc.fmt_count = 1; 1652 m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); 1653 m->conn->net_type = pj_str("IN"); 1654 m->conn->addr_type = pj_str("IP4"); 1655 m->conn->addr = pj_str("127.0.0.1"); 1656 1657 switch (call_med->type) { 1658 case PJMEDIA_TYPE_AUDIO: 1659 m->desc.media = pj_str("audio"); 1660 m->desc.fmt[0] = pj_str("0"); 1661 break; 1662 case PJMEDIA_TYPE_VIDEO: 1663 m->desc.media = pj_str("video"); 1664 m->desc.fmt[0] = pj_str("31"); 1665 break; 1666 default: 1667 if (rem_sdp && mi < rem_sdp->media_count) { 1668 pj_strdup(pool, &m->desc.media, 1669 &rem_sdp->media[mi]->desc.media); 1670 pj_strdup(pool, &m->desc.fmt[0], 1671 &rem_sdp->media[mi]->desc.fmt[0]); 1672 } else { 1673 pj_assert(!"Invalid call_med media type"); 1674 return PJ_EBUG; 1675 } 1387 1676 } 1677 1678 sdp->media[sdp->media_count++] = m; 1679 continue; 1680 } 1681 1682 /* Get transport address info */ 1683 pjmedia_transport_info_init(&tpinfo); 1684 pjmedia_transport_get_info(call_med->tp, &tpinfo); 1685 1686 /* Ask pjmedia endpoint to create SDP media line */ 1687 switch (call_med->type) { 1688 case PJMEDIA_TYPE_AUDIO: 1689 status = pjmedia_endpt_create_audio_sdp(pjsua_var.med_endpt, pool, 1690 &tpinfo.sock_info, 0, &m); 1691 break; 1692 case PJMEDIA_TYPE_VIDEO: 1693 status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool, 1694 &tpinfo.sock_info, 0, &m); 1695 break; 1696 default: 1697 pj_assert(!"Invalid call_med media type"); 1698 return PJ_EBUG; 1699 } 1700 1701 if (status != PJ_SUCCESS) 1702 return status; 1703 1704 sdp->media[sdp->media_count++] = m; 1705 1706 /* Give to transport */ 1707 status = pjmedia_transport_encode_sdp(call_med->tp, pool, 1708 sdp, rem_sdp, mi); 1709 if (status != PJ_SUCCESS) { 1710 if (sip_err_code) *sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 1711 return status; 1388 1712 } 1389 1713 } … … 1413 1737 } 1414 1738 1415 /* Give the SDP to media transport */ 1416 status = pjmedia_transport_encode_sdp(call->med_tp, pool, sdp, rem_sdp, 1417 call->audio_idx); 1418 if (status != PJ_SUCCESS) { 1419 if (sip_status_code) *sip_status_code = PJSIP_SC_NOT_ACCEPTABLE; 1420 return status; 1421 } 1422 1423 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1739 1740 #if DISABLED_FOR_TICKET_1185 && defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 1424 1741 /* Check if SRTP is in optional mode and configured to use duplicated 1425 1742 * media, i.e: secured and unsecured version, in the SDP offer. … … 1434 1751 pjmedia_sdp_media *m = sdp->media[i]; 1435 1752 1436 /* Check if this media is unsecured but has SDP "crypto" 1753 /* Check if this media is unsecured but has SDP "crypto" 1437 1754 * attribute. 1438 1755 */ … … 1440 1757 pjmedia_sdp_media_find_attr2(m, "crypto", NULL) != NULL) 1441 1758 { 1442 if (i == (unsigned)call->audio_idx && 1759 if (i == (unsigned)call->audio_idx && 1443 1760 sdp_neg_state == PJMEDIA_SDP_NEG_STATE_DONE) 1444 1761 { … … 1463 1780 /* Insert the new media before the unsecured media */ 1464 1781 if (sdp->media_count < PJMEDIA_MAX_SDP_MEDIA) { 1465 pj_array_insert(sdp->media, sizeof(new_m), 1782 pj_array_insert(sdp->media, sizeof(new_m), 1466 1783 sdp->media_count, i, &new_m); 1467 1784 ++sdp->media_count; … … 1474 1791 #endif 1475 1792 1476 /* Update currently advertised RTP source address */1477 pj_memcpy(&call->med_rtp_addr, &tpinfo.sock_info.rtp_addr_name,1478 sizeof(pj_sockaddr));1479 1480 1793 *p_sdp = sdp; 1481 1794 return PJ_SUCCESS; … … 1486 1799 { 1487 1800 pjsua_call *call = &pjsua_var.calls[call_id]; 1488 1489 if (call->conf_slot != PJSUA_INVALID_ID) { 1490 if (pjsua_var.mconf) { 1491 pjsua_conf_remove_port(call->conf_slot); 1492 } 1493 call->conf_slot = PJSUA_INVALID_ID; 1494 } 1495 1496 if (call->session) { 1497 pjmedia_rtcp_stat stat; 1498 1499 if ((call->media_dir & PJMEDIA_DIR_ENCODING) && 1500 (pjmedia_session_get_stream_stat(call->session, 0, &stat) 1501 == PJ_SUCCESS)) 1801 unsigned mi; 1802 1803 for (mi=0; mi<call->med_cnt; ++mi) { 1804 pjsua_call_media *call_med = &call->media[mi]; 1805 1806 if (call_med->type == PJMEDIA_TYPE_AUDIO) { 1807 pjmedia_stream *strm = call_med->strm.a.stream; 1808 pjmedia_rtcp_stat stat; 1809 1810 if (strm) { 1811 if (call_med->strm.a.conf_slot != PJSUA_INVALID_ID) { 1812 if (pjsua_var.mconf) { 1813 pjsua_conf_remove_port(call_med->strm.a.conf_slot); 1814 } 1815 call_med->strm.a.conf_slot = PJSUA_INVALID_ID; 1816 } 1817 1818 if ((call_med->dir & PJMEDIA_DIR_ENCODING) && 1819 (pjmedia_stream_get_stat(strm, &stat) == PJ_SUCCESS)) 1820 { 1821 /* Save RTP timestamp & sequence, so when media session is 1822 * restarted, those values will be restored as the initial 1823 * RTP timestamp & sequence of the new media session. So in 1824 * the same call session, RTP timestamp and sequence are 1825 * guaranteed to be contigue. 1826 */ 1827 call_med->rtp_tx_seq_ts_set = 1 | (1 << 1); 1828 call_med->rtp_tx_seq = stat.rtp_tx_last_seq; 1829 call_med->rtp_tx_ts = stat.rtp_tx_last_ts; 1830 } 1831 1832 if (pjsua_var.ua_cfg.cb.on_stream_destroyed) { 1833 pjsua_var.ua_cfg.cb.on_stream_destroyed(call_id, strm, mi); 1834 } 1835 1836 pjmedia_stream_destroy(strm); 1837 call_med->strm.a.stream = NULL; 1838 1839 PJ_LOG(4,(THIS_FILE, "Media session call%02d:%d is destroyed", 1840 call_id, mi)); 1841 } 1842 } 1843 call_med->state = PJSUA_CALL_MEDIA_NONE; 1844 } 1845 } 1846 1847 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) 1848 { 1849 pjsua_call *call = &pjsua_var.calls[call_id]; 1850 unsigned mi; 1851 1852 stop_media_session(call_id); 1853 1854 for (mi=0; mi<call->med_cnt; ++mi) { 1855 pjsua_call_media *call_med = &call->media[mi]; 1856 1857 if (call_med->tp_st != PJSUA_MED_TP_IDLE) { 1858 pjmedia_transport_media_stop(call_med->tp); 1859 call_med->tp_st = PJSUA_MED_TP_IDLE; 1860 } 1861 1862 if (call_med->tp_orig && call_med->tp && 1863 call_med->tp != call_med->tp_orig) 1502 1864 { 1503 /* Save RTP timestamp & sequence, so when media session is 1504 * restarted, those values will be restored as the initial 1505 * RTP timestamp & sequence of the new media session. So in 1506 * the same call session, RTP timestamp and sequence are 1507 * guaranteed to be contigue. 1508 */ 1509 call->rtp_tx_seq_ts_set = 1 | (1 << 1); 1510 call->rtp_tx_seq = stat.rtp_tx_last_seq; 1511 call->rtp_tx_ts = stat.rtp_tx_last_ts; 1512 } 1513 1514 if (pjsua_var.ua_cfg.cb.on_stream_destroyed) { 1515 pjsua_var.ua_cfg.cb.on_stream_destroyed(call_id, call->session, 0); 1516 } 1517 1518 pjmedia_session_destroy(call->session); 1519 call->session = NULL; 1520 1521 PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed", 1522 call_id)); 1523 1524 } 1525 1526 call->media_st = PJSUA_CALL_MEDIA_NONE; 1527 } 1528 1529 pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id) 1530 { 1531 pjsua_call *call = &pjsua_var.calls[call_id]; 1532 1533 stop_media_session(call_id); 1534 1535 if (call->med_tp_st != PJSUA_MED_TP_IDLE) { 1536 pjmedia_transport_media_stop(call->med_tp); 1537 call->med_tp_st = PJSUA_MED_TP_IDLE; 1538 } 1539 1540 if (call->med_orig && call->med_tp && call->med_tp != call->med_orig) { 1541 pjmedia_transport_close(call->med_tp); 1542 call->med_tp = call->med_orig; 1865 pjmedia_transport_close(call_med->tp); 1866 call_med->tp = call_med->tp_orig; 1867 } 1543 1868 } 1544 1869 … … 1570 1895 1571 1896 1572 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, 1573 const pjmedia_sdp_session *local_sdp, 1574 const pjmedia_sdp_session *remote_sdp) 1575 { 1576 int prev_media_st = 0; 1577 pjsua_call *call = &pjsua_var.calls[call_id]; 1578 pjmedia_session_info sess_info; 1579 pjmedia_stream_info *si = NULL; 1897 static pj_status_t audio_channel_update(pjsua_call_media *call_med, 1898 pj_pool_t *tmp_pool, 1899 const pjmedia_sdp_session *local_sdp, 1900 const pjmedia_sdp_session *remote_sdp) 1901 { 1902 pjsua_call *call = call_med->call; 1903 pjmedia_stream_info the_si, *si = &the_si; 1580 1904 pjmedia_port *media_port; 1905 unsigned strm_idx = call_med->idx; 1581 1906 pj_status_t status; 1582 1583 if (!pjsua_var.med_endpt) { 1584 /* We're being shutdown */ 1585 return PJ_EBUSY; 1586 } 1587 1588 /* Destroy existing media session, if any. */ 1589 prev_media_st = call->media_st; 1590 stop_media_session(call->index); 1591 1592 /* Create media session info based on SDP parameters. 1593 */ 1594 status = pjmedia_session_info_from_sdp( call->inv->pool_prov, 1595 pjsua_var.med_endpt, 1596 PJMEDIA_MAX_SDP_MEDIA, &sess_info, 1597 local_sdp, remote_sdp); 1907 1908 status = pjmedia_stream_info_from_sdp(si, tmp_pool, pjsua_var.med_endpt, 1909 local_sdp, remote_sdp, strm_idx); 1598 1910 if (status != PJ_SUCCESS) 1599 1911 return status; 1600 1912 1601 /* Update audio index from the negotiated SDP */1602 call->audio_idx = find_audio_index(local_sdp, PJ_TRUE);1603 1604 /* Find which session is audio */1605 PJ_ASSERT_RETURN(call->audio_idx != -1, PJ_EBUG);1606 PJ_ASSERT_RETURN(call->audio_idx < (int)sess_info.stream_cnt, PJ_EBUG);1607 si = &sess_info.stream_info[call->audio_idx];1608 1609 /* Reset session info with only one media stream */1610 sess_info.stream_cnt = 1;1611 if (si != &sess_info.stream_info[0]) {1612 pj_memcpy(&sess_info.stream_info[0], si, sizeof(pjmedia_stream_info));1613 si = &sess_info.stream_info[0];1614 }1615 1616 1913 /* Check if no media is active */ 1617 if (sess_info.stream_cnt == 0 || si->dir == PJMEDIA_DIR_NONE) 1618 { 1914 if (si->dir == PJMEDIA_DIR_NONE) { 1619 1915 /* Call media state */ 1620 call ->media_st= PJSUA_CALL_MEDIA_NONE;1916 call_med->state = PJSUA_CALL_MEDIA_NONE; 1621 1917 1622 1918 /* Call media direction */ 1623 call->media_dir = PJMEDIA_DIR_NONE; 1624 1625 /* Don't stop transport because we need to transmit keep-alives, and 1626 * also to prevent restarting ICE negotiation. See 1627 * http://trac.pjsip.org/repos/ticket/1094 1628 */ 1629 #if 0 1630 /* Shutdown transport's session */ 1631 pjmedia_transport_media_stop(call->med_tp); 1632 call->med_tp_st = PJSUA_MED_TP_IDLE; 1633 1634 /* No need because we need keepalive? */ 1635 1636 /* Close upper entry of transport stack */ 1637 if (call->med_orig && (call->med_tp != call->med_orig)) { 1638 pjmedia_transport_close(call->med_tp); 1639 call->med_tp = call->med_orig; 1640 } 1641 #endif 1919 call_med->dir = PJMEDIA_DIR_NONE; 1642 1920 1643 1921 } else { … … 1645 1923 1646 1924 /* Start/restart media transport */ 1647 status = pjmedia_transport_media_start(call->med_tp, 1648 call->inv->pool_prov, 1649 local_sdp, remote_sdp, 1650 call->audio_idx); 1925 status = pjmedia_transport_media_start(call_med->tp, 1926 tmp_pool, local_sdp, 1927 remote_sdp, strm_idx); 1651 1928 if (status != PJ_SUCCESS) 1652 1929 return status; 1653 1930 1654 call ->med_tp_st = PJSUA_MED_TP_RUNNING;1931 call_med->tp_st = PJSUA_MED_TP_RUNNING; 1655 1932 1656 1933 /* Get remote SRTP usage policy */ 1657 1934 pjmedia_transport_info_init(&tp_info); 1658 pjmedia_transport_get_info(call ->med_tp, &tp_info);1935 pjmedia_transport_get_info(call_med->tp, &tp_info); 1659 1936 if (tp_info.specific_info_cnt > 0) { 1660 1937 unsigned i; … … 1665 1942 (pjmedia_srtp_info*) tp_info.spc_info[i].buffer; 1666 1943 1667 call ->rem_srtp_use = srtp_info->peer_use;1944 call_med->rem_srtp_use = srtp_info->peer_use; 1668 1945 break; 1669 1946 } … … 1694 1971 1695 1972 /* Set SSRC */ 1696 si->ssrc = call ->ssrc;1973 si->ssrc = call_med->ssrc; 1697 1974 1698 1975 /* Set RTP timestamp & sequence, normally these value are intialized … … 1701 1978 * contigue. 1702 1979 */ 1703 si->rtp_ts = call ->rtp_tx_ts;1704 si->rtp_seq = call ->rtp_tx_seq;1705 si->rtp_seq_ts_set = call ->rtp_tx_seq_ts_set;1980 si->rtp_ts = call_med->rtp_tx_ts; 1981 si->rtp_seq = call_med->rtp_tx_seq; 1982 si->rtp_seq_ts_set = call_med->rtp_tx_seq_ts_set; 1706 1983 1707 1984 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 … … 1711 1988 1712 1989 /* Create session based on session info. */ 1713 status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info, 1714 &call->med_tp, 1715 call, &call->session ); 1990 status = pjmedia_stream_create(pjsua_var.med_endpt, NULL, si, 1991 call_med->tp, NULL, 1992 &call_med->strm.a.stream); 1993 if (status != PJ_SUCCESS) { 1994 return status; 1995 } 1996 1997 /* Start stream */ 1998 status = pjmedia_stream_start(call_med->strm.a.stream); 1716 1999 if (status != PJ_SUCCESS) { 1717 2000 return status; … … 1722 2005 */ 1723 2006 if (pjsua_var.ua_cfg.cb.on_dtmf_digit) { 1724 pjmedia_s ession_set_dtmf_callback(call->session, 0,1725 &dtmf_callback,1726 2007 pjmedia_stream_set_dtmf_callback(call_med->strm.a.stream, 2008 &dtmf_callback, 2009 (void*)(long)(call->index)); 1727 2010 } 1728 2011 … … 1730 2013 * We need the port interface to add to the conference bridge. 1731 2014 */ 1732 pjmedia_s ession_get_port(call->session, 0, &media_port);2015 pjmedia_stream_get_port(call_med->strm.a.stream, &media_port); 1733 2016 1734 2017 /* Notify application about stream creation. … … 1737 2020 */ 1738 2021 if (pjsua_var.ua_cfg.cb.on_stream_created) { 1739 pjsua_var.ua_cfg.cb.on_stream_created(call_id, call->session, 1740 0, &media_port); 2022 pjsua_var.ua_cfg.cb.on_stream_created(call->index, 2023 call_med->strm.a.stream, 2024 strm_idx, &media_port); 1741 2025 } 1742 2026 … … 1759 2043 media_port, 1760 2044 &port_name, 1761 (unsigned*)&call->conf_slot); 2045 (unsigned*) 2046 &call_med->strm.a.conf_slot); 1762 2047 if (status != PJ_SUCCESS) { 1763 2048 return status; … … 1766 2051 1767 2052 /* Call media direction */ 1768 call ->media_dir = si->dir;2053 call_med->dir = si->dir; 1769 2054 1770 2055 /* Call media state */ 1771 2056 if (call->local_hold) 1772 call ->media_st= PJSUA_CALL_MEDIA_LOCAL_HOLD;1773 else if (call ->media_dir == PJMEDIA_DIR_DECODING)1774 call ->media_st= PJSUA_CALL_MEDIA_REMOTE_HOLD;2057 call_med->state = PJSUA_CALL_MEDIA_LOCAL_HOLD; 2058 else if (call_med->dir == PJMEDIA_DIR_DECODING) 2059 call_med->state = PJSUA_CALL_MEDIA_REMOTE_HOLD; 1775 2060 else 1776 call ->media_st= PJSUA_CALL_MEDIA_ACTIVE;2061 call_med->state = PJSUA_CALL_MEDIA_ACTIVE; 1777 2062 } 1778 2063 … … 1781 2066 char info[80]; 1782 2067 int info_len = 0; 1783 unsigned i; 1784 1785 for (i=0; i<sess_info.stream_cnt; ++i) { 1786 int len; 1787 const char *dir; 1788 pjmedia_stream_info *strm_info = &sess_info.stream_info[i]; 1789 1790 switch (strm_info->dir) { 1791 case PJMEDIA_DIR_NONE: 1792 dir = "inactive"; 1793 break; 1794 case PJMEDIA_DIR_ENCODING: 1795 dir = "sendonly"; 1796 break; 1797 case PJMEDIA_DIR_DECODING: 1798 dir = "recvonly"; 1799 break; 1800 case PJMEDIA_DIR_ENCODING_DECODING: 1801 dir = "sendrecv"; 1802 break; 1803 default: 1804 dir = "unknown"; 1805 break; 2068 int len; 2069 const char *dir; 2070 2071 switch (si->dir) { 2072 case PJMEDIA_DIR_NONE: 2073 dir = "inactive"; 2074 break; 2075 case PJMEDIA_DIR_ENCODING: 2076 dir = "sendonly"; 2077 break; 2078 case PJMEDIA_DIR_DECODING: 2079 dir = "recvonly"; 2080 break; 2081 case PJMEDIA_DIR_ENCODING_DECODING: 2082 dir = "sendrecv"; 2083 break; 2084 default: 2085 dir = "unknown"; 2086 break; 2087 } 2088 len = pj_ansi_sprintf( info+info_len, 2089 ", stream #%d: %.*s (%s)", strm_idx, 2090 (int)si->fmt.encoding_name.slen, 2091 si->fmt.encoding_name.ptr, 2092 dir); 2093 if (len > 0) 2094 info_len += len; 2095 PJ_LOG(4,(THIS_FILE,"Media updates%s", info)); 2096 } 2097 2098 return PJ_SUCCESS; 2099 } 2100 2101 pj_status_t pjsua_media_channel_update(pjsua_call_id call_id, 2102 const pjmedia_sdp_session *local_sdp, 2103 const pjmedia_sdp_session *remote_sdp) 2104 { 2105 pjsua_call *call = &pjsua_var.calls[call_id]; 2106 pj_pool_t *tmp_pool = call->inv->pool_prov; 2107 unsigned mi; 2108 pj_status_t status; 2109 2110 if (pjsua_get_state() != PJSUA_STATE_RUNNING) 2111 return PJ_EBUSY; 2112 2113 /* Destroy existing media session, if any. */ 2114 stop_media_session(call->index); 2115 2116 /* Reset audio_idx first */ 2117 call->audio_idx = -1; 2118 2119 /* Process each media stream */ 2120 for (mi=0; mi < call->med_cnt; ++mi) { 2121 pjsua_call_media *call_med = &call->media[mi]; 2122 2123 if (mi > local_sdp->media_count || 2124 mi > remote_sdp->media_count) 2125 { 2126 /* Something is wrong */ 2127 PJ_LOG(1,(THIS_FILE, "Error updating media for call %d: " 2128 "invalid media index %d in SDP", call_id, mi)); 2129 return PJMEDIA_SDP_EINSDP; 2130 } 2131 2132 switch (call_med->type) { 2133 case PJMEDIA_TYPE_AUDIO: 2134 status = audio_channel_update(call_med, tmp_pool, 2135 local_sdp, remote_sdp); 2136 if (call->audio_idx==-1 && status==PJ_SUCCESS && 2137 call_med->strm.a.stream) 2138 { 2139 call->audio_idx = mi; 1806 2140 } 1807 len = pj_ansi_sprintf( info+info_len, 1808 ", stream #%d: %.*s (%s)", i, 1809 (int)strm_info->fmt.encoding_name.slen, 1810 strm_info->fmt.encoding_name.ptr, 1811 dir); 1812 if (len > 0) 1813 info_len += len; 1814 } 1815 PJ_LOG(4,(THIS_FILE,"Media updates%s", info)); 2141 break; 2142 case PJMEDIA_TYPE_VIDEO: 2143 PJ_LOG(4,(THIS_FILE, "-x-x-x-x- Updating video for stream %d", mi)); 2144 break; 2145 default: 2146 break; 2147 } 2148 2149 if (status != PJ_SUCCESS) { 2150 PJ_PERROR(1,(THIS_FILE, status, "Error updating media call%02:%d", 2151 call_id, mi)); 2152 } 1816 2153 } 1817 2154
Note: See TracChangeset
for help on using the changeset viewer.