Changeset 6106


Ignore:
Timestamp:
Nov 13, 2019 9:11:04 AM (4 years ago)
Author:
nanang
Message:

Close #1437: Video keyframe request/response using RTCP-FB PLI.

Location:
pjproject/trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r6105 r6106  
    466466 
    467467/** 
    468  * Interval to send RTCP packets, in msec 
     468 * Interval to send regular RTCP packets, in msec. 
    469469 */ 
    470470#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*/ 
    472481#endif 
    473482 
     
    15281537 
    15291538/** 
     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/** 
    15301549 * Specify minimum delay of video decoding, in milliseconds. Lower value may 
    15311550 * degrade video quality significantly in a bad network environment (e.g: 
  • pjproject/trunk/pjmedia/include/pjmedia/event.h

    r6085 r6106  
    2626#include <pjmedia/audiodev.h> 
    2727#include <pjmedia/format.h> 
     28#include <pjmedia/rtcp_fb.h> 
    2829#include <pjmedia/signatures.h> 
    2930#include <pjmedia/videodev.h> 
     
    297298        /** Media transport error event data */ 
    298299        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; 
    299303 
    300304        /** Pointer to storage to user event data, if it's outside 
  • pjproject/trunk/pjmedia/include/pjmedia/rtcp_fb.h

    r5825 r6106  
    136136    /** 
    137137     * 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. 
    142143     * 
    143      * Default: PJ_FALSE. 
     144     * Default: PJ_TRUE. 
    144145     */ 
    145146    pj_bool_t                dont_use_avpf; 
     
    295296 
    296297/** 
     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 */ 
     312PJ_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/** 
    297323 * Build an RTCP Feedback Generic NACK packet. This packet can be appended to 
    298324 * other RTCP packets, e.g: RTCP RR/SR, to compose a compound RTCP packet. 
  • pjproject/trunk/pjmedia/include/pjmedia/types.h

    r5820 r6106  
    306306 */ 
    307307PJ_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 */ 
     317PJ_DECL(pjmedia_type) pjmedia_get_type(const pj_str_t *name); 
     318 
    308319 
    309320/** 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_codec.h

    r3956 r6106  
    525525/** 
    526526 * 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. 
    528529 * 
    529530 * @param info      The codec info 
     
    541542 * Find codecs by the unique codec identifier. This function will find 
    542543 * 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. 
    545546 * 
    546547 * @param mgr       The codec manager instance. If NULL, the default codec 
  • pjproject/trunk/pjmedia/include/pjmedia/vid_stream.h

    r5788 r6106  
    3030#include <pjmedia/port.h> 
    3131#include <pjmedia/rtcp.h> 
     32#include <pjmedia/rtcp_fb.h> 
    3233#include <pjmedia/transport.h> 
    3334#include <pjmedia/vid_codec.h> 
     
    157158                                         will be calculated from RTP.       */ 
    158159    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.             */ 
    159162    unsigned            tx_pt;      /**< Outgoing codec paylaod type.       */ 
    160163    unsigned            rx_pt;      /**< Incoming codec paylaod type.       */ 
  • pjproject/trunk/pjmedia/src/pjmedia/rtcp.c

    r5919 r6106  
    780780    //pjmedia_rtcp_fb_rpsi rpsi; 
    781781    pjmedia_event ev; 
    782     pjmedia_event_rx_rtcp_fb_data ev_data; 
    783782    pj_timestamp ts_now; 
    784783 
    785784    pj_get_timestamp(&ts_now); 
    786     pj_bzero(&ev_data, sizeof(ev_data)); 
    787785 
    788786    if (pjmedia_rtcp_fb_parse_nack(pkt, size, &cnt, nack)==PJ_SUCCESS) 
    789787    { 
    790788        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]; 
    796791        pjmedia_event_publish(NULL, sess, &ev, 0); 
    797792 
    798         /*  For other FB type implementations later 
    799793    } else if (pjmedia_rtcp_fb_parse_pli(pkt, size)==PJ_SUCCESS) 
    800794    { 
     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 
    801801    } else if (pjmedia_rtcp_fb_parse_sli(pkt, size, &cnt, sli)==PJ_SUCCESS) 
    802802    { 
  • pjproject/trunk/pjmedia/src/pjmedia/rtcp_fb.c

    r5827 r6106  
    2222#include <pjmedia/endpoint.h> 
    2323#include <pjmedia/errno.h> 
     24#include <pjmedia/vid_codec.h> 
    2425#include <pj/assert.h> 
    2526#include <pj/log.h> 
     
    215216{ 
    216217    pj_bzero(opt, sizeof(*opt)); 
     218    opt->dont_use_avpf = PJ_TRUE; 
    217219 
    218220    return PJ_SUCCESS; 
     
    332334    pjmedia_codec_mgr *codec_mgr; 
    333335    unsigned j, cnt = 0; 
     336    pjmedia_type type = PJMEDIA_TYPE_UNKNOWN; 
    334337    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; 
    335342 
    336343    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     
    339346        pt = pj_strtoul(&m->desc.fmt[j]); 
    340347        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            } 
    348364        } else { 
    349365            pjmedia_sdp_attr *a; 
     
    356372            if (status != PJ_SUCCESS) 
    357373                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" */ 
    359391                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); 
    369394            } 
    370395        } 
     
    396421    PJ_UNUSED_ARG(sdp_remote); 
    397422 
    398     PJ_ASSERT_RETURN(pool && endpt&& opt && sdp_local, PJ_EINVAL); 
     423    PJ_ASSERT_RETURN(pool && endpt && opt && sdp_local, PJ_EINVAL); 
    399424    PJ_ASSERT_RETURN(med_idx < sdp_local->media_count, PJ_EINVAL); 
    400425 
     
    403428        unsigned proto = pjmedia_sdp_transport_get_proto(&m->desc.transport); 
    404429        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; 
    411434        } 
    412435    } 
     
    477500                                    pjmedia_rtcp_fb_info *info) 
    478501{ 
     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 */ 
     509PJ_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{ 
    479518    unsigned sci_cnt = PJMEDIA_MAX_SDP_FMT; 
    480519    sdp_codec_info_t sci[PJMEDIA_MAX_SDP_FMT]; 
     
    487526    PJ_ASSERT_RETURN(pool && endpt && opt==NULL && sdp, PJ_EINVAL); 
    488527    PJ_ASSERT_RETURN(med_idx < sdp->media_count, PJ_EINVAL); 
     528    PJ_ASSERT_RETURN(pt <= 127, PJ_EINVAL); 
    489529 
    490530    m = sdp->media[med_idx]; 
     
    515555 
    516556        if (pj_strcmp2(&token, "*") == 0) { 
    517             /* Asterisk (all codecs) */ 
     557            /* All codecs */ 
    518558            codec_id = "*"; 
    519559        } 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); 
    522562            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_)) { 
    524565                    codec_id = sci[j].id; 
    525566                    break; 
     
    528569        } 
    529570 
    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 */ 
    531572        if (!codec_id) 
    532573            continue; 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r6098 r6106  
    22522252    { 
    22532253        pjmedia_event_rx_rtcp_fb_data *data = (pjmedia_event_rx_rtcp_fb_data*) 
    2254                                               event->data.ptr; 
     2254                                              &event->data.rx_rtcp_fb; 
    22552255 
    22562256        /* Application not configured to listen to NACK, discard this event */ 
     
    22622262 
    22632263    /* 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); 
    22652266} 
    22662267 
     
    27432744#endif 
    27442745 
    2745     /* Check if we should send RTCP-FB generic NACK for this codec */ 
     2746    /* Check if we should send RTCP-FB */ 
    27462747    if (stream->si.rem_rtcp_fb.cap_count) { 
    27472748        pjmedia_rtcp_fb_info *rfi = &stream->si.rem_rtcp_fb; 
    2748         char cid[32]; 
    27492749        unsigned i; 
    2750  
    2751         pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid)); 
    27522750 
    27532751        for (i = 0; i < rfi->cap_count; ++i) { 
    27542752            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) 
    27572754            { 
    27582755                stream->send_rtcp_fb_nack = PJ_TRUE; 
     2756                PJ_LOG(4,(stream->port.info.name.ptr, 
     2757                          "Send RTCP-FB generic NACK")); 
    27592758                break; 
    27602759            } 
     
    27622761    } 
    27632762 
    2764     /* Check if we handle incoming RTCP-FB generic NACK for this codec */ 
     2763    /* Check if we should process incoming RTCP-FB */ 
    27652764    stream->rtcp_fb_nack_cap_idx = -1; 
    27662765    if (stream->si.loc_rtcp_fb.cap_count) { 
    27672766        pjmedia_rtcp_fb_info *lfi = &stream->si.loc_rtcp_fb; 
    2768         char cid[32]; 
    27692767        unsigned i; 
    2770  
    2771         pjmedia_codec_info_to_id(&stream->si.fmt, cid, sizeof(cid)); 
    27722768 
    27732769        for (i = 0; i < lfi->cap_count; ++i) { 
    27742770            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) 
    27772772            { 
    27782773                stream->rtcp_fb_nack_cap_idx = i; 
     2774                PJ_LOG(4,(stream->port.info.name.ptr, 
     2775                          "Receive RTCP-FB generic NACK")); 
    27792776                break; 
    27802777            } 
  • pjproject/trunk/pjmedia/src/pjmedia/stream_info.c

    r5820 r6106  
    2424#include <pj/rand.h> 
    2525 
    26 static const pj_str_t ID_AUDIO = { "audio", 5}; 
    2726static const pj_str_t ID_IN = { "IN", 2 }; 
    2827static const pj_str_t ID_IP4 = { "IP4", 3}; 
     
    387386 
    388387    /* 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) 
    390389        return PJMEDIA_EINVALIMEDIATYPE; 
    391390 
     
    602601 
    603602    /* 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); 
    606605    if (status != PJ_SUCCESS) 
    607606        return status; 
    608607 
    609608    /* 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); 
    612611    if (status != PJ_SUCCESS) 
    613612        return status; 
  • pjproject/trunk/pjmedia/src/pjmedia/types.c

    r4411 r6106  
    2020#include <pjmedia/types.h> 
    2121#include <pj/assert.h> 
     22#include <pj/string.h> 
    2223 
    23 /** 
     24 
     25/* Map structure for pjmedia type names */ 
     26typedef struct pjmedia_type_map { 
     27    pjmedia_type type; 
     28    const char* name; 
     29} pjmedia_type_map; 
     30 
     31/* Internal mapping for pjmedia type names */ 
     32static 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/* 
    2441 * Utility function to return the string name for a pjmedia_type. 
    25  * 
    26  * @param t             The media type. 
    27  * 
    28  * @return              String. 
    2942 */ 
    3043PJ_DEF(const char*) pjmedia_type_name(pjmedia_type t) 
    3144{ 
    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)); 
    4146    pj_assert(PJMEDIA_TYPE_UNKNOWN == 4); 
    4247 
    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; 
    4550    else 
    4651        return "??"; 
    4752} 
     53 
     54/* 
     55 * Utility function to return the media type for a media name string. 
     56 */ 
     57PJ_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  
    410410 
    411411/* 
    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. 
    416413 */ 
    417414PJ_DEF(pj_status_t) pjmedia_vid_codec_mgr_find_codecs_by_id( 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream.c

    r6098 r6106  
    2020#include <pjmedia/errno.h> 
    2121#include <pjmedia/event.h> 
     22#include <pjmedia/jbuf.h> 
    2223#include <pjmedia/rtp.h> 
    2324#include <pjmedia/rtcp.h> 
    24 #include <pjmedia/jbuf.h> 
     25#include <pjmedia/rtcp_fb.h> 
    2526#include <pj/array.h> 
    2627#include <pj/assert.h> 
     
    124125 
    125126    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.         */ 
    128130    pj_bool_t                initial_rr;    /**< Initial RTCP RR sent       */ 
    129131    pj_bool_t                rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/ 
     
    150152    pj_bool_t                force_keyframe;/**< Forced to encode keyframe? */ 
    151153    unsigned                 num_keyframe;  /**< The number of keyframe needed 
    152                                                  to be sent, after the stream 
    153                                                  is created. */ 
     154                                                 to be sent, e.g: after the 
     155                                                 stream is created. */ 
    154156    pj_timestamp             last_keyframe_tx; 
    155157                                            /**< Timestamp of the last 
     
    187189    pj_sockaddr              rtp_src_addr;  /**< Actual packet src addr.    */ 
    188190    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.    */ 
    189202 
    190203#if TRACE_RC 
     
    204217static pj_status_t send_rtcp(pjmedia_vid_stream *stream, 
    205218                             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); 
    207222 
    208223static void on_rx_rtcp( void *data, 
     
    399414            /* Republish this event later from get_frame(). */ 
    400415            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            } 
    401424            return PJ_SUCCESS; 
    402425 
     
    404427            break; 
    405428        } 
    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 
    410468 
    411469/** 
     
    502560static pj_status_t send_rtcp(pjmedia_vid_stream *stream, 
    503561                             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) 
    505565{ 
    506566    void *sr_rr_pkt; 
     
    513573    pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 
    514574 
    515     if (with_sdes || with_bye) { 
     575    if (with_sdes || with_bye || with_fb_nack || with_fb_pli) { 
    516576        pkt = (pj_uint8_t*) stream->out_rtcp_pkt; 
    517577        pj_memcpy(pkt, sr_rr_pkt, len); 
     
    522582    } 
    523583 
    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; 
    525586    if (with_sdes) { 
    526587        pjmedia_rtcp_sdes sdes; 
     
    542603    /* Build RTCP BYE packet */ 
    543604    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; 
    547606        status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len, 
    548607                                             &bye_len, NULL); 
     
    555614    } 
    556615 
     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 
    557642    /* Send! */ 
    558643    status = pjmedia_transport_send_rtcp(stream->transport, pkt, len); 
     
    575660 * This function is can be called by either put_frame() or get_frame(), 
    576661 * 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 */ 
     664static 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). 
    583671     */ 
    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    { 
    591689        pj_status_t status; 
    592690 
    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); 
    594694        if (status != PJ_SUCCESS) { 
    595695            PJ_PERROR(4,(stream->name.ptr, status, 
     
    597697        } 
    598698 
    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--; 
    600709    } 
    601710} 
     
    841950    pj_mutex_unlock( stream->jb_mutex ); 
    842951 
     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    } 
    843965 
    844966    /* Check if now is the time to transmit RTCP SR/RR report. 
     
    848970     */ 
    849971    if (stream->dir == PJMEDIA_DIR_DECODING || stream->enc->paused) { 
    850         check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 
     972        check_tx_rtcp(stream); 
    851973    } 
    852974 
     
    869991    if (stream->rtcp.received >= 10 && !stream->initial_rr) { 
    870992        status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, 
    871                            PJ_FALSE); 
     993                           PJ_FALSE, PJ_FALSE, PJ_FALSE); 
    872994        if (status != PJ_SUCCESS) { 
    873995            PJ_PERROR(4,(stream->name.ptr, status, 
     
    9241046    unsigned pkt_cnt = 0; 
    9251047    pj_timestamp initial_time; 
     1048    pj_timestamp now; 
    9261049    pj_timestamp null_ts ={{0}}; 
    9271050 
     
    9671090 
    9681091    /* Check if need to send keyframe. */ 
     1092    pj_get_timestamp(&now); 
    9691093    if (stream->num_keyframe && 
    9701094        (pj_cmp_timestamp(&null_ts, &stream->last_keyframe_tx) != 0)) 
    9711095    { 
    9721096        unsigned elapse_time; 
    973         pj_timestamp now; 
    974  
    975         pj_get_timestamp(&now); 
    9761097 
    9771098        elapse_time = pj_elapsed_msec(&stream->last_keyframe_tx, &now); 
    978  
    9791099        if (elapse_time > stream->info.sk_cfg.interval) 
    9801100        { 
     
    9861106    /* Init encoding option */ 
    9871107    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    { 
    9891112        /* Force encoder to generate keyframe */ 
    9901113        enc_opt.force_keyframe = PJ_TRUE; 
     
    10131136    pj_get_timestamp(&initial_time); 
    10141137 
    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) 
    10181140    { 
    10191141        stream->last_keyframe_tx = initial_time; 
     1142        TRC_((channel->port.info.name.ptr, "Keyframe generated")); 
    10201143    } 
    10211144 
     
    11301253     */ 
    11311254    if (stream->dir != PJMEDIA_DIR_DECODING) { 
    1132         check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 
     1255        check_tx_rtcp(stream); 
    11331256    } 
    11341257 
     
    16371760    stream->dir = info->dir; 
    16381761    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; 
    16411763    stream->rtcp_sdes_bye_disabled = info->rtcp_sdes_bye_disabled; 
    16421764 
     
    18161938 
    18171939        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); 
    18181944    } 
    18191945 
    18201946    /* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES, 
    1821      * BYE, and XR. 
     1947     * BYE, Feedback, and XR. 
    18221948     */ 
    18231949    stream->out_rtcp_pkt_size =  sizeof(pjmedia_rtcp_sr_pkt) + 
    18241950                                 sizeof(pjmedia_rtcp_common) + 
    18251951                                 (4 + (unsigned)stream->cname.slen) + 
    1826                                  32; 
     1952                                 32 + 32; 
    18271953    if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU) 
    18281954        stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU; 
     
    18972023    stream->info.codec_param = pjmedia_vid_codec_param_clone( 
    18982024                                                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    } 
    18992068 
    19002069    /* Success! */ 
     
    19312100#endif 
    19322101 
     2102    /* Unsubscribe events from RTCP */ 
     2103    pjmedia_event_unsubscribe(NULL, &stream_event_cb, stream, &stream->rtcp); 
     2104 
    19332105    /* Send RTCP BYE (also SDES) */ 
    19342106    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); 
    19362108    } 
    19372109 
     
    21732345                                                pjmedia_vid_stream *stream) 
    21742346{ 
     2347    pj_timestamp now; 
     2348 
    21752349    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
    21762350 
     
    21782352        return PJ_EINVALIDOP; 
    21792353 
     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 
    21802361    stream->force_keyframe = PJ_TRUE; 
    21812362 
     
    21922373    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
    21932374 
    2194     return send_rtcp(stream, PJ_TRUE, PJ_FALSE); 
     2375    return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE, PJ_FALSE); 
    21952376} 
    21962377 
     
    22052386 
    22062387    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); 
    22082389    } 
    22092390 
  • pjproject/trunk/pjmedia/src/pjmedia/vid_stream_info.c

    r5820 r6106  
    2525#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 
    2626 
    27 static const pj_str_t ID_VIDEO = { "video", 5}; 
    2827static const pj_str_t ID_IN = { "IN", 2 }; 
    2928static const pj_str_t ID_IP4 = { "IP4", 3}; 
     
    217216 
    218217    /* 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) 
    220219        return PJMEDIA_EINVALIMEDIATYPE; 
    221220 
     
    403402    si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 
    404403 
     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 
    405416    return status; 
    406417} 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r6097 r6106  
    861861     * the call. Value is bitmask of #pjsua_vid_req_keyframe_method. 
    862862     * 
    863      * Default: PJSUA_VID_REQ_KEYFRAME_SIP_INFO 
     863     * Default: (PJSUA_VID_REQ_KEYFRAME_SIP_INFO |  
     864     *           PJSUA_VID_REQ_KEYFRAME_RTCP_PLI) 
    864865     */ 
    865866    unsigned         req_keyframe_method; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r6083 r6106  
    618618    opt->vid_cnt = 1; 
    619619    opt->req_keyframe_method = PJSUA_VID_REQ_KEYFRAME_SIP_INFO | 
    620                              PJSUA_VID_REQ_KEYFRAME_RTCP_PLI; 
     620                               PJSUA_VID_REQ_KEYFRAME_RTCP_PLI; 
    621621#endif 
    622622} 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r6093 r6106  
    13361336        const pjmedia_sdp_media *m = sdp->media[i]; 
    13371337        const pjmedia_sdp_conn *c; 
    1338         static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
     1338        pj_uint32_t proto; 
    13391339 
    13401340        /* Skip different media */ 
     
    13471347 
    13481348        /* 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        { 
    13501352            switch (use_srtp) { 
    13511353            case PJMEDIA_SRTP_MANDATORY: 
     
    13581360                break; 
    13591361            } 
    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        { 
    13611364            switch (use_srtp) { 
    13621365            case PJMEDIA_SRTP_MANDATORY: 
     
    14821485pj_status_t on_media_event(pjmedia_event *event, void *user_data) 
    14831486{ 
     1487    char ev_name[5]; 
    14841488    pj_status_t status = PJ_SUCCESS; 
    14851489 
    14861490    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)); 
    14871495 
    14881496    /* Forward the event */ 
     
    15001508    pjsua_call_media *call_med = (pjsua_call_media*)user_data; 
    15011509    pjsua_call *call = call_med? call_med->call : NULL; 
     1510    char ev_name[5]; 
    15021511    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 
    15041520    switch(event->type) { 
    15051521        case PJMEDIA_EVENT_KEYFRAME_MISSING: 
     
    26752691        } 
    26762692 
    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 
    26792725            status = pjmedia_rtcp_fb_encode_sdp(pool, pjsua_var.med_endpt, 
    2680                                                 &acc->cfg.rtcp_fb_cfg, sdp, 
     2726                                                &rtcp_cfg, sdp, 
    26812727                                                mi, rem_sdp); 
    26822728            if (status != PJ_SUCCESS) { 
    26832729                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 " 
    26852731                             "setting to SDP", 
    26862732                             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                } 
    26872749            } 
    26882750        } 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c

    r6093 r6106  
    10831083            goto on_error; 
    10841084 
     1085        /* Subscribe to video stream events */ 
     1086        pjmedia_event_subscribe(NULL, &call_media_on_event, 
     1087                                call_med, call_med->strm.v.stream); 
     1088 
    10851089        /* Start stream */ 
    10861090        status = pjmedia_vid_stream_start(call_med->strm.v.stream); 
     
    12871291        call_med->rtp_tx_ts = stat.rtp_tx_last_ts; 
    12881292    } 
     1293 
     1294    /* Unsubscribe from video stream events */ 
     1295    pjmedia_event_unsubscribe(NULL, &call_media_on_event, call_med, strm); 
    12891296 
    12901297    pjmedia_vid_stream_destroy(strm); 
Note: See TracChangeset for help on using the changeset viewer.