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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 
Note: See TracChangeset for help on using the changeset viewer.