Ignore:
Timestamp:
Apr 6, 2006 7:29:03 PM (18 years ago)
Author:
bennylp
Message:

Integrate (stream) quality monitoring into RTCP framework, and update all RTCP clients accordingly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r381 r390  
    3838#define ERRLEVEL                        1 
    3939#define TRACE_(expr)                    stream_perror expr 
    40  
     40#define TRC_(expr)                      PJ_LOG(4,expr) 
    4141#define PJMEDIA_MAX_FRAME_DURATION_MS   200 
    4242#define PJMEDIA_MAX_BUFFER_SIZE_MS      2000 
     
    4444#define PJMEDIA_DTMF_DURATION           1600    /* in timestamp */ 
    4545#define PJMEDIA_RTP_NAT_PROBATION_CNT   10 
     46#define PJMEDIA_RTCP_INTERVAL           5       /* seconds      */ 
    4647 
    4748 
     
    8889 
    8990    pjmedia_dir              dir;           /**< Stream direction.          */ 
    90     pjmedia_stream_stat      stat;          /**< Stream statistics.         */ 
    9191    void                    *user_data;     /**< User data.                 */ 
    9292 
     
    111111    pj_ioqueue_key_t        *rtcp_key;      /**< RTCP ioqueue key.          */ 
    112112    pj_ioqueue_op_key_t      rtcp_op_key;   /**< The pending read op key.   */ 
    113  
     113    pj_size_t                rtcp_pkt_size; /**< Size of RTCP packet buf.   */ 
     114    char                     rtcp_pkt[512]; /**< RTCP packet buffer.        */ 
     115    pj_uint32_t              rtcp_tx_time;  /**< RTCP tx time in timestamp  */ 
     116    int                      rtcp_addrlen;  /**< Address length.            */ 
    114117 
    115118    /* RFC 2833 DTMF transmission queue: */ 
     
    270273    struct pjmedia_frame frame_out; 
    271274    int ts_len; 
     275    pj_bool_t has_tx; 
    272276    void *rtphdr; 
    273277    int rtphdrlen; 
     
    279283    /* Init frame_out buffer. */ 
    280284    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
     285 
     286    /* Make compiler happy */ 
     287    frame_out.size = 0; 
    281288 
    282289    /* If we have DTMF digits in the queue, transmit the digits.  
     
    285292    if (stream->tx_dtmf_count) { 
    286293 
     294        has_tx = PJ_TRUE; 
    287295        create_dtmf_payload(stream, &frame_out); 
    288296 
     
    297305        unsigned max_size; 
    298306 
     307        has_tx = PJ_TRUE; 
    299308        max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr); 
    300309        status = stream->codec->op->encode( stream->codec, frame,  
     
    317326 
    318327        /* Just update RTP session's timestamp. */ 
     328        has_tx = PJ_FALSE; 
    319329        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    320330                                         0, 0,  
     
    322332                                         (const void**)&rtphdr,  
    323333                                         &rtphdrlen); 
    324         return PJ_SUCCESS; 
    325  
    326     } 
    327  
    328     if (status != 0) { 
     334 
     335    } 
     336 
     337    if (status != PJ_SUCCESS) { 
    329338        TRACE_((THIS_FILE, "RTP encode_rtp() error", status)); 
    330339        return status; 
    331340    } 
     341 
     342    /* Check if this is the time to transmit RTCP packet */ 
     343    if (stream->rtcp_tx_time == 0) { 
     344        stream->rtcp_tx_time = pj_ntohl(channel->rtp.out_hdr.ts) + 
     345                               PJMEDIA_RTCP_INTERVAL *  
     346                               stream->port.info.sample_rate; 
     347    } else if (pj_ntohl(channel->rtp.out_hdr.ts) >= stream->rtcp_tx_time) { 
     348         
     349        pjmedia_rtcp_pkt *rtcp_pkt; 
     350        pj_ssize_t size; 
     351        int len; 
     352 
     353        pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); 
     354        size = len; 
     355        status = pj_sock_sendto(stream->skinfo.rtcp_sock, rtcp_pkt, &size, 0, 
     356                                &stream->rem_rtcp_addr,  
     357                                sizeof(stream->rem_rtcp_addr)); 
     358        if (status != PJ_SUCCESS) { 
     359            ; 
     360        } 
     361         
     362        stream->rtcp_tx_time = pj_ntohl(channel->rtp.out_hdr.ts) + 
     363                               PJMEDIA_RTCP_INTERVAL *  
     364                               stream->port.info.sample_rate; 
     365    } 
     366 
     367    /* Do nothing if we have nothing to transmit */ 
     368    if (!has_tx) 
     369        return PJ_SUCCESS; 
    332370 
    333371    if (rtphdrlen != sizeof(pjmedia_rtp_hdr)) { 
    334372        /* We don't support RTP with extended header yet. */ 
    335373        PJ_TODO(SUPPORT_SENDING_RTP_WITH_EXTENDED_HEADER); 
    336         //TRACE_((THIS_FILE, "Unsupported extended RTP header for transmission")); 
    337         return 0; 
     374        return PJ_SUCCESS; 
    338375    } 
    339376 
     
    342379    /* Send. */ 
    343380    sent = frame_out.size+sizeof(pjmedia_rtp_hdr); 
    344     status = pj_sock_sendto(stream->skinfo.rtp_sock, channel->out_pkt, &sent, 0,  
    345                             &stream->rem_rtp_addr, sizeof(stream->rem_rtp_addr)); 
     381    status = pj_sock_sendto(stream->skinfo.rtp_sock, channel->out_pkt,  
     382                            &sent, 0, &stream->rem_rtp_addr,  
     383                            sizeof(stream->rem_rtp_addr)); 
    346384    if (status != PJ_SUCCESS) 
    347385        return status; 
    348386 
    349387    /* Update stat */ 
    350     stream->stat.enc.pkt++; 
    351     stream->stat.enc.bytes += frame_out.size+sizeof(pjmedia_rtp_hdr); 
     388    pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
    352389 
    353390    return PJ_SUCCESS; 
     
    460497        const void *payload; 
    461498        unsigned payloadlen; 
     499        pjmedia_rtp_status seq_st; 
    462500 
    463501        /* Go straight to read next packet if bytes_read == 0. 
     
    477515 
    478516 
     517        /* Inform RTCP session */ 
     518        pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), 
     519                            pj_ntohl(hdr->ts), payloadlen); 
     520 
    479521        /* Handle incoming DTMF. */ 
    480522        if (hdr->pt == stream->rx_event_pt) { 
     
    487529         * the incoming packet. 
    488530         */ 
    489         status = pjmedia_rtp_session_update(&channel->rtp, hdr); 
    490         if (status != 0 &&  
    491             status != PJMEDIA_RTP_ESESSPROBATION &&  
    492             status != PJMEDIA_RTP_ESESSRESTART)  
    493         { 
    494             TRACE_((THIS_FILE, "RTP session_update error (details follows)",  
    495                     status)); 
    496             PJ_LOG(4,(THIS_FILE,"RTP packet detail: pt=%d, seq=%d", 
    497                       hdr->pt, pj_ntohs(hdr->seq))); 
     531        pjmedia_rtp_session_update(&channel->rtp, hdr, &seq_st); 
     532        if (seq_st.status.flag.bad) { 
     533            TRC_  ((THIS_FILE,  
     534                    "RTP session_update error: badpt=%d, dup=%d, outorder=%d, " 
     535                    "probation=%d, restart=%d",  
     536                    seq_st.status.flag.badpt, 
     537                    seq_st.status.flag.dup, 
     538                    seq_st.status.flag.outorder, 
     539                    seq_st.status.flag.probation, 
     540                    seq_st.status.flag.restart)); 
    498541            goto read_next_packet; 
    499542        } 
    500  
    501  
    502         /* Update the RTCP session. */ 
    503         pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq),  
    504                             pj_ntohl(hdr->ts)); 
    505  
    506  
    507         /* Update stat */ 
    508         stream->stat.dec.pkt++; 
    509         stream->stat.dec.bytes += bytes_read; 
    510543 
    511544 
     
    572605                        pj_ssize_t bytes_read) 
    573606{ 
    574     PJ_UNUSED_ARG(key); 
     607    pjmedia_stream *stream = pj_ioqueue_get_user_data(key); 
     608    pj_status_t status; 
     609 
    575610    PJ_UNUSED_ARG(op_key); 
    576     PJ_UNUSED_ARG(bytes_read); 
     611 
     612    do { 
     613        if (bytes_read > 0) { 
     614            pjmedia_rtcp_rx_rtcp(&stream->rtcp, stream->rtcp_pkt,  
     615                                 bytes_read); 
     616        } 
     617 
     618        bytes_read = stream->rtcp_pkt_size; 
     619        stream->rtcp_addrlen = sizeof(stream->rem_rtcp_addr); 
     620        status = pj_ioqueue_recvfrom( stream->rtcp_key, 
     621                                      &stream->rtcp_op_key, 
     622                                      stream->rtcp_pkt, 
     623                                      &bytes_read, 0, 
     624                                      &stream->rem_rtcp_addr, 
     625                                      &stream->rtcp_addrlen); 
     626 
     627    } while (status == PJ_SUCCESS); 
     628 
     629    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     630        char errmsg[PJ_ERR_MSG_SIZE]; 
     631 
     632        pj_strerror(status, errmsg, sizeof(errmsg)); 
     633        PJ_LOG(4,(THIS_FILE, "Error reading RTCP packet: %s [status=%d]", 
     634                             errmsg, status)); 
     635    } 
     636 
    577637} 
    578638 
     
    659719    pjmedia_codec_param codec_param; 
    660720    pj_ioqueue_callback ioqueue_cb; 
     721    pj_uint16_t rtcp_port; 
    661722    pj_status_t status; 
    662723 
     
    691752    stream->skinfo = info->sock_info; 
    692753    stream->rem_rtp_addr = info->rem_addr; 
     754    rtcp_port = (pj_uint16_t) (pj_ntohs(info->rem_addr.sin_port)+1); 
     755    stream->rem_rtcp_addr = stream->rem_rtp_addr; 
     756    stream->rem_rtcp_addr.sin_port = pj_htons(rtcp_port); 
    693757    stream->tx_event_pt = info->tx_event_pt; 
    694758    stream->rx_event_pt = info->rx_event_pt; 
    695759    stream->last_dtmf = -1; 
    696  
    697  
    698     PJ_TODO(INITIALIZE_RTCP_REMOTE_ADDRESS); 
    699760 
    700761    /* Create mutex to protect jitter buffer: */ 
     
    739800    /* Init RTCP session: */ 
    740801 
    741     pjmedia_rtcp_init(&stream->rtcp, info->fmt.sample_rate, info->ssrc); 
     802    pjmedia_rtcp_init(&stream->rtcp, info->fmt.sample_rate,  
     803                      stream->port.info.samples_per_frame,  
     804                      info->ssrc); 
    742805 
    743806 
     
    800863    pj_ioqueue_op_key_init(&stream->rtcp_op_key, sizeof(stream->rtcp_op_key)); 
    801864 
     865    stream->rtcp_pkt_size = sizeof(stream->rtcp_pkt); 
     866 
    802867    /* Bootstrap the first recvfrom() operation. */ 
    803868    on_rx_rtcp( stream->rtcp_key, &stream->rtcp_op_key, 0); 
     
    901966 */ 
    902967PJ_DEF(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 
    903                                              pjmedia_stream_stat *stat) 
     968                                             pjmedia_rtcp_stat *stat) 
    904969{ 
    905970    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL); 
    906971 
    907     pj_memcpy(stat, &stream->stat, sizeof(pjmedia_stream_stat)); 
    908  
     972    pj_memcpy(stat, &stream->rtcp.stat, sizeof(pjmedia_rtcp_stat)); 
    909973    return PJ_SUCCESS; 
    910974} 
Note: See TracChangeset for help on using the changeset viewer.