- Timestamp:
- Nov 13, 2019 9:11:04 AM (4 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/config.h
r6105 r6106 466 466 467 467 /** 468 * Interval to send RTCP packets, in msec468 * Interval to send regular RTCP packets, in msec. 469 469 */ 470 470 #ifndef PJMEDIA_RTCP_INTERVAL 471 # define PJMEDIA_RTCP_INTERVAL 5000 /* msec*/ 471 # define PJMEDIA_RTCP_INTERVAL 5000 /* msec*/ 472 #endif 473 474 475 /** 476 * Minimum interval between two consecutive outgoing RTCP-FB packets, 477 * such as Picture Loss Indication, in msec. 478 */ 479 #ifndef PJMEDIA_RTCP_FB_INTERVAL 480 # define PJMEDIA_RTCP_FB_INTERVAL 50 /* msec*/ 472 481 #endif 473 482 … … 1528 1537 1529 1538 /** 1539 * Specify the minimum interval to send video keyframe, in msec. 1540 * 1541 * Default : 1000 1542 */ 1543 #ifndef PJMEDIA_VID_STREAM_MIN_KEYFRAME_INTERVAL_MSEC 1544 # define PJMEDIA_VID_STREAM_MIN_KEYFRAME_INTERVAL_MSEC 1000 1545 #endif 1546 1547 1548 /** 1530 1549 * Specify minimum delay of video decoding, in milliseconds. Lower value may 1531 1550 * degrade video quality significantly in a bad network environment (e.g: -
pjproject/trunk/pjmedia/include/pjmedia/event.h
r6085 r6106 26 26 #include <pjmedia/audiodev.h> 27 27 #include <pjmedia/format.h> 28 #include <pjmedia/rtcp_fb.h> 28 29 #include <pjmedia/signatures.h> 29 30 #include <pjmedia/videodev.h> … … 297 298 /** Media transport error event data */ 298 299 pjmedia_event_media_tp_err_data med_tp_err; 300 301 /** Receiving RTCP-FB event data */ 302 pjmedia_event_rx_rtcp_fb_data rx_rtcp_fb; 299 303 300 304 /** Pointer to storage to user event data, if it's outside -
pjproject/trunk/pjmedia/include/pjmedia/rtcp_fb.h
r5825 r6106 136 136 /** 137 137 * Specify whether transport protocol in SDP media description uses 138 * RTP/AVP instead of RTP/AVPF. Note that the standard mandates to signal 139 * AVPF profile, but it may cause SDP negotiation failure when negotiating 140 * with endpoints that does not support RTCP Feedback (including older 141 * version of PJSIP). 138 * RTP/AVP instead of RTP/AVPF. Note that RFC4585 mandates to signal 139 * RTP/AVPF profile, but it may cause SDP negotiation failure when 140 * negotiating with endpoints that does not support RTP/AVPF (including 141 * older version of PJSIP), furthermore, there is RFC8643 that promotes 142 * interoperability over the strictness of RTP profile specifications. 142 143 * 143 * Default: PJ_ FALSE.144 * Default: PJ_TRUE. 144 145 */ 145 146 pj_bool_t dont_use_avpf; … … 295 296 296 297 /** 298 * Decode RTCP Feedback specific information from SDP media for the specified 299 * payload type. If the payload type is set to negative value, it will decode 300 * RTCP Feedback info for all payload types in the SDP media. 301 * 302 * @param pool Pool object to allocate memory. 303 * @param endpt The media endpoint. 304 * @param opt Options, currently it must be NULL. 305 * @param sdp The SDP. 306 * @param med_idx The SDP media index. 307 * @param pt The payload type. 308 * @param info The RTCP-FB info fetched from SDP. 309 * 310 * @return PJ_SUCCESS on success. 311 */ 312 PJ_DECL(pj_status_t) pjmedia_rtcp_fb_decode_sdp2( 313 pj_pool_t *pool, 314 pjmedia_endpt *endpt, 315 const void *opt, 316 const pjmedia_sdp_session *sdp, 317 unsigned med_idx, 318 int pt, 319 pjmedia_rtcp_fb_info *info); 320 321 322 /** 297 323 * Build an RTCP Feedback Generic NACK packet. This packet can be appended to 298 324 * other RTCP packets, e.g: RTCP RR/SR, to compose a compound RTCP packet. -
pjproject/trunk/pjmedia/include/pjmedia/types.h
r5820 r6106 306 306 */ 307 307 PJ_DECL(const char*) pjmedia_type_name(pjmedia_type t); 308 309 310 /** 311 * Utility function to return the media type for a media name string. 312 * 313 * @param name The media name string. 314 * 315 * @return media type. 316 */ 317 PJ_DECL(pjmedia_type) pjmedia_get_type(const pj_str_t *name); 318 308 319 309 320 /** -
pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h
r3956 r6106 525 525 /** 526 526 * Convert codec info struct into a unique codec identifier. 527 * A codec identifier looks something like "H263/90000". 527 * A codec identifier looks something like "H263/34", where "H263" is the 528 * codec name and "34" is the (default) payload type. 528 529 * 529 530 * @param info The codec info … … 541 542 * Find codecs by the unique codec identifier. This function will find 542 543 * all codecs that match the codec identifier prefix. For example, if 543 * "H26" is specified, then it will find "H263 /90000", "H264/90000",544 * and so on,up to the maximum count specified in the argument.544 * "H26" is specified, then it will find "H263", "H264", and so on, 545 * up to the maximum count specified in the argument. 545 546 * 546 547 * @param mgr The codec manager instance. If NULL, the default codec -
pjproject/trunk/pjmedia/include/pjmedia/vid_stream.h
r5788 r6106 30 30 #include <pjmedia/port.h> 31 31 #include <pjmedia/rtcp.h> 32 #include <pjmedia/rtcp_fb.h> 32 33 #include <pjmedia/transport.h> 33 34 #include <pjmedia/vid_codec.h> … … 157 158 will be calculated from RTP. */ 158 159 pj_bool_t rtcp_mux; /**< Use RTP and RTCP multiplexing. */ 160 pjmedia_rtcp_fb_info loc_rtcp_fb; /**< Local RTCP-FB info. */ 161 pjmedia_rtcp_fb_info rem_rtcp_fb; /**< Remote RTCP-FB info. */ 159 162 unsigned tx_pt; /**< Outgoing codec paylaod type. */ 160 163 unsigned rx_pt; /**< Incoming codec paylaod type. */ -
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r5919 r6106 780 780 //pjmedia_rtcp_fb_rpsi rpsi; 781 781 pjmedia_event ev; 782 pjmedia_event_rx_rtcp_fb_data ev_data;783 782 pj_timestamp ts_now; 784 783 785 784 pj_get_timestamp(&ts_now); 786 pj_bzero(&ev_data, sizeof(ev_data));787 785 788 786 if (pjmedia_rtcp_fb_parse_nack(pkt, size, &cnt, nack)==PJ_SUCCESS) 789 787 { 790 788 pjmedia_event_init(&ev, PJMEDIA_EVENT_RX_RTCP_FB, &ts_now, sess); 791 ev_data.cap.type = PJMEDIA_RTCP_FB_NACK; 792 ev_data.msg.nack = nack[0]; 793 ev.data.ptr = &ev_data; 794 795 /* Sync publish, i.e: don't use PJMEDIA_EVENT_PUBLISH_POST_EVENT */ 789 ev.data.rx_rtcp_fb.cap.type = PJMEDIA_RTCP_FB_NACK; 790 ev.data.rx_rtcp_fb.msg.nack = nack[0]; 796 791 pjmedia_event_publish(NULL, sess, &ev, 0); 797 792 798 /* For other FB type implementations later799 793 } else if (pjmedia_rtcp_fb_parse_pli(pkt, size)==PJ_SUCCESS) 800 794 { 795 pjmedia_event_init(&ev, PJMEDIA_EVENT_RX_RTCP_FB, &ts_now, sess); 796 ev.data.rx_rtcp_fb.cap.type = PJMEDIA_RTCP_FB_NACK; 797 pj_strset2(&ev.data.rx_rtcp_fb.cap.param, (char*)"pli"); 798 pjmedia_event_publish(NULL, sess, &ev, 0); 799 800 /* For other FB type implementations later 801 801 } else if (pjmedia_rtcp_fb_parse_sli(pkt, size, &cnt, sli)==PJ_SUCCESS) 802 802 { -
pjproject/trunk/pjmedia/src/pjmedia/rtcp_fb.c
r5827 r6106 22 22 #include <pjmedia/endpoint.h> 23 23 #include <pjmedia/errno.h> 24 #include <pjmedia/vid_codec.h> 24 25 #include <pj/assert.h> 25 26 #include <pj/log.h> … … 215 216 { 216 217 pj_bzero(opt, sizeof(*opt)); 218 opt->dont_use_avpf = PJ_TRUE; 217 219 218 220 return PJ_SUCCESS; … … 332 334 pjmedia_codec_mgr *codec_mgr; 333 335 unsigned j, cnt = 0; 336 pjmedia_type type = PJMEDIA_TYPE_UNKNOWN; 334 337 pj_status_t status; 338 339 type = pjmedia_get_type(&m->desc.media); 340 if (type != PJMEDIA_TYPE_AUDIO && type != PJMEDIA_TYPE_VIDEO) 341 return PJMEDIA_EUNSUPMEDIATYPE; 335 342 336 343 codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); … … 339 346 pt = pj_strtoul(&m->desc.fmt[j]); 340 347 if (pt < 96) { 341 const pjmedia_codec_info *ci; 342 status = pjmedia_codec_mgr_get_codec_info(codec_mgr, 343 pt, &ci); 344 if (status != PJ_SUCCESS) 345 continue; 346 347 pjmedia_codec_info_to_id(ci, sci[cnt].id, sizeof(sci[0].id)); 348 if (type == PJMEDIA_TYPE_AUDIO) { 349 const pjmedia_codec_info *ci; 350 status = pjmedia_codec_mgr_get_codec_info(codec_mgr, pt, &ci); 351 if (status != PJ_SUCCESS) 352 continue; 353 354 pjmedia_codec_info_to_id(ci, sci[cnt].id, sizeof(sci[0].id)); 355 } else { 356 const pjmedia_vid_codec_info *ci; 357 status = pjmedia_vid_codec_mgr_get_codec_info(NULL, pt, &ci); 358 if (status != PJ_SUCCESS) 359 continue; 360 361 pjmedia_vid_codec_info_to_id(ci, sci[cnt].id, 362 sizeof(sci[0].id)); 363 } 348 364 } else { 349 365 pjmedia_sdp_attr *a; … … 356 372 if (status != PJ_SUCCESS) 357 373 continue; 358 if (r.param.slen) { 374 375 if (type == PJMEDIA_TYPE_AUDIO) { 376 /* Audio codec id format: "name/clock-rate/channel-count" */ 377 if (r.param.slen) { 378 pj_ansi_snprintf(sci[cnt].id, sizeof(sci[0].id), 379 "%.*s/%d/%.*s", 380 (int)r.enc_name.slen, r.enc_name.ptr, 381 r.clock_rate, 382 (int)r.param.slen, r.param.ptr); 383 } else { 384 pj_ansi_snprintf(sci[cnt].id, sizeof(sci[0].id), 385 "%.*s/%d/1", 386 (int)r.enc_name.slen, r.enc_name.ptr, 387 r.clock_rate); 388 } 389 } else { 390 /* Video codec id format: "name/payload-type" */ 359 391 pj_ansi_snprintf(sci[cnt].id, sizeof(sci[0].id), 360 "%.*s/%d/%.*s", 361 (int)r.enc_name.slen, r.enc_name.ptr, 362 r.clock_rate, 363 (int)r.param.slen, r.param.ptr); 364 } else { 365 pj_ansi_snprintf(sci[cnt].id, sizeof(sci[0].id), 366 "%.*s/%d/1", 367 (int)r.enc_name.slen, r.enc_name.ptr, 368 r.clock_rate); 392 "%.*s/%d", 393 (int)r.enc_name.slen, r.enc_name.ptr, pt); 369 394 } 370 395 } … … 396 421 PJ_UNUSED_ARG(sdp_remote); 397 422 398 PJ_ASSERT_RETURN(pool && endpt && opt && sdp_local, PJ_EINVAL);423 PJ_ASSERT_RETURN(pool && endpt && opt && sdp_local, PJ_EINVAL); 399 424 PJ_ASSERT_RETURN(med_idx < sdp_local->media_count, PJ_EINVAL); 400 425 … … 403 428 unsigned proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 404 429 if (!PJMEDIA_TP_PROTO_HAS_FLAG(proto, PJMEDIA_TP_PROFILE_RTCP_FB)) { 405 char *new_tp; 406 new_tp = (char*)pj_pool_zalloc(pool, m->desc.transport.slen+1); 407 pj_ansi_strncpy(new_tp, m->desc.transport.ptr, 408 m->desc.transport.slen); 409 pj_ansi_strcat(new_tp, "F"); 410 pj_strset2(&m->desc.transport, new_tp); 430 pj_str_t new_tp; 431 pj_strdup_with_null(pool, &new_tp, &m->desc.transport); 432 new_tp.ptr[new_tp.slen++] = 'F'; 433 m->desc.transport = new_tp; 411 434 } 412 435 } … … 477 500 pjmedia_rtcp_fb_info *info) 478 501 { 502 return pjmedia_rtcp_fb_decode_sdp2(pool, endpt, opt, sdp, med_idx, -1, 503 info); 504 } 505 506 /* 507 * Decode RTCP Feedback specific information from SDP media. 508 */ 509 PJ_DEF(pj_status_t) pjmedia_rtcp_fb_decode_sdp2( 510 pj_pool_t *pool, 511 pjmedia_endpt *endpt, 512 const void *opt, 513 const pjmedia_sdp_session *sdp, 514 unsigned med_idx, 515 int pt, 516 pjmedia_rtcp_fb_info *info) 517 { 479 518 unsigned sci_cnt = PJMEDIA_MAX_SDP_FMT; 480 519 sdp_codec_info_t sci[PJMEDIA_MAX_SDP_FMT]; … … 487 526 PJ_ASSERT_RETURN(pool && endpt && opt==NULL && sdp, PJ_EINVAL); 488 527 PJ_ASSERT_RETURN(med_idx < sdp->media_count, PJ_EINVAL); 528 PJ_ASSERT_RETURN(pt <= 127, PJ_EINVAL); 489 529 490 530 m = sdp->media[med_idx]; … … 515 555 516 556 if (pj_strcmp2(&token, "*") == 0) { 517 /* A sterisk (all codecs)*/557 /* All codecs */ 518 558 codec_id = "*"; 519 559 } else { 520 /* Specific PT */521 unsigned pt = (unsigned) pj_strtoul2(&token, NULL, 10);560 /* Specific PT/codec */ 561 unsigned pt_ = (unsigned) pj_strtoul2(&token, NULL, 10); 522 562 for (j = 0; j < sci_cnt; ++j) { 523 if (pt == sci[j].pt) { 563 /* Check if payload type is valid and requested */ 564 if (pt_ == sci[j].pt && (pt < 0 || pt == (int)pt_)) { 524 565 codec_id = sci[j].id; 525 566 break; … … 528 569 } 529 570 530 /* Skip this a=rtcp-fb if PT is not recognized */571 /* Skip this a=rtcp-fb if PT is not recognized or not requested */ 531 572 if (!codec_id) 532 573 continue; -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r6098 r6106 2252 2252 { 2253 2253 pjmedia_event_rx_rtcp_fb_data *data = (pjmedia_event_rx_rtcp_fb_data*) 2254 event->data.ptr;2254 &event->data.rx_rtcp_fb; 2255 2255 2256 2256 /* Application not configured to listen to NACK, discard this event */ … … 2262 2262 2263 2263 /* Republish events */ 2264 return pjmedia_event_publish(NULL, stream, event, 0); 2264 return pjmedia_event_publish(NULL, stream, event, 2265 PJMEDIA_EVENT_PUBLISH_POST_EVENT); 2265 2266 } 2266 2267 … … 2743 2744 #endif 2744 2745 2745 /* Check if we should send RTCP-FB generic NACK for this codec*/2746 /* Check if we should send RTCP-FB */ 2746 2747 if (stream->si.rem_rtcp_fb.cap_count) { 2747 2748 pjmedia_rtcp_fb_info *rfi = &stream->si.rem_rtcp_fb; 2748 char cid[32];2749 2749 unsigned i; 2750 2751 pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid));2752 2750 2753 2751 for (i = 0; i < rfi->cap_count; ++i) { 2754 2752 if (rfi->caps[i].type == PJMEDIA_RTCP_FB_NACK && 2755 (!pj_strcmp2( &rfi->caps[i].codec_id, "*") || 2756 !pj_stricmp2(&rfi->caps[i].codec_id, cid))) 2753 rfi->caps[i].param.slen == 0) 2757 2754 { 2758 2755 stream->send_rtcp_fb_nack = PJ_TRUE; 2756 PJ_LOG(4,(stream->port.info.name.ptr, 2757 "Send RTCP-FB generic NACK")); 2759 2758 break; 2760 2759 } … … 2762 2761 } 2763 2762 2764 /* Check if we handle incoming RTCP-FB generic NACK for this codec*/2763 /* Check if we should process incoming RTCP-FB */ 2765 2764 stream->rtcp_fb_nack_cap_idx = -1; 2766 2765 if (stream->si.loc_rtcp_fb.cap_count) { 2767 2766 pjmedia_rtcp_fb_info *lfi = &stream->si.loc_rtcp_fb; 2768 char cid[32];2769 2767 unsigned i; 2770 2771 pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid));2772 2768 2773 2769 for (i = 0; i < lfi->cap_count; ++i) { 2774 2770 if (lfi->caps[i].type == PJMEDIA_RTCP_FB_NACK && 2775 (!pj_strcmp2( &lfi->caps[i].codec_id, "*") || 2776 !pj_stricmp2(&lfi->caps[i].codec_id, cid))) 2771 lfi->caps[i].param.slen == 0) 2777 2772 { 2778 2773 stream->rtcp_fb_nack_cap_idx = i; 2774 PJ_LOG(4,(stream->port.info.name.ptr, 2775 "Receive RTCP-FB generic NACK")); 2779 2776 break; 2780 2777 } -
pjproject/trunk/pjmedia/src/pjmedia/stream_info.c
r5820 r6106 24 24 #include <pj/rand.h> 25 25 26 static const pj_str_t ID_AUDIO = { "audio", 5};27 26 static const pj_str_t ID_IN = { "IN", 2 }; 28 27 static const pj_str_t ID_IP4 = { "IP4", 3}; … … 387 386 388 387 /* Media type must be audio */ 389 if (pj _stricmp(&local_m->desc.media, &ID_AUDIO) != 0)388 if (pjmedia_get_type(&local_m->desc.media) != PJMEDIA_TYPE_AUDIO) 390 389 return PJMEDIA_EINVALIMEDIATYPE; 391 390 … … 602 601 603 602 /* Get local RTCP-FB info */ 604 status = pjmedia_rtcp_fb_decode_sdp (pool, endpt, NULL, local, stream_idx,605 &si->loc_rtcp_fb);603 status = pjmedia_rtcp_fb_decode_sdp2(pool, endpt, NULL, local, stream_idx, 604 si->rx_pt, &si->loc_rtcp_fb); 606 605 if (status != PJ_SUCCESS) 607 606 return status; 608 607 609 608 /* Get remote RTCP-FB info */ 610 status = pjmedia_rtcp_fb_decode_sdp (pool, endpt, NULL, remote, stream_idx,611 &si->rem_rtcp_fb);609 status = pjmedia_rtcp_fb_decode_sdp2(pool, endpt, NULL, remote, stream_idx, 610 si->tx_pt, &si->rem_rtcp_fb); 612 611 if (status != PJ_SUCCESS) 613 612 return status; -
pjproject/trunk/pjmedia/src/pjmedia/types.c
r4411 r6106 20 20 #include <pjmedia/types.h> 21 21 #include <pj/assert.h> 22 #include <pj/string.h> 22 23 23 /** 24 25 /* Map structure for pjmedia type names */ 26 typedef struct pjmedia_type_map { 27 pjmedia_type type; 28 const char* name; 29 } pjmedia_type_map; 30 31 /* Internal mapping for pjmedia type names */ 32 static pjmedia_type_map media_type_names[] = { 33 {PJMEDIA_TYPE_NONE, "none"}, 34 {PJMEDIA_TYPE_AUDIO, "audio"}, 35 {PJMEDIA_TYPE_VIDEO, "video"}, 36 {PJMEDIA_TYPE_APPLICATION, "application"}, 37 {PJMEDIA_TYPE_UNKNOWN, "unknown"} 38 }; 39 40 /* 24 41 * Utility function to return the string name for a pjmedia_type. 25 *26 * @param t The media type.27 *28 * @return String.29 42 */ 30 43 PJ_DEF(const char*) pjmedia_type_name(pjmedia_type t) 31 44 { 32 const char *type_names[] = { 33 "none", 34 "audio", 35 "video", 36 "application", 37 "unknown" 38 }; 39 40 pj_assert(t < (int)PJ_ARRAY_SIZE(type_names)); 45 pj_assert(t < (int)PJ_ARRAY_SIZE(media_type_names)); 41 46 pj_assert(PJMEDIA_TYPE_UNKNOWN == 4); 42 47 43 if (t < (int)PJ_ARRAY_SIZE( type_names))44 return type_names[t];48 if (t < (int)PJ_ARRAY_SIZE(media_type_names)) 49 return media_type_names[t].name; 45 50 else 46 51 return "??"; 47 52 } 53 54 /* 55 * Utility function to return the media type for a media name string. 56 */ 57 PJ_DEF(pjmedia_type) pjmedia_get_type(const pj_str_t *name) 58 { 59 int i; 60 for (i = 0; i < PJ_ARRAY_SIZE(media_type_names); ++i) { 61 if (pj_stricmp2(name, media_type_names[i].name)==0) 62 return media_type_names[i].type; 63 } 64 return PJMEDIA_TYPE_UNKNOWN; 65 } -
pjproject/trunk/pjmedia/src/pjmedia/vid_codec.c
r4616 r6106 410 410 411 411 /* 412 * Find codecs by the unique codec identifier. This function will find 413 * all codecs that match the codec identifier prefix. For example, if 414 * "L16" is specified, then it will find "L16/8000/1", "L16/16000/1", 415 * and so on, up to the maximum count specified in the argument. 412 * Find codecs by the unique codec identifier. 416 413 */ 417 414 PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_find_codecs_by_id( -
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 -
pjproject/trunk/pjmedia/src/pjmedia/vid_stream_info.c
r5820 r6106 25 25 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 26 26 27 static const pj_str_t ID_VIDEO = { "video", 5};28 27 static const pj_str_t ID_IN = { "IN", 2 }; 29 28 static const pj_str_t ID_IP4 = { "IP4", 3}; … … 217 216 218 217 /* Media type must be video */ 219 if (pj _stricmp(&local_m->desc.media, &ID_VIDEO) != 0)218 if (pjmedia_get_type(&local_m->desc.media) != PJMEDIA_TYPE_VIDEO) 220 219 return PJMEDIA_EINVALIMEDIATYPE; 221 220 … … 403 402 si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 404 403 404 /* Get local RTCP-FB info */ 405 status = pjmedia_rtcp_fb_decode_sdp2(pool, endpt, NULL, local, stream_idx, 406 si->rx_pt, &si->loc_rtcp_fb); 407 if (status != PJ_SUCCESS) 408 return status; 409 410 /* Get remote RTCP-FB info */ 411 status = pjmedia_rtcp_fb_decode_sdp2(pool, endpt, NULL, remote, stream_idx, 412 si->tx_pt, &si->rem_rtcp_fb); 413 if (status != PJ_SUCCESS) 414 return status; 415 405 416 return status; 406 417 } -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r6097 r6106 861 861 * the call. Value is bitmask of #pjsua_vid_req_keyframe_method. 862 862 * 863 * Default: PJSUA_VID_REQ_KEYFRAME_SIP_INFO 863 * Default: (PJSUA_VID_REQ_KEYFRAME_SIP_INFO | 864 * PJSUA_VID_REQ_KEYFRAME_RTCP_PLI) 864 865 */ 865 866 unsigned req_keyframe_method; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r6083 r6106 618 618 opt->vid_cnt = 1; 619 619 opt->req_keyframe_method = PJSUA_VID_REQ_KEYFRAME_SIP_INFO | 620 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI;620 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI; 621 621 #endif 622 622 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
r6093 r6106 1336 1336 const pjmedia_sdp_media *m = sdp->media[i]; 1337 1337 const pjmedia_sdp_conn *c; 1338 static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };1338 pj_uint32_t proto; 1339 1339 1340 1340 /* Skip different media */ … … 1347 1347 1348 1348 /* Supported transports */ 1349 if (pj_stristr(&m->desc.transport, &ID_RTP_SAVP)) { 1349 proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 1350 if (PJMEDIA_TP_PROTO_HAS_FLAG(proto, PJMEDIA_TP_PROTO_RTP_SAVP)) 1351 { 1350 1352 switch (use_srtp) { 1351 1353 case PJMEDIA_SRTP_MANDATORY: … … 1358 1360 break; 1359 1361 } 1360 } else if (pj_stricmp2(&m->desc.transport, "RTP/AVP")==0) { 1362 } else if (PJMEDIA_TP_PROTO_HAS_FLAG(proto, PJMEDIA_TP_PROTO_RTP_AVP)) 1363 { 1361 1364 switch (use_srtp) { 1362 1365 case PJMEDIA_SRTP_MANDATORY: … … 1482 1485 pj_status_t on_media_event(pjmedia_event *event, void *user_data) 1483 1486 { 1487 char ev_name[5]; 1484 1488 pj_status_t status = PJ_SUCCESS; 1485 1489 1486 1490 PJ_UNUSED_ARG(user_data); 1491 1492 pjmedia_fourcc_name(event->type, ev_name); 1493 PJ_LOG(4,(THIS_FILE, "Received media event type=%s, src=%p, epub=%p", 1494 ev_name, event->src, event->epub)); 1487 1495 1488 1496 /* Forward the event */ … … 1500 1508 pjsua_call_media *call_med = (pjsua_call_media*)user_data; 1501 1509 pjsua_call *call = call_med? call_med->call : NULL; 1510 char ev_name[5]; 1502 1511 pj_status_t status = PJ_SUCCESS; 1503 1512 1513 pj_assert(call && call_med); 1514 pjmedia_fourcc_name(event->type, ev_name); 1515 PJ_LOG(5,(THIS_FILE, "Call %d: Media %d: Received media event, type=%s, " 1516 "src=%p, epub=%p", 1517 call->index, call_med->idx, ev_name, 1518 event->src, event->epub)); 1519 1504 1520 switch(event->type) { 1505 1521 case PJMEDIA_EVENT_KEYFRAME_MISSING: … … 2675 2691 } 2676 2692 2677 /* Add RTCP-FB info in SDP if we are offerer */ 2678 if (rem_sdp == NULL && acc->cfg.rtcp_fb_cfg.cap_count) { 2693 /* Setup RTCP-FB */ 2694 { 2695 pjmedia_rtcp_fb_setting rtcp_cfg; 2696 pjmedia_rtcp_fb_setting_default(&rtcp_cfg); 2697 2698 /* Add RTCP-FB PLI if PJSUA_VID_REQ_KEYFRAME_RTCP_PLI is set */ 2699 if (call_med->type == PJMEDIA_TYPE_VIDEO && 2700 (call->opt.req_keyframe_method & 2701 PJSUA_VID_REQ_KEYFRAME_RTCP_PLI)) 2702 { 2703 rtcp_cfg.cap_count = 1; 2704 pj_strset2(&rtcp_cfg.caps[0].codec_id, (char*)"*"); 2705 rtcp_cfg.caps[0].type = PJMEDIA_RTCP_FB_NACK; 2706 pj_strset2(&rtcp_cfg.caps[0].param, (char*)"pli"); 2707 } 2708 2709 /* Should we put "RTP/AVPF" in SDP?*/ 2710 if (rem_sdp) { 2711 /* For answer, match remote offer */ 2712 unsigned rem_proto = 0; 2713 rem_proto = pjmedia_sdp_transport_get_proto( 2714 &rem_sdp->media[mi]->desc.transport); 2715 rtcp_cfg.dont_use_avpf = 2716 !PJMEDIA_TP_PROTO_HAS_FLAG(rem_proto, 2717 PJMEDIA_TP_PROFILE_RTCP_FB); 2718 } else { 2719 /* For offer, check account setting */ 2720 rtcp_cfg.dont_use_avpf = acc->cfg.rtcp_fb_cfg.dont_use_avpf || 2721 (acc->cfg.rtcp_fb_cfg.cap_count == 0 2722 && rtcp_cfg.cap_count == 0); 2723 } 2724 2679 2725 status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt, 2680 & acc->cfg.rtcp_fb_cfg, sdp,2726 &rtcp_cfg, sdp, 2681 2727 mi, rem_sdp); 2682 2728 if (status != PJ_SUCCESS) { 2683 2729 PJ_PERROR(3,(THIS_FILE, status, 2684 "Call %d media %d: Failed to encode RTCP-FB "2730 "Call %d media %d: Failed to encode RTCP-FB PLI " 2685 2731 "setting to SDP", 2686 2732 call_id, mi)); 2733 } 2734 2735 /* Add any other RTCP-FB setting configured in account setting */ 2736 if (acc->cfg.rtcp_fb_cfg.cap_count) { 2737 pj_bool_t tmp = rtcp_cfg.dont_use_avpf; 2738 rtcp_cfg = acc->cfg.rtcp_fb_cfg; 2739 rtcp_cfg.dont_use_avpf = tmp; 2740 status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt, 2741 &rtcp_cfg, sdp, 2742 mi, rem_sdp); 2743 if (status != PJ_SUCCESS) { 2744 PJ_PERROR(3,(THIS_FILE, status, 2745 "Call %d media %d: Failed to encode account " 2746 "RTCP-FB setting to SDP", 2747 call_id, mi)); 2748 } 2687 2749 } 2688 2750 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
r6093 r6106 1083 1083 goto on_error; 1084 1084 1085 /* Subscribe to video stream events */ 1086 pjmedia_event_subscribe(NULL, &call_media_on_event, 1087 call_med, call_med->strm.v.stream); 1088 1085 1089 /* Start stream */ 1086 1090 status = pjmedia_vid_stream_start(call_med->strm.v.stream); … … 1287 1291 call_med->rtp_tx_ts = stat.rtp_tx_last_ts; 1288 1292 } 1293 1294 /* Unsubscribe from video stream events */ 1295 pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, strm); 1289 1296 1290 1297 pjmedia_vid_stream_destroy(strm);
Note: See TracChangeset
for help on using the changeset viewer.