Changeset 6106 for pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
- Timestamp:
- Nov 13, 2019 9:11:04 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c
r6098 r6106 20 20 #include <pjmedia/errno.h> 21 21 #include <pjmedia/event.h> 22 #include <pjmedia/jbuf.h> 22 23 #include <pjmedia/rtp.h> 23 24 #include <pjmedia/rtcp.h> 24 #include <pjmedia/ jbuf.h>25 #include <pjmedia/rtcp_fb.h> 25 26 #include <pj/array.h> 26 27 #include <pj/assert.h> … … 124 125 125 126 pjmedia_rtcp_session rtcp; /**< RTCP for incoming RTP. */ 126 pj_uint32_t rtcp_last_tx; /**< RTCP tx time in timestamp */ 127 pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */ 127 pj_timestamp rtcp_last_tx; /**< Last RTCP tx time. */ 128 pj_timestamp rtcp_fb_last_tx;/**< Last RTCP-FB tx time. */ 129 pj_uint32_t rtcp_interval; /**< Interval, in msec. */ 128 130 pj_bool_t initial_rr; /**< Initial RTCP RR sent */ 129 131 pj_bool_t rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/ … … 150 152 pj_bool_t force_keyframe;/**< Forced to encode keyframe? */ 151 153 unsigned num_keyframe; /**< The number of keyframe needed 152 to be sent, after the stream153 is created. */154 to be sent, e.g: after the 155 stream is created. */ 154 156 pj_timestamp last_keyframe_tx; 155 157 /**< Timestamp of the last … … 187 189 pj_sockaddr rtp_src_addr; /**< Actual packet src addr. */ 188 190 unsigned rtp_src_cnt; /**< How many pkt from this addr*/ 191 192 193 /* RTCP Feedback */ 194 pj_bool_t send_rtcp_fb_nack; /**< Send NACK? */ 195 int pending_rtcp_fb_nack; /**< Any pending NACK? */ 196 int rtcp_fb_nack_cap_idx; /**< RX NACK cap idx. */ 197 pjmedia_rtcp_fb_nack rtcp_fb_nack; /**< TX NACK state. */ 198 199 pj_bool_t send_rtcp_fb_pli; /**< Send PLI? */ 200 int pending_rtcp_fb_pli; /**< Any pending PLI? */ 201 int rtcp_fb_pli_cap_idx; /**< RX PLI cap idx. */ 189 202 190 203 #if TRACE_RC … … 204 217 static pj_status_t send_rtcp(pjmedia_vid_stream *stream, 205 218 pj_bool_t with_sdes, 206 pj_bool_t with_bye); 219 pj_bool_t with_bye, 220 pj_bool_t with_fb_nack, 221 pj_bool_t with_fb_pli); 207 222 208 223 static void on_rx_rtcp( void *data, … … 399 414 /* Republish this event later from get_frame(). */ 400 415 pj_memcpy(&stream->miss_keyframe_event, event, sizeof(*event)); 416 417 if (stream->send_rtcp_fb_pli) { 418 /* Schedule sending RTCP-FB PLI to encoder, if configured, 419 * also perhaps better to make it redundant, in case the first 420 * packet is lost. 421 */ 422 stream->pending_rtcp_fb_pli = 2; 423 } 401 424 return PJ_SUCCESS; 402 425 … … 404 427 break; 405 428 } 406 } 407 408 return pjmedia_event_publish(NULL, stream, event, 0); 409 } 429 } else if (event->epub == &stream->rtcp && 430 event->type==PJMEDIA_EVENT_RX_RTCP_FB) 431 { 432 /* This is RX RTCP-FB event */ 433 pjmedia_event_rx_rtcp_fb_data *data = 434 (pjmedia_event_rx_rtcp_fb_data*)&event->data.rx_rtcp_fb; 435 436 /* Check if configured to listen to the RTCP-FB type */ 437 if (data->cap.type == PJMEDIA_RTCP_FB_NACK) { 438 if (data->cap.param.slen == 0 && 439 stream->rtcp_fb_nack_cap_idx >= 0) 440 { 441 /* Generic NACK */ 442 443 /* Update event data capability before republishing */ 444 data->cap = stream->info.loc_rtcp_fb.caps[ 445 stream->rtcp_fb_nack_cap_idx]; 446 } 447 else if (pj_strcmp2(&data->cap.param, "pli") == 0 && 448 stream->rtcp_fb_pli_cap_idx >= 0) 449 { 450 /* PLI */ 451 452 /* Tell encoder to generate keyframe */ 453 pjmedia_vid_stream_send_keyframe(stream); 454 455 /* Update event data capability before republishing */ 456 data->cap = stream->info.loc_rtcp_fb.caps[ 457 stream->rtcp_fb_pli_cap_idx]; 458 459 } 460 } 461 } 462 463 /* Republish events */ 464 return pjmedia_event_publish(NULL, stream, event, 465 PJMEDIA_EVENT_PUBLISH_POST_EVENT); 466 } 467 410 468 411 469 /** … … 502 560 static pj_status_t send_rtcp(pjmedia_vid_stream *stream, 503 561 pj_bool_t with_sdes, 504 pj_bool_t with_bye) 562 pj_bool_t with_bye, 563 pj_bool_t with_fb_nack, 564 pj_bool_t with_fb_pli) 505 565 { 506 566 void *sr_rr_pkt; … … 513 573 pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 514 574 515 if (with_sdes || with_bye ) {575 if (with_sdes || with_bye || with_fb_nack || with_fb_pli) { 516 576 pkt = (pj_uint8_t*) stream->out_rtcp_pkt; 517 577 pj_memcpy(pkt, sr_rr_pkt, len); … … 522 582 } 523 583 524 /* Build RTCP SDES packet */ 584 /* Build RTCP SDES packet, forced if also send RTCP-FB */ 585 with_sdes = with_sdes || with_fb_pli || with_fb_nack; 525 586 if (with_sdes) { 526 587 pjmedia_rtcp_sdes sdes; … … 542 603 /* Build RTCP BYE packet */ 543 604 if (with_bye) { 544 pj_size_t bye_len; 545 546 bye_len = max_len - len; 605 pj_size_t bye_len = max_len - len; 547 606 status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len, 548 607 &bye_len, NULL); … … 555 614 } 556 615 616 /* Build RTCP-FB generic NACK packet */ 617 if (with_fb_nack && stream->rtcp_fb_nack.pid >= 0) { 618 pj_size_t fb_len = max_len - len; 619 status = pjmedia_rtcp_fb_build_nack(&stream->rtcp, pkt+len, &fb_len, 620 1, &stream->rtcp_fb_nack); 621 if (status != PJ_SUCCESS) { 622 PJ_PERROR(4,(stream->name.ptr, status, 623 "Error generating RTCP-FB NACK")); 624 } else { 625 len += (int)fb_len; 626 } 627 } 628 629 /* Build RTCP-FB PLI packet */ 630 if (with_fb_pli) { 631 pj_size_t fb_len = max_len - len; 632 status = pjmedia_rtcp_fb_build_pli(&stream->rtcp, pkt+len, &fb_len); 633 if (status != PJ_SUCCESS) { 634 PJ_PERROR(4,(stream->name.ptr, status, 635 "Error generating RTCP-FB PLI")); 636 } else { 637 len += (int)fb_len; 638 PJ_LOG(5,(stream->name.ptr, "Sending RTCP-FB PLI packet")); 639 } 640 } 641 557 642 /* Send! */ 558 643 status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); … … 575 660 * This function is can be called by either put_frame() or get_frame(), 576 661 * to transmit periodic RTCP SR/RR report. 577 */ 578 static void check_tx_rtcp(pjmedia_vid_stream *stream, pj_uint32_t timestamp) 579 { 580 /* Note that timestamp may represent local or remote timestamp, 581 * depending on whether this function is called from put_frame() 582 * or get_frame(). 662 * If 'fb_pli' is set to PJ_TRUE, this will send immediate RTCP-FB PLI. 663 */ 664 static void check_tx_rtcp(pjmedia_vid_stream *stream) 665 { 666 pj_timestamp now; 667 pj_bool_t early; 668 669 /* Check if early RTCP mode is required (i.e: RTCP-FB) and allowed (i.e: 670 * elapsed timestamp from previous RTCP-FB >= PJMEDIA_RTCP_FB_INTERVAL). 583 671 */ 584 585 586 if (stream->rtcp_last_tx == 0) { 587 588 stream->rtcp_last_tx = timestamp; 589 590 } else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) { 672 pj_get_timestamp(&now); 673 early = ((stream->pending_rtcp_fb_pli || stream->pending_rtcp_fb_nack) 674 && 675 (stream->rtcp_fb_last_tx.u64 == 0 || 676 pj_elapsed_msec(&stream->rtcp_fb_last_tx, &now) >= 677 PJMEDIA_RTCP_FB_INTERVAL)); 678 679 /* First check, unless RTCP is 'urgent', just init rtcp_last_tx. */ 680 if (stream->rtcp_last_tx.u64 == 0 && !early) { 681 pj_get_timestamp(&stream->rtcp_last_tx); 682 return; 683 } 684 685 /* Build & send RTCP */ 686 if (early || 687 pj_elapsed_msec(&stream->rtcp_last_tx, &now) >= stream->rtcp_interval) 688 { 591 689 pj_status_t status; 592 690 593 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE); 691 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE, 692 stream->pending_rtcp_fb_nack, 693 stream->pending_rtcp_fb_pli); 594 694 if (status != PJ_SUCCESS) { 595 695 PJ_PERROR(4,(stream->name.ptr, status, … … 597 697 } 598 698 599 stream->rtcp_last_tx = timestamp; 699 stream->rtcp_last_tx = now; 700 701 if (early) 702 stream->rtcp_fb_last_tx = now; 703 704 if (stream->pending_rtcp_fb_pli) 705 stream->pending_rtcp_fb_pli--; 706 707 if (stream->pending_rtcp_fb_nack) 708 stream->pending_rtcp_fb_nack--; 600 709 } 601 710 } … … 841 950 pj_mutex_unlock( stream->jb_mutex ); 842 951 952 /* Check if we need to send RTCP-FB generic NACK */ 953 if (stream->send_rtcp_fb_nack && seq_st.diff > 1 && 954 pj_ntohs(hdr->seq) >= seq_st.diff) 955 { 956 int i; 957 pj_bzero(&stream->rtcp_fb_nack, sizeof(stream->rtcp_fb_nack)); 958 stream->rtcp_fb_nack.pid = pj_ntohs(hdr->seq) - seq_st.diff + 1; 959 for (i = 0; i < (seq_st.diff - 1); ++i) { 960 stream->rtcp_fb_nack.blp <<= 1; 961 stream->rtcp_fb_nack.blp |= 1; 962 } 963 stream->pending_rtcp_fb_nack = 1; 964 } 843 965 844 966 /* Check if now is the time to transmit RTCP SR/RR report. … … 848 970 */ 849 971 if (stream->dir == PJMEDIA_DIR_DECODING || stream->enc->paused) { 850 check_tx_rtcp(stream , pj_ntohl(hdr->ts));972 check_tx_rtcp(stream); 851 973 } 852 974 … … 869 991 if (stream->rtcp.received >= 10 && !stream->initial_rr) { 870 992 status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 871 PJ_FALSE );993 PJ_FALSE, PJ_FALSE, PJ_FALSE); 872 994 if (status != PJ_SUCCESS) { 873 995 PJ_PERROR(4,(stream->name.ptr, status, … … 924 1046 unsigned pkt_cnt = 0; 925 1047 pj_timestamp initial_time; 1048 pj_timestamp now; 926 1049 pj_timestamp null_ts ={{0}}; 927 1050 … … 967 1090 968 1091 /* Check if need to send keyframe. */ 1092 pj_get_timestamp(&now); 969 1093 if (stream->num_keyframe && 970 1094 (pj_cmp_timestamp(&null_ts, &stream->last_keyframe_tx) != 0)) 971 1095 { 972 1096 unsigned elapse_time; 973 pj_timestamp now;974 975 pj_get_timestamp(&now);976 1097 977 1098 elapse_time = pj_elapsed_msec(&stream->last_keyframe_tx, &now); 978 979 1099 if (elapse_time > stream->info.sk_cfg.interval) 980 1100 { … … 986 1106 /* Init encoding option */ 987 1107 pj_bzero(&enc_opt, sizeof(enc_opt)); 988 if (stream->force_keyframe) { 1108 if (stream->force_keyframe && 1109 pj_elapsed_msec(&stream->last_keyframe_tx, &now) >= 1110 PJMEDIA_VID_STREAM_MIN_KEYFRAME_INTERVAL_MSEC) 1111 { 989 1112 /* Force encoder to generate keyframe */ 990 1113 enc_opt.force_keyframe = PJ_TRUE; … … 1013 1136 pj_get_timestamp(&initial_time); 1014 1137 1015 if ((stream->num_keyframe) && 1016 ((frame_out.bit_info & PJMEDIA_VID_FRM_KEYFRAME) 1017 == PJMEDIA_VID_FRM_KEYFRAME)) 1138 if ((frame_out.bit_info & PJMEDIA_VID_FRM_KEYFRAME) 1139 == PJMEDIA_VID_FRM_KEYFRAME) 1018 1140 { 1019 1141 stream->last_keyframe_tx = initial_time; 1142 TRC_((channel->port.info.name.ptr, "Keyframe generated")); 1020 1143 } 1021 1144 … … 1130 1253 */ 1131 1254 if (stream->dir != PJMEDIA_DIR_DECODING) { 1132 check_tx_rtcp(stream , pj_ntohl(channel->rtp.out_hdr.ts));1255 check_tx_rtcp(stream); 1133 1256 } 1134 1257 … … 1637 1760 stream->dir = info->dir; 1638 1761 stream->user_data = user_data; 1639 stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) * 1640 info->codec_info.clock_rate / 1000; 1762 stream->rtcp_interval = PJMEDIA_RTCP_INTERVAL + pj_rand()%1000 - 500; 1641 1763 stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled; 1642 1764 … … 1816 1938 1817 1939 pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting); 1940 1941 /* Subscribe to RTCP events */ 1942 pjmedia_event_subscribe(NULL, &stream_event_cb, stream, 1943 &stream->rtcp); 1818 1944 } 1819 1945 1820 1946 /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES, 1821 * BYE, and XR.1947 * BYE, Feedback, and XR. 1822 1948 */ 1823 1949 stream->out_rtcp_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) + 1824 1950 sizeof(pjmedia_rtcp_common) + 1825 1951 (4 + (unsigned)stream->cname.slen) + 1826 32 ;1952 32 + 32; 1827 1953 if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU) 1828 1954 stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU; … … 1897 2023 stream->info.codec_param = pjmedia_vid_codec_param_clone( 1898 2024 pool, info->codec_param); 2025 pjmedia_rtcp_fb_info_dup(pool, &stream->info.loc_rtcp_fb, 2026 &info->loc_rtcp_fb); 2027 pjmedia_rtcp_fb_info_dup(pool, &stream->info.rem_rtcp_fb, 2028 &info->rem_rtcp_fb); 2029 2030 /* Check if we should send RTCP-FB */ 2031 if (stream->info.rem_rtcp_fb.cap_count) { 2032 pjmedia_rtcp_fb_info *rfi = &stream->info.rem_rtcp_fb; 2033 unsigned i; 2034 2035 for (i = 0; i < rfi->cap_count; ++i) { 2036 if (rfi->caps[i].type == PJMEDIA_RTCP_FB_NACK) { 2037 if (rfi->caps[i].param.slen == 0) { 2038 stream->send_rtcp_fb_nack = PJ_TRUE; 2039 PJ_LOG(5,(stream->name.ptr, "Send RTCP-FB generic NACK")); 2040 } else if (pj_stricmp2(&rfi->caps[i].param, "pli")==0) { 2041 stream->send_rtcp_fb_pli = PJ_TRUE; 2042 PJ_LOG(5,(stream->name.ptr, "Send RTCP-FB PLI")); 2043 } 2044 } 2045 } 2046 } 2047 2048 /* Check if we should process incoming RTCP-FB */ 2049 stream->rtcp_fb_nack_cap_idx = -1; 2050 stream->rtcp_fb_pli_cap_idx = -1; 2051 if (stream->info.loc_rtcp_fb.cap_count) { 2052 pjmedia_rtcp_fb_info *lfi = &stream->info.loc_rtcp_fb; 2053 unsigned i; 2054 2055 for (i = 0; i < lfi->cap_count; ++i) { 2056 if (lfi->caps[i].type == PJMEDIA_RTCP_FB_NACK) { 2057 if (lfi->caps[i].param.slen == 0) { 2058 stream->rtcp_fb_nack_cap_idx = i; 2059 PJ_LOG(5,(stream->name.ptr, 2060 "Receive RTCP-FB generic NACK")); 2061 } else if (pj_stricmp2(&lfi->caps[i].param, "pli")==0) { 2062 stream->rtcp_fb_pli_cap_idx = i; 2063 PJ_LOG(5,(stream->name.ptr, "Receive RTCP-FB PLI")); 2064 } 2065 } 2066 } 2067 } 1899 2068 1900 2069 /* Success! */ … … 1931 2100 #endif 1932 2101 2102 /* Unsubscribe events from RTCP */ 2103 pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream, &stream->rtcp); 2104 1933 2105 /* Send RTCP BYE (also SDES) */ 1934 2106 if (stream->transport && !stream->rtcp_sdes_bye_disabled) { 1935 send_rtcp(stream, PJ_TRUE, PJ_TRUE );2107 send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE, PJ_FALSE); 1936 2108 } 1937 2109 … … 2173 2345 pjmedia_vid_stream *stream) 2174 2346 { 2347 pj_timestamp now; 2348 2175 2349 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 2176 2350 … … 2178 2352 return PJ_EINVALIDOP; 2179 2353 2354 pj_get_timestamp(&now); 2355 if (pj_elapsed_msec(&stream->last_keyframe_tx, &now) < 2356 PJMEDIA_VID_STREAM_MIN_KEYFRAME_INTERVAL_MSEC) 2357 { 2358 return PJ_ETOOMANY; 2359 } 2360 2180 2361 stream->force_keyframe = PJ_TRUE; 2181 2362 … … 2192 2373 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 2193 2374 2194 return send_rtcp(stream, PJ_TRUE, PJ_FALSE );2375 return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 2195 2376 } 2196 2377 … … 2205 2386 2206 2387 if (stream->enc && stream->transport) { 2207 return send_rtcp(stream, PJ_TRUE, PJ_TRUE );2388 return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE, PJ_FALSE); 2208 2389 } 2209 2390
Note: See TracChangeset
for help on using the changeset viewer.