Ignore:
Timestamp:
Jul 17, 2018 8:11:17 AM (15 months ago)
Author:
nanang
Message:

Re #2126: Implemented incoming RTCP-FB handling, i.e: parse and notify application via PJMEDIA event framework.

File:
1 edited

Legend:

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

    r5820 r5825  
    215215{ 
    216216    pj_bzero(opt, sizeof(*opt)); 
    217  
    218     /* == just for test == */ 
    219     opt->cap_count = 4; 
    220  
    221     pj_cstr(&opt->caps[0].codec_id, "*"); 
    222     opt->caps[0].type = PJMEDIA_RTCP_FB_ACK; 
    223      
    224     pj_cstr(&opt->caps[1].codec_id, "speex/16000"); 
    225     opt->caps[1].type = PJMEDIA_RTCP_FB_NACK; 
    226      
    227     pj_cstr(&opt->caps[2].codec_id, "H264"); 
    228     opt->caps[2].type = PJMEDIA_RTCP_FB_NACK; 
    229     pj_cstr(&opt->caps[2].param, "pli"); 
    230  
    231     pj_cstr(&opt->caps[3].codec_id, "pcmu"); 
    232     opt->caps[3].type = PJMEDIA_RTCP_FB_NACK; 
    233     /* == just for test == */ 
    234217 
    235218    return PJ_SUCCESS; 
     
    581564    return PJ_SUCCESS; 
    582565} 
     566 
     567 
     568/* 
     569 * Check whether the specified payload contains RTCP feedback generic NACK 
     570 * message, and parse the payload if it does. 
     571 */ 
     572PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_nack( 
     573                                        const void *buf, 
     574                                        pj_size_t length, 
     575                                        unsigned *nack_cnt, 
     576                                        pjmedia_rtcp_fb_nack nack[]) 
     577{ 
     578    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf; 
     579    pj_uint8_t *p; 
     580    unsigned cnt, i; 
     581 
     582    PJ_ASSERT_RETURN(buf && nack_cnt && nack, PJ_EINVAL); 
     583    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL); 
     584 
     585    /* Generic NACK uses pt==RTCP_RTPFB and FMT==1 */ 
     586    if (hdr->pt != RTCP_RTPFB || hdr->count != 1) 
     587        return PJ_ENOTFOUND; 
     588 
     589    cnt = pj_ntohs((pj_uint16_t)hdr->length) - 2; 
     590    if (length < (cnt+3)*4) 
     591        return PJ_ETOOSMALL; 
     592 
     593    *nack_cnt = PJ_MIN(*nack_cnt, cnt); 
     594 
     595    p = (pj_uint8_t*)hdr + sizeof(*hdr); 
     596    for (i = 0; i < *nack_cnt; ++i) { 
     597        pj_uint16_t val; 
     598 
     599        pj_memcpy(&val, p, 2); 
     600        nack[i].pid = pj_ntohs(val); 
     601        pj_memcpy(&val, p+2, 2); 
     602        nack[i].blp = pj_ntohs(val); 
     603        p += 4; 
     604    } 
     605 
     606    return PJ_SUCCESS; 
     607} 
     608 
     609 
     610/* 
     611 * Check whether the specified payload contains RTCP feedback Picture Loss 
     612 * Indication (PLI) message. 
     613 */ 
     614PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_pli( 
     615                                        const void *buf, 
     616                                        pj_size_t length) 
     617{ 
     618    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf; 
     619 
     620    PJ_ASSERT_RETURN(buf, PJ_EINVAL); 
     621    PJ_ASSERT_RETURN(length >= 12, PJ_ETOOSMALL); 
     622 
     623    /* PLI uses pt==RTCP_PSFB and FMT==1 */ 
     624    if (hdr->pt != RTCP_PSFB || hdr->count != 1) 
     625        return PJ_ENOTFOUND; 
     626 
     627    return PJ_SUCCESS; 
     628} 
     629 
     630 
     631/* 
     632 * Check whether the specified payload contains RTCP feedback Slice Loss 
     633 * Indication (SLI) message, and parse the payload if it does. 
     634 */ 
     635PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_sli( 
     636                                        const void *buf, 
     637                                        pj_size_t length, 
     638                                        unsigned *sli_cnt, 
     639                                        pjmedia_rtcp_fb_sli sli[]) 
     640{ 
     641    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf; 
     642    pj_uint8_t *p; 
     643    unsigned cnt, i; 
     644 
     645    PJ_ASSERT_RETURN(buf && sli_cnt && sli, PJ_EINVAL); 
     646    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL); 
     647 
     648    /* PLI uses pt==RTCP_PSFB and FMT==2 */ 
     649    if (hdr->pt != RTCP_PSFB || hdr->count != 2) 
     650        return PJ_ENOTFOUND; 
     651 
     652    cnt = pj_ntohs((pj_uint16_t)hdr->length) - 2; 
     653    if (length < (cnt+3)*4) 
     654        return PJ_ETOOSMALL; 
     655 
     656    *sli_cnt = PJ_MIN(*sli_cnt, cnt); 
     657 
     658    p = (pj_uint8_t*)hdr + sizeof(*hdr); 
     659    for (i = 0; i < *sli_cnt; ++i) { 
     660        /* 'first' takes 13 bit */ 
     661        sli[i].first = (p[0] << 5) + ((p[1] & 0xF8) >> 3); 
     662        /* 'number' takes 13 bit */ 
     663        sli[i].number = ((p[1] & 0x07) << 10) + 
     664                        (p[2] << 2) + 
     665                        ((p[3] & 0xC0) >> 6); 
     666        /* 'pict_id' takes 6 bit */ 
     667        sli[i].pict_id = (p[3] & 0x3F); 
     668        p += 4; 
     669    } 
     670 
     671    return PJ_SUCCESS; 
     672} 
     673 
     674 
     675/* 
     676 * Check whether the specified payload contains RTCP feedback Reference 
     677 * Picture Selection Indication (RPSI) message, and parse the payload 
     678 * if it does. 
     679 */ 
     680PJ_DEF(pj_status_t) pjmedia_rtcp_fb_parse_rpsi( 
     681                                        const void *buf, 
     682                                        pj_size_t length, 
     683                                        pjmedia_rtcp_fb_rpsi *rpsi) 
     684{ 
     685    pjmedia_rtcp_common *hdr = (pjmedia_rtcp_common*) buf; 
     686    pj_uint8_t *p; 
     687    pj_uint8_t padlen; 
     688    pj_size_t rpsi_len; 
     689 
     690    PJ_ASSERT_RETURN(buf && rpsi, PJ_EINVAL); 
     691    PJ_ASSERT_RETURN(length >= sizeof(pjmedia_rtcp_common), PJ_ETOOSMALL); 
     692 
     693    /* RPSI uses pt==RTCP_PSFB and FMT==3 */ 
     694    if (hdr->pt != RTCP_PSFB || hdr->count != 3) 
     695        return PJ_ENOTFOUND; 
     696 
     697    rpsi_len = (pj_ntohs((pj_uint16_t)hdr->length)-2) * 4; 
     698    if (length < rpsi_len + 12) 
     699        return PJ_ETOOSMALL; 
     700 
     701    p = (pj_uint8_t*)hdr + sizeof(*hdr); 
     702    padlen = *p++; 
     703    rpsi->pt = (*p++ & 0x7F); 
     704    rpsi->rpsi_bit_len = rpsi_len*8 - 16 - padlen; 
     705    pj_strset(&rpsi->rpsi, (char*)p, (rpsi->rpsi_bit_len + 7)/8); 
     706 
     707    return PJ_SUCCESS; 
     708} 
Note: See TracChangeset for help on using the changeset viewer.