Changeset 6005
- Timestamp:
- May 26, 2019 1:18:02 PM (6 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/config.h
r5915 r6005 1223 1223 1224 1224 1225 /** 1226 * Specify the number of identical consecutive error that will be ignored when 1227 * receiving RTP/RTCP data before the library tries to restart the transport. 1228 * 1229 * When receiving RTP/RTCP data, the library will ignore error besides 1230 * PJ_EPENDING or PJ_ECANCELLED and continue the loop to receive the data. 1231 * If the OS always return error, then the loop will continue non stop. 1232 * This setting will limit the number of the identical consecutive error, 1233 * before the library start to restart the transport. If error still happens 1234 * after transport restart, then PJMEDIA_EVENT_MEDIA_TP_ERR event will be 1235 * publish as a notification. 1236 * 1237 * If PJ_ESOCKETSTOP is raised, then transport will be restarted regardless 1238 * of this setting. 1239 * 1240 * To always ignore the error when receving RTP/RTCP, set this to 0. 1241 * 1242 * Default : 20 1243 */ 1244 #ifndef PJMEDIA_IGNORE_RECV_ERR_CNT 1245 # define PJMEDIA_IGNORE_RECV_ERR_CNT 20 1246 #endif 1247 1248 1225 1249 /* 1226 1250 * .... new stuffs ... -
pjproject/trunk/pjmedia/include/pjmedia/event.h
r5923 r6005 94 94 * Audio device stopped on error. 95 95 */ 96 PJMEDIA_EVENT_AUD_DEV_ERROR = PJMEDIA_FOURCC('A', 'E', 'R', 'R') 96 PJMEDIA_EVENT_AUD_DEV_ERROR = PJMEDIA_FOURCC('A', 'E', 'R', 'R'), 97 98 /** 99 * Transport media error. 100 */ 101 PJMEDIA_EVENT_MEDIA_TP_ERR = PJMEDIA_FOURCC('T', 'E', 'R', 'R') 97 102 98 103 } pjmedia_event_type; … … 155 160 pj_status_t status; 156 161 } pjmedia_event_aud_dev_err_data; 162 163 /** 164 * Additional data/parameters for media transmit error event. 165 */ 166 typedef struct pjmedia_event_media_tp_err_data 167 { 168 /** The media type */ 169 pjmedia_type type; 170 171 /** RTP/RTCP? */ 172 pj_bool_t is_rtp; 173 174 /** Media direction */ 175 pjmedia_dir dir; 176 177 /** The error code */ 178 pj_status_t status; 179 180 } pjmedia_event_media_tp_err_data; 181 157 182 158 183 /** Additional parameters for window changed event. */ … … 243 268 /** Storage for user event data */ 244 269 pjmedia_event_user_data user; 270 271 /** Media transport error event data */ 272 pjmedia_event_media_tp_err_data med_tp_err; 245 273 246 274 /** Pointer to storage to user event data, if it's outside -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r5982 r6005 75 75 /* Number of DTMF E bit transmissions */ 76 76 #define DTMF_EBIT_RETRANSMIT_CNT 3 77 78 /* Number of send error before repeat the report. */ 79 #define SEND_ERR_COUNT_TO_REPORT 50 77 80 78 81 /** … … 234 237 pj_sockaddr rem_rtp_addr; /**< Remote RTP address */ 235 238 unsigned rem_rtp_flag; /**< Indicator flag about 236 packet from this addr. 237 0=no pkt, 1=good ssrc, 239 packet from this addr. 240 0=no pkt, 1=good ssrc, 238 241 2=bad ssrc pkts */ 239 242 unsigned rtp_src_cnt; /**< How many pkt from … … 245 248 #endif 246 249 247 pj_uint32_t rtp_rx_last_ts; /**< Last received RTP timestamp*/ 248 pj_status_t rtp_rx_last_err; /**< Last RTP recv() error */ 249 pj_status_t rtp_tx_last_err; /**< Last RTP send() error */ 250 pj_status_t rtcp_tx_last_err; /**< Last RTCP send() error */ 250 pj_uint32_t rtp_rx_last_ts; /**< Last received RTP 251 timestamp */ 252 pj_uint32_t rtp_tx_err_cnt; /**< The number of RTP 253 send() error */ 254 pj_uint32_t rtcp_tx_err_cnt; /**< The number of RTCP 255 send() error */ 251 256 252 257 /* RTCP Feedback */ … … 263 268 '4', '5', '6', '7', 264 269 '8', '9', '*', '#', 265 'A', 'B', 'C', 'D', 270 'A', 'B', 'C', 'D', 266 271 'R'}; 267 272 … … 462 467 /* Send RTCP */ 463 468 send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 464 469 465 470 /* Update stats in case the stream is paused */ 466 471 stream->rtcp.stat.rtp_tx_last_seq = pj_ntohs(stream->enc->rtp.out_hdr.seq); … … 538 543 stream->dec_buf_pos; 539 544 unsigned nsamples_copy = PJ_MIN(nsamples_req, nsamples_avail); 540 545 541 546 pjmedia_copy_samples(p_out_samp + samples_count, 542 547 stream->dec_buf + stream->dec_buf_pos, … … 1013 1018 1014 1019 1020 /** 1021 * Publish transport error event. 1022 */ 1023 static void publish_tp_event(pjmedia_event_type event_type, 1024 pj_status_t status, 1025 pj_bool_t is_rtp, 1026 pjmedia_dir dir, 1027 pjmedia_stream *stream) 1028 { 1029 pjmedia_event ev; 1030 pj_timestamp ts_now; 1031 1032 pj_get_timestamp(&ts_now); 1033 pj_bzero(&ev.data.med_tp_err, sizeof(ev.data.med_tp_err)); 1034 1035 /* Publish event. */ 1036 pjmedia_event_init(&ev, event_type, 1037 &ts_now, stream); 1038 ev.data.med_tp_err.type = PJMEDIA_TYPE_AUDIO; 1039 ev.data.med_tp_err.is_rtp = is_rtp; 1040 ev.data.med_tp_err.dir = dir; 1041 ev.data.med_tp_err.status = status; 1042 1043 pjmedia_event_publish(NULL, stream, &ev, 0); 1044 } 1045 1046 1015 1047 static pj_status_t send_rtcp(pjmedia_stream *stream, 1016 1048 pj_bool_t with_sdes, … … 1134 1166 status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); 1135 1167 if (status != PJ_SUCCESS) { 1136 if (stream->rtcp_tx_last_err != status) { 1137 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1138 "Error sending RTCP")); 1139 stream->rtcp_tx_last_err = status; 1140 } 1141 } else { 1142 if (stream->rtcp_tx_last_err != PJ_SUCCESS) { 1143 PJ_LOG(4,(stream->port.info.name.ptr, "Sending RTCP resumed")); 1144 stream->rtcp_tx_last_err = PJ_SUCCESS; 1168 if (stream->rtcp_tx_err_cnt++ == 0) { 1169 LOGERR_((stream->port.info.name.ptr, status, 1170 "Error sending RTCP")); 1171 } 1172 if (stream->rtcp_tx_err_cnt > SEND_ERR_COUNT_TO_REPORT) { 1173 stream->rtcp_tx_err_cnt = 0; 1145 1174 } 1146 1175 } … … 1484 1513 frame_out.size + 1485 1514 sizeof(pjmedia_rtp_hdr)); 1515 1486 1516 if (status != PJ_SUCCESS) { 1487 if (stream->rtp_tx_last_err != status) { 1488 PJ_PERROR(4,(stream->port.info.name.ptr, status, 1489 "Error sending RTP")); 1490 stream->rtp_tx_last_err = status; 1517 if (stream->rtp_tx_err_cnt++ == 0) { 1518 LOGERR_((stream->port.info.name.ptr, status, "Error sending RTP")); 1519 } 1520 if (stream->rtp_tx_err_cnt > SEND_ERR_COUNT_TO_REPORT) { 1521 stream->rtp_tx_err_cnt = 0; 1491 1522 } 1492 1523 return PJ_SUCCESS; 1493 } else {1494 if (stream->rtp_tx_last_err != PJ_SUCCESS) {1495 PJ_LOG(4,(stream->port.info.name.ptr, "Sending RTP resumed"));1496 stream->rtp_tx_last_err = PJ_SUCCESS;1497 }1498 1524 } 1499 1525 … … 1680 1706 #else 1681 1707 if (event->event > 15) { 1682 #endif 1708 #endif 1683 1709 PJ_LOG(5,(stream->port.info.name.ptr, 1684 1710 "Ignored RTP pkt with bad DTMF event %d", … … 1744 1770 return; 1745 1771 } 1746 if (stream->rtp_rx_last_err != status) { 1747 char errmsg[PJ_ERR_MSG_SIZE]; 1748 pj_strerror(status, errmsg, sizeof(errmsg)); 1749 PJ_LOG(4,(stream->port.info.name.ptr, 1750 "Unable to receive RTP packet, recv() returned %d: %s", 1751 status, errmsg)); 1752 stream->rtp_rx_last_err = status; 1772 1773 LOGERR_((stream->port.info.name.ptr, status, 1774 "Unable to receive RTP packet")); 1775 1776 if (status == PJ_ESOCKETSTOP) { 1777 /* Publish receive error event. */ 1778 publish_tp_event(PJMEDIA_EVENT_MEDIA_TP_ERR, status, PJ_TRUE, 1779 PJMEDIA_DIR_DECODING, stream); 1753 1780 } 1754 1781 return; 1755 } else {1756 stream->rtp_rx_last_err = PJ_SUCCESS;1757 1782 } 1758 1783 … … 1769 1794 return; 1770 1795 } 1771 1796 1772 1797 /* Check if multiplexing is allowed and the payload indicates RTCP. */ 1773 1798 if (stream->si.rtcp_mux && hdr->pt >= 64 && hdr->pt <= 95) { … … 1838 1863 } 1839 1864 1840 /* See if source address of RTP packet is different than the 1865 /* See if source address of RTP packet is different than the 1841 1866 * configured address, and check if we need to tell the 1842 1867 * media transport to switch RTP remote address. … … 1852 1877 } else { 1853 1878 stream->rtp_src_cnt++; 1854 1879 1855 1880 if (stream->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 1856 1881 if (stream->rem_rtp_flag == 1 || … … 1865 1890 pkt_discarded = PJ_TRUE; 1866 1891 goto on_return; 1867 } 1892 } 1868 1893 if (stream->si.has_rem_ssrc && !seq_st.status.flag.badssrc && 1869 1894 stream->rem_rtp_flag != 1) … … 1927 1952 { 1928 1953 unsigned dec_ptime; 1929 1954 1930 1955 PJ_LOG(4, (stream->port.info.name.ptr, "codec decode " 1931 1956 "ptime change detected")); … … 2106 2131 { 2107 2132 pjmedia_stream *stream = (pjmedia_stream*) data; 2133 pj_status_t status; 2108 2134 2109 2135 /* Check for errors */ 2110 2136 if (bytes_read < 0) { 2111 if (bytes_read != -PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) { 2112 LOGERR_((stream->port.info.name.ptr, (pj_status_t)-bytes_read, 2113 "RTCP recv() error")); 2137 status = (pj_status_t)-bytes_read; 2138 if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) { 2139 return; 2140 } 2141 LOGERR_((stream->port.info.name.ptr, status, 2142 "Unable to receive RTCP packet")); 2143 2144 if (status == PJ_ESOCKETSTOP) { 2145 /* Publish receive error event. */ 2146 publish_tp_event(PJMEDIA_EVENT_MEDIA_TP_ERR, status, PJ_FALSE, 2147 PJMEDIA_DIR_DECODING, stream); 2114 2148 } 2115 2149 return; … … 2220 2254 if (stream->rtcp_fb_nack_cap_idx < 0) 2221 2255 return PJ_SUCCESS; 2222 2256 2223 2257 data->cap = stream->si.loc_rtcp_fb.caps[stream->rtcp_fb_nack_cap_idx]; 2224 2258 } … … 2636 2670 pj_sockaddr_cp(&stream->rem_rtp_addr, &info->rem_addr); 2637 2671 if (stream->si.rtcp_mux) { 2638 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_addr); 2672 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_addr); 2639 2673 } else if (pj_sockaddr_has_addr(&info->rem_rtcp.addr)) { 2640 2674 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp); … … 3128 3162 pt = 11; 3129 3163 } 3130 #if defined(PJMEDIA_HAS_DTMF_FLASH) && PJMEDIA_HAS_DTMF_FLASH!= 0 3164 #if defined(PJMEDIA_HAS_DTMF_FLASH) && PJMEDIA_HAS_DTMF_FLASH!= 0 3131 3165 else if (dig == 'r') 3132 3166 { -
pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
r5907 r6005 19 19 */ 20 20 #include <pjmedia/transport_udp.h> 21 #include <pj/compat/socket.h> 21 22 #include <pj/addr_resolv.h> 22 23 #include <pj/assert.h> … … 27 28 #include <pj/rand.h> 28 29 #include <pj/string.h> 29 30 30 31 31 /* Maximum size of incoming RTP packet */ … … 155 155 unsigned pct_lost); 156 156 static pj_status_t transport_destroy (pjmedia_transport *tp); 157 158 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \159 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0160 157 static pj_status_t transport_restart (pj_bool_t is_rtp, 161 158 struct transport_udp *udp); 162 #endif163 159 164 160 static pjmedia_transport_op transport_udp_op = … … 454 450 } 455 451 452 /* Call RTP cb. */ 453 static void call_rtp_cb(struct transport_udp *udp, pj_ssize_t bytes_read, 454 pj_bool_t *rem_switch) 455 { 456 void (*cb)(void*,void*,pj_ssize_t); 457 void (*cb2)(pjmedia_tp_cb_param*); 458 void *user_data; 459 460 cb = udp->rtp_cb; 461 cb2 = udp->rtp_cb2; 462 user_data = udp->user_data; 463 464 if (cb2) { 465 pjmedia_tp_cb_param param; 466 467 param.user_data = user_data; 468 param.pkt = udp->rtp_pkt; 469 param.size = bytes_read; 470 param.src_addr = &udp->rtp_src_addr; 471 param.rem_switch = PJ_FALSE; 472 (*cb2)(¶m); 473 if (rem_switch) 474 *rem_switch = param.rem_switch; 475 } else if (cb) { 476 (*cb)(user_data, udp->rtp_pkt, bytes_read); 477 } 478 } 479 480 /* Call RTCP cb. */ 481 static void call_rtcp_cb(struct transport_udp *udp, pj_ssize_t bytes_read) 482 { 483 void(*cb)(void*, void*, pj_ssize_t); 484 void *user_data; 485 486 cb = udp->rtcp_cb; 487 user_data = udp->user_data; 488 489 if (cb) 490 (*cb)(user_data, udp->rtcp_pkt, bytes_read); 491 } 456 492 457 493 /* Notification from ioqueue about incoming RTP packet */ … … 463 499 pj_status_t status; 464 500 pj_bool_t rem_switch = PJ_FALSE; 501 pj_bool_t transport_restarted = PJ_FALSE; 502 unsigned num_err = 0; 503 pj_status_t last_err = PJ_SUCCESS; 465 504 466 505 PJ_UNUSED_ARG(op_key); … … 470 509 udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 471 510 472 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \473 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0474 511 if (-bytes_read == PJ_ESOCKETSTOP) { 475 512 /* Try to recover by restarting the transport. */ 476 PJ_LOG(4, (udp->base.name, "Restarting RTP transport"));477 513 status = transport_restart(PJ_TRUE, udp); 478 if (status == PJ_SUCCESS) { 479 PJ_LOG(4, (udp->base.name, "Success restarting RTP transport")); 480 } else { 481 PJ_PERROR(1, (udp->base.name, status, 482 "Error restarting RTP transport")); 514 if (status != PJ_SUCCESS) { 515 bytes_read = -PJ_ESOCKETSTOP; 516 call_rtp_cb(udp, bytes_read, NULL); 483 517 } 484 518 return; 485 519 } 486 #endif487 520 488 521 do { 489 void (*cb)(void*,void*,pj_ssize_t);490 void (*cb2)(pjmedia_tp_cb_param*);491 void *user_data;492 522 pj_bool_t discard = PJ_FALSE; 493 494 cb = udp->rtp_cb;495 cb2 = udp->rtp_cb2;496 user_data = udp->user_data;497 523 498 524 /* Simulate packet lost on RX direction */ … … 507 533 508 534 //if (!discard && udp->attached && cb) 509 if (!discard) { 510 if (cb2) { 511 pjmedia_tp_cb_param param; 512 513 param.user_data = user_data; 514 param.pkt = udp->rtp_pkt; 515 param.size = bytes_read; 516 param.src_addr = &udp->rtp_src_addr; 517 param.rem_switch = PJ_FALSE; 518 (*cb2)(¶m); 519 rem_switch = param.rem_switch; 520 } else if (cb) { 521 (*cb)(user_data, udp->rtp_pkt, bytes_read); 522 } 535 if (!discard && 536 (-bytes_read != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL))) 537 { 538 call_rtp_cb(udp, bytes_read, &rem_switch); 523 539 } 524 540 … … 566 582 udp->rtp_addrlen = sizeof(udp->rtp_src_addr); 567 583 status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op, 568 udp->rtp_pkt, &bytes_read, 0, 569 &udp->rtp_src_addr, 570 &udp->rtp_addrlen); 571 572 if (status != PJ_EPENDING && status != PJ_SUCCESS) 584 udp->rtp_pkt, &bytes_read, 0, 585 &udp->rtp_src_addr, 586 &udp->rtp_addrlen); 587 588 if (status != PJ_EPENDING && status != PJ_SUCCESS) { 589 if (transport_restarted && last_err == status) { 590 /* Still the same error after restart */ 591 bytes_read = -PJ_ESOCKETSTOP; 592 call_rtp_cb(udp, bytes_read, NULL); 593 break; 594 } else if (PJMEDIA_IGNORE_RECV_ERR_CNT) { 595 if (last_err == status) { 596 ++num_err; 597 } else { 598 num_err = 1; 599 last_err = status; 600 } 601 602 if (status == PJ_ESOCKETSTOP || 603 num_err > PJMEDIA_IGNORE_RECV_ERR_CNT) 604 { 605 status = transport_restart(PJ_TRUE, udp); 606 if (status != PJ_SUCCESS) { 607 bytes_read = -PJ_ESOCKETSTOP; 608 call_rtp_cb(udp, bytes_read, NULL); 609 break; 610 } 611 transport_restarted = PJ_TRUE; 612 num_err = 0; 613 } 614 } 573 615 bytes_read = -status; 574 616 } 575 617 } while (status != PJ_EPENDING && status != PJ_ECANCELLED && 576 618 udp->started); … … 585 627 struct transport_udp *udp; 586 628 pj_status_t status = PJ_SUCCESS; 629 pj_bool_t transport_restarted = PJ_FALSE; 630 unsigned num_err = 0; 631 pj_status_t last_err = PJ_SUCCESS; 587 632 588 633 PJ_UNUSED_ARG(op_key); … … 592 637 udp = (struct transport_udp*) pj_ioqueue_get_user_data(key); 593 638 594 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \595 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0596 639 if (-bytes_read == PJ_ESOCKETSTOP) { 597 640 /* Try to recover by restarting the transport. */ 598 PJ_LOG(4, (udp->base.name, "Restarting RTCP transport"));599 641 status = transport_restart(PJ_FALSE, udp); 600 if (status == PJ_SUCCESS) { 601 PJ_LOG(4, (udp->base.name, "Success restarting RTCP transport")); 602 } else { 603 PJ_PERROR(1, (udp->base.name, status, 604 "Error restarting RTCP transport")); 642 if (status != PJ_SUCCESS) { 643 bytes_read = -PJ_ESOCKETSTOP; 644 call_rtcp_cb(udp, bytes_read); 605 645 } 606 646 return; 607 647 } 608 #endif609 648 610 649 do { 611 void (*cb)(void*,void*,pj_ssize_t); 612 void *user_data; 613 614 cb = udp->rtcp_cb; 615 user_data = udp->user_data; 616 617 //if (udp->attached && cb) 618 if (cb) 619 (*cb)(user_data, udp->rtcp_pkt, bytes_read); 650 call_rtcp_cb(udp, bytes_read); 620 651 621 652 #if defined(PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR) && \ … … 656 687 &udp->rtcp_src_addr, 657 688 &udp->rtcp_addr_len); 658 if (status != PJ_EPENDING && status != PJ_SUCCESS) 689 690 if (status != PJ_EPENDING && status != PJ_SUCCESS) { 691 if (transport_restarted && last_err == status) { 692 /* Still the same error after restart */ 693 bytes_read = -PJ_ESOCKETSTOP; 694 call_rtcp_cb(udp, bytes_read); 695 break; 696 } else if (PJMEDIA_IGNORE_RECV_ERR_CNT) { 697 if (last_err == status) { 698 ++num_err; 699 } else { 700 num_err = 1; 701 last_err = status; 702 } 703 704 if (status == PJ_ESOCKETSTOP || 705 num_err > PJMEDIA_IGNORE_RECV_ERR_CNT) 706 { 707 status = transport_restart(PJ_FALSE, udp); 708 if (status != PJ_SUCCESS) { 709 bytes_read = -PJ_ESOCKETSTOP; 710 call_rtcp_cb(udp, bytes_read); 711 break; 712 } 713 transport_restarted = PJ_TRUE; 714 num_err = 0; 715 } 716 } 659 717 bytes_read = -status; 660 718 } 661 719 } while (status != PJ_EPENDING && status != PJ_ECANCELLED && 662 720 udp->started); … … 928 986 PJ_ASSERT_RETURN(size <= PJMEDIA_MAX_MTU, PJ_ETOOBIG); 929 987 988 if (!udp->started) { 989 return PJ_SUCCESS; 990 } 991 930 992 /* Simulate packet lost on TX direction */ 931 993 if (udp->tx_drop_pct) { … … 985 1047 986 1048 //PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP); 1049 1050 if (!udp->started) { 1051 return PJ_SUCCESS; 1052 } 987 1053 988 1054 if (addr == NULL) { … … 1181 1247 } 1182 1248 1183 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 1184 PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 1185 static pj_status_t transport_restart(pj_bool_t is_rtp, 1249 static pj_status_t transport_restart(pj_bool_t is_rtp, 1186 1250 struct transport_udp *udp) 1187 1251 { … … 1194 1258 pj_ssize_t size; 1195 1259 1260 PJ_LOG(4, (udp->base.name, "Restarting %s transport", 1261 (is_rtp)?"RTP":"RTCP")); 1262 1263 udp->started = PJ_FALSE; 1196 1264 /* Destroy existing socket, if any. */ 1197 1265 if (key) { … … 1208 1276 pj_sock_close(*sock); 1209 1277 } 1210 *sock = PJ_INVALID_SOCKET; 1278 *sock = PJ_INVALID_SOCKET; 1211 1279 1212 1280 /* Create socket */ … … 1224 1292 /* Set buffer size for RTP socket */ 1225 1293 #if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE 1226 {1294 if (is_rtp) { 1227 1295 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE; 1228 1296 1229 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(), 1230 PJ_TRUE, &sobuf_size); 1231 if (status != PJ_SUCCESS) { 1232 pj_perror(3, udp->base.name, status, "Failed setting SO_RCVBUF"); 1233 } else { 1234 if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) { 1235 PJ_LOG(4, (udp->base.name, 1236 "Warning! Cannot set SO_RCVBUF as configured, " 1237 "now=%d, configured=%d", 1238 sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE)); 1239 } else { 1240 PJ_LOG(5, (udp->base.name, "SO_RCVBUF set to %d", sobuf_size)); 1241 } 1242 } 1297 pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(), 1298 PJ_TRUE, &sobuf_size); 1243 1299 } 1244 1300 #endif 1245 1301 #if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE 1246 {1302 if (is_rtp) { 1247 1303 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE; 1248 1304 1249 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(), 1250 PJ_TRUE, &sobuf_size); 1251 if (status != PJ_SUCCESS) { 1252 pj_perror(3, udp->base.name, status, "Failed setting SO_SNDBUF"); 1253 } else { 1254 if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) { 1255 PJ_LOG(4, (udp->base.name, 1256 "Warning! Cannot set SO_SNDBUF as configured, " 1257 "now=%d, configured=%d", 1258 sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE)); 1259 } else { 1260 PJ_LOG(5, (udp->base.name, "SO_SNDBUF set to %d", sobuf_size)); 1261 } 1262 } 1305 pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(), 1306 PJ_TRUE, &sobuf_size); 1263 1307 } 1264 1308 #endif … … 1296 1340 goto on_error; 1297 1341 1298 1342 udp->started = PJ_TRUE; 1343 PJ_LOG(4, (udp->base.name, "Success restarting %s transport", 1344 (is_rtp)?"RTP":"RTCP")); 1299 1345 return PJ_SUCCESS; 1300 1346 on_error: … … 1303 1349 *sock = PJ_INVALID_SOCKET; 1304 1350 } 1351 PJ_PERROR(1, (udp->base.name, status, 1352 "Error restarting %s transport", (is_rtp)?"RTP":"RTCP")); 1305 1353 return status; 1306 1354 } 1307 #endif -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
r5982 r6005 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) 4 4 * … … 15 15 * You should have received a copy of the GNU General Public License 16 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 19 #include <pjmedia/vid_stream.h> … … 75 75 #define MIN_CHUNKS_PER_FRM 30 76 76 77 /* Number of send error before repeat the report. */ 78 #define SEND_ERR_COUNT_TO_REPORT 50 77 79 78 80 /** … … 115 117 116 118 pjmedia_transport *transport; /**< Stream transport. */ 117 unsigned send_err_cnt; /**< Send error count. */118 119 119 120 pj_mutex_t *jb_mutex; … … 137 138 pjmedia_event fmt_event; /**< Buffered fmt_changed event 138 139 to avoid deadlock */ 139 pjmedia_event miss_keyframe_event; 140 pjmedia_event miss_keyframe_event; 140 141 /**< Buffered missing keyframe 141 142 event for delayed republish*/ … … 148 149 frame assembly. */ 149 150 pj_bool_t force_keyframe;/**< Forced to encode keyframe? */ 150 unsigned num_keyframe; /**< The number of keyframe needed 151 unsigned num_keyframe; /**< The number of keyframe needed 151 152 to be sent, after the stream 152 153 is created. */ 153 pj_timestamp last_keyframe_tx; 154 /**< Timestamp of the last 154 pj_timestamp last_keyframe_tx; 155 /**< Timestamp of the last 155 156 keyframe. */ 156 157 … … 172 173 pj_uint32_t last_dec_ts; /**< Last decoded timestamp. */ 173 174 int last_dec_seq; /**< Last decoded sequence. */ 174 pj_status_t rtp_rx_last_err; /**< Last RTP recv() error. */ 175 pj_uint32_t rtp_tx_err_cnt;/**< The number of RTP 176 send() error */ 177 pj_uint32_t rtcp_tx_err_cnt;/**< The number of RTCP 178 send() error */ 175 179 176 180 pj_timestamp ts_freq; /**< Timestamp frequency. */ … … 178 182 pj_sockaddr rem_rtp_addr; /**< Remote RTP address */ 179 183 unsigned rem_rtp_flag; /**< Indicator flag about 180 packet from this addr. 181 0=no pkt, 1=good ssrc pkts, 184 packet from this addr. 185 0=no pkt, 1=good ssrc pkts, 182 186 2=bad ssrc pkts */ 183 187 pj_sockaddr rtp_src_addr; /**< Actual packet src addr. */ … … 203 207 204 208 static void on_rx_rtcp( void *data, 205 void *pkt, 209 void *pkt, 206 210 pj_ssize_t bytes_read); 207 211 … … 233 237 } 234 238 235 PJ_INLINE(int) trace_jb_print_state(pjmedia_vid_stream *stream, 239 PJ_INLINE(int) trace_jb_print_state(pjmedia_vid_stream *stream, 236 240 char **buf, pj_ssize_t len) 237 241 { … … 405 409 } 406 410 411 /** 412 * Publish transport error event. 413 */ 414 static void publish_tp_event(pjmedia_event_type event_type, 415 pj_status_t status, 416 pj_bool_t is_rtp, 417 pjmedia_dir dir, 418 pjmedia_vid_stream *stream) 419 { 420 pjmedia_event ev; 421 pj_timestamp ts_now; 422 423 pj_get_timestamp(&ts_now); 424 pj_bzero(&ev.data.med_tp_err, sizeof(ev.data.med_tp_err)); 425 426 /* Publish event. */ 427 pjmedia_event_init(&ev, event_type, 428 &ts_now, stream); 429 ev.data.med_tp_err.type = PJMEDIA_TYPE_VIDEO; 430 ev.data.med_tp_err.is_rtp = is_rtp; 431 ev.data.med_tp_err.dir = dir; 432 ev.data.med_tp_err.status = status; 433 434 pjmedia_event_publish(NULL, stream, &ev, 0); 435 } 436 407 437 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 408 438 /* … … 462 492 463 493 #else 464 494 465 495 PJ_UNUSED_ARG(stream); 466 496 … … 478 508 int len, max_len; 479 509 pj_status_t status; 510 pjmedia_vid_channel *channel = stream->enc; 480 511 481 512 /* Build RTCP RR/SR packet */ … … 526 557 /* Send! */ 527 558 status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); 528 559 if (status != PJ_SUCCESS) { 560 if (stream->rtcp_tx_err_cnt++ == 0) { 561 LOGERR_((channel->port.info.name.ptr, status, 562 "Error sending RTCP")); 563 } 564 if (stream->rtcp_tx_err_cnt > SEND_ERR_COUNT_TO_REPORT) { 565 stream->rtcp_tx_err_cnt = 0; 566 } 567 } 529 568 return status; 530 569 } … … 539 578 static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp) 540 579 { 541 /* Note that timestamp may represent local or remote timestamp, 580 /* Note that timestamp may represent local or remote timestamp, 542 581 * depending on whether this function is called from put_frame() 543 582 * or get_frame(). … … 546 585 547 586 if (stream->rtcp_last_tx == 0) { 548 587 549 588 stream->rtcp_last_tx = timestamp; 550 589 551 590 } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { 552 591 pj_status_t status; 553 592 554 593 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE); 555 594 if (status != PJ_SUCCESS) { … … 591 630 /* 592 631 * This callback is called by stream transport on receipt of packets 593 * in the RTP socket. 632 * in the RTP socket. 594 633 */ 595 634 static void on_rx_rtp( pjmedia_tp_cb_param *param) … … 612 651 return; 613 652 } 614 if (stream->rtp_rx_last_err != status) { 615 char errmsg[PJ_ERR_MSG_SIZE]; 616 pj_strerror(status, errmsg, sizeof(errmsg)); 617 PJ_LOG(4,(channel->port.info.name.ptr, 618 "Unable to receive RTP packet, recv() returned %d: %s", 619 status, errmsg)); 620 stream->rtp_rx_last_err = status; 653 654 LOGERR_((channel->port.info.name.ptr, status, 655 "Unable to receive RTP packet")); 656 657 if (status == PJ_ESOCKETSTOP) { 658 /* Publish receive error event. */ 659 publish_tp_event(PJMEDIA_EVENT_MEDIA_TP_ERR, status, PJ_TRUE, 660 PJMEDIA_DIR_DECODING, stream); 621 661 } 622 662 return; 623 } else {624 stream->rtp_rx_last_err = PJ_SUCCESS;625 663 } 626 664 … … 653 691 pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, PJ_TRUE); 654 692 if (seq_st.status.value) { 655 TRC_ ((channel->port.info.name.ptr, 693 TRC_ ((channel->port.info.name.ptr, 656 694 "RTP status: badpt=%d, badssrc=%d, dup=%d, " 657 "outorder=%d, probation=%d, restart=%d", 695 "outorder=%d, probation=%d, restart=%d", 658 696 seq_st.status.flag.badpt, 659 697 seq_st.status.flag.badssrc, … … 691 729 } 692 730 693 /* See if source address of RTP packet is different than the 731 /* See if source address of RTP packet is different than the 694 732 * configured address, and check if we need to tell the 695 733 * media transport to switch RTP remote address. … … 705 743 } else { 706 744 stream->rtp_src_cnt++; 707 745 708 746 if (stream->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) { 709 747 if (stream->rem_rtp_flag == 1 || … … 718 756 pkt_discarded = PJ_TRUE; 719 757 goto on_return; 720 } 758 } 721 759 if (stream->info.has_rem_ssrc && !seq_st.status.flag.badssrc 722 760 && stream->rem_rtp_flag != 1) … … 793 831 } else { 794 832 /* Just put the payload into jitter buffer */ 795 pjmedia_jbuf_put_frame3(stream->jb, payload, payloadlen, 0, 833 pjmedia_jbuf_put_frame3(stream->jb, payload, payloadlen, 0, 796 834 pj_ntohs(hdr->seq), pj_ntohl(hdr->ts), NULL); 797 835 … … 844 882 /* 845 883 * This callback is called by stream transport on receipt of packets 846 * in the RTCP socket. 884 * in the RTCP socket. 847 885 */ 848 886 static void on_rx_rtcp( void *data, 849 void *pkt, 887 void *pkt, 850 888 pj_ssize_t bytes_read) 851 889 { 852 890 pjmedia_vid_stream *stream = (pjmedia_vid_stream*) data; 891 pj_status_t status; 853 892 854 893 /* Check for errors */ 855 894 if (bytes_read < 0) { 856 if (bytes_read != -PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) { 857 LOGERR_((stream->cname.ptr, (pj_status_t)-bytes_read, 858 "RTCP recv() error")); 895 status = (pj_status_t)-bytes_read; 896 if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) { 897 return; 898 } 899 LOGERR_((stream->cname.ptr, status, "Unable to receive RTCP packet")); 900 if (status == PJ_ESOCKETSTOP) { 901 /* Publish receive error event. */ 902 publish_tp_event(PJMEDIA_EVENT_MEDIA_TP_ERR, status, PJ_FALSE, 903 PJMEDIA_DIR_DECODING, stream); 859 904 } 860 905 return; … … 889 934 pj_uint32_t dtx_duration; 890 935 891 dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent, 936 dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent, 892 937 &frame->timestamp); 893 938 … … 922 967 923 968 /* Check if need to send keyframe. */ 924 if (stream->num_keyframe && 925 (pj_cmp_timestamp(&null_ts, &stream->last_keyframe_tx) != 0)) 926 { 969 if (stream->num_keyframe && 970 (pj_cmp_timestamp(&null_ts, &stream->last_keyframe_tx) != 0)) 971 { 927 972 unsigned elapse_time; 928 973 pj_timestamp now; … … 935 980 { 936 981 stream->force_keyframe = PJ_TRUE; 937 --stream->num_keyframe; 982 --stream->num_keyframe; 938 983 } 939 984 } … … 965 1010 return status; 966 1011 } 967 1012 968 1013 pj_get_timestamp(&initial_time); 969 1014 970 if ((stream->num_keyframe) && 971 ((frame_out.bit_info & PJMEDIA_VID_FRM_KEYFRAME) 972 == PJMEDIA_VID_FRM_KEYFRAME)) 1015 if ((stream->num_keyframe) && 1016 ((frame_out.bit_info & PJMEDIA_VID_FRM_KEYFRAME) 1017 == PJMEDIA_VID_FRM_KEYFRAME)) 973 1018 { 974 1019 stream->last_keyframe_tx = initial_time; … … 1003 1048 sizeof(pjmedia_rtp_hdr)); 1004 1049 if (status != PJ_SUCCESS) { 1005 enum { COUNT_TO_REPORT = 20 }; 1006 if (stream->send_err_cnt++ == 0) { 1050 if (stream->rtp_tx_err_cnt++ == 0) { 1007 1051 LOGERR_((channel->port.info.name.ptr, status, 1008 " Transport send_rtp() error"));1052 "Error sending RTP")); 1009 1053 } 1010 if (stream-> send_err_cnt > COUNT_TO_REPORT)1011 stream-> send_err_cnt = 0;1012 /* Ignore this error */1054 if (stream->rtp_tx_err_cnt > SEND_ERR_COUNT_TO_REPORT) { 1055 stream->rtp_tx_err_cnt = 0; 1056 } 1013 1057 } 1014 1015 1058 pjmedia_rtcp_tx_rtp(&stream->rtcp, (unsigned)frame_out.size); 1016 1059 total_sent += frame_out.size; … … 1082 1125 #endif 1083 1126 1084 /* Check if now is the time to transmit RTCP SR/RR report. 1127 /* Check if now is the time to transmit RTCP SR/RR report. 1085 1128 * We only do this when stream direction is not "decoding only", because 1086 1129 * when it is, check_tx_rtcp() will be handled by get_frame(). … … 1244 1287 1245 1288 ts_diff = frm_ts - stream->last_dec_ts; 1246 1289 1247 1290 /* Calculate new FPS based on RTP timestamp diff */ 1248 1291 if (stream->info.codec_info.clock_rate % ts_diff == 0) { … … 1273 1316 pjmedia_jbuf_get_state(stream->jb, &jb_state); 1274 1317 1275 stream->dec_delay_cnt = 1318 stream->dec_delay_cnt = 1276 1319 ((PJMEDIA_VID_STREAM_DECODE_MIN_DELAY_MSEC * 1277 1320 vfd->fps.num) + … … 1425 1468 char fourcc_name[5]; 1426 1469 pjmedia_port_info *pi; 1427 1470 1428 1471 pj_assert(info->type == PJMEDIA_TYPE_VIDEO); 1429 1472 pj_assert(dir == PJMEDIA_DIR_DECODING || dir == PJMEDIA_DIR_ENCODING); … … 1450 1493 channel->paused = 1; 1451 1494 channel->pt = pt; 1452 1495 1453 1496 /* Allocate buffer for outgoing packet. */ 1454 1497 if (dir == PJMEDIA_DIR_ENCODING) { … … 1553 1596 /* Init stream/port name */ 1554 1597 stream->name.ptr = (char*) pj_pool_alloc(pool, M); 1555 stream->name.slen = pj_ansi_snprintf(stream->name.ptr, M, 1598 stream->name.slen = pj_ansi_snprintf(stream->name.ptr, M, 1556 1599 "vstrm%p", stream); 1557 1600 1558 1601 /* Create and initialize codec: */ 1559 status = pjmedia_vid_codec_mgr_alloc_codec(stream->codec_mgr, 1602 status = pjmedia_vid_codec_mgr_alloc_codec(stream->codec_mgr, 1560 1603 &info->codec_info, 1561 1604 &stream->codec); … … 1567 1610 pjmedia_vid_codec_param def_param; 1568 1611 1569 status = pjmedia_vid_codec_mgr_get_default_param(stream->codec_mgr, 1612 status = pjmedia_vid_codec_mgr_get_default_param(stream->codec_mgr, 1570 1613 &info->codec_info, 1571 1614 &def_param); … … 1642 1685 stream->frame_size = vfd_enc->max_bps/8 * vfd_enc->fps.denum / 1643 1686 vfd_enc->fps.num; 1644 1687 1645 1688 /* As the maximum frame_size is not represented directly by maximum bps 1646 1689 * (which includes intra and predicted frames), let's increase the … … 1651 1694 1652 1695 /* Validate the frame size */ 1653 if (stream->frame_size == 0 || 1696 if (stream->frame_size == 0 || 1654 1697 stream->frame_size > PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE) 1655 1698 { … … 1686 1729 1687 1730 /* Create decoder channel */ 1688 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, 1731 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, 1689 1732 info->rx_pt, info, &stream->dec); 1690 1733 if (status != PJ_SUCCESS) … … 1692 1735 1693 1736 /* Create encoder channel */ 1694 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, 1737 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, 1695 1738 info->tx_pt, info, &stream->enc); 1696 1739 if (status != PJ_SUCCESS) … … 1793 1836 pj_sockaddr_cp(&stream->rem_rtp_addr, &info->rem_addr); 1794 1837 if (info->rtcp_mux) { 1795 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_addr); 1838 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_addr); 1796 1839 } else if (pj_sockaddr_has_addr(&info->rem_rtcp.addr)) { 1797 1840 pj_sockaddr_cp(&att_param.rem_rtcp, &info->rem_rtcp); 1798 } 1841 } 1799 1842 att_param.addr_len = pj_sockaddr_get_len(&info->rem_addr); 1800 1843 att_param.rtp_cb2 = &on_rx_rtp; … … 1824 1867 pj_ssize_t len; 1825 1868 1826 pj_ansi_snprintf(trace_name, sizeof(trace_name), 1869 pj_ansi_snprintf(trace_name, sizeof(trace_name), 1827 1870 TRACE_JB_PATH_PREFIX "%s.csv", 1828 1871 channel->port.info.name.ptr); … … 1832 1875 stream->trace_jb_fd = TRACE_JB_INVALID_FD; 1833 1876 PJ_PERROR(3,(THIS_FILE, status, 1834 "Failed creating RTP trace file '%s'", 1877 "Failed creating RTP trace file '%s'", 1835 1878 trace_name)); 1836 1879 } else { … … 1876 1919 1877 1920 total_time = pj_elapsed_msec(&stream->tx_start, &stream->tx_end); 1878 PJ_LOG(5, (stream->name.ptr, 1921 PJ_LOG(5, (stream->name.ptr, 1879 1922 "RC stat: pkt_cnt=%.2f/image, sleep=%.2fms/s, fps=%.2f", 1880 1923 stream->rc_total_pkt*1.0/stream->rc_total_img, … … 1889 1932 } 1890 1933 1891 /* Detach from transport 1934 /* Detach from transport 1892 1935 * MUST NOT hold stream mutex while detaching from transport, as 1893 1936 * it may cause deadlock. See ticket #460 for the details. … … 1913 1956 1914 1957 /* Free mutex */ 1915 1958 1916 1959 if (stream->jb_mutex) { 1917 1960 pj_mutex_destroy(stream->jb_mutex); -
pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
r5999 r6005 905 905 } 906 906 907 static char *get_media_dir(pjmedia_dir dir) { 908 switch (dir) { 909 case PJMEDIA_DIR_ENCODING: 910 return "TX"; 911 case PJMEDIA_DIR_DECODING: 912 return "RX"; 913 case PJMEDIA_DIR_ENCODING+PJMEDIA_DIR_DECODING: 914 return "TX+RX"; 915 default: 916 return "unknown dir"; 917 } 918 } 919 907 920 /* Callback on media events */ 908 921 static void on_call_media_event(pjsua_call_id call_id, … … 915 928 pjmedia_fourcc_name(event->type, event_name))); 916 929 930 if (event->type == PJMEDIA_EVENT_MEDIA_TP_ERR) { 931 pjmedia_event_media_tp_err_data *err_data; 932 933 err_data = &event->data.med_tp_err; 934 PJ_PERROR(3, (THIS_FILE, err_data->status, 935 "Media transport error event (%s %s %s)", 936 (err_data->type==PJMEDIA_TYPE_AUDIO)?"Audio":"Video", 937 (err_data->is_rtp)?"RTP":"RTCP", 938 get_media_dir(err_data->dir))); 939 } 917 940 #if PJSUA_HAS_VIDEO 918 if (event->type == PJMEDIA_EVENT_FMT_CHANGED) {941 else if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { 919 942 /* Adjust renderer window size to original video size */ 920 943 pjsua_call_info ci; … … 931 954 wid = ci.media[med_idx].stream.vid.win_in; 932 955 pjsua_vid_win_get_info(wid, &win_info); 933 956 934 957 size = event->data.fmt_changed.new_fmt.det.vid.size; 935 958 if (size.w != win_info.size.w || size.h != win_info.size.h) { … … 943 966 #else 944 967 PJ_UNUSED_ARG(call_id); 945 PJ_UNUSED_ARG(med_idx); 946 PJ_UNUSED_ARG(event); 968 PJ_UNUSED_ARG(med_idx); 947 969 #endif 948 970 }
Note: See TracChangeset
for help on using the changeset viewer.