JRTPLIB: RTP和RTCP协议栈

RTP和RTCP

RTP协议和RTCP协议都是流媒体传输协议 都是实时流媒体传输协议的一部分
1. RTP协议规定流媒体传输的打包格式
2. RTCP协议控制流媒体传输质量

JRTPLIB是一个外国人开源的RTP项目,包括对RTP和RTCP的支持
github的仓库地址为

https://github.com/j0r1/JRTPLIB

JRTPLIB

项目有一个官方的网站 http://research.edm.uhasselt.be/jori/page/CS/Jrtplib.html

值得一提的项目的开源协议是MIT
无论是个人还是商用都没有什么顾虑

JRTPLIB依赖于JTHREAD项目 两个项目的作者是同一个
编译JRTPLIB前需要先编译JTHREAD

利用JRTPLIB接收H264-RTP流并组帧

这里展示一个使用JRTPLIB接收h264-rtp流的例子
getOneNalu是拼帧函数
int RtpRcver::getOneNalu(void *bufIn, int pktSize, int payloadLen,
                         void **bufOut, int *bufLen) {
    int rtpHdrLen = 0;
    uint8_t nalu, headf, heads, pos, fu_hdr;
    uint8_t *src = NULL, *tmp = NULL;

    *bufLen = 0;
    if (pktSize < 12 || payloadLen < 2)
        return -1;

    rtpHdrLen = pktSize - payloadLen;
    src = (uint8_t *)bufIn + 12;
    headf = *src;
    heads = *(src + 1);
    nalu = headf & 0x1f;
    pos = heads & 0xe0;
    fu_hdr = (headf & 0xe0) | (heads & 0x1f);

    if (nalu != 28) {
        *bufOut = src - 4;
        *((uint32_t *)(*bufOut)) = 0x01000000;
        *bufLen = pktSize - 12 + 4;

        return 0;
    } else {
        if (pos == 0x80) {
            *bufOut = src - 3;
            *((uint32_t *)(*bufOut)) = 0x01000000;
            *((char *)(*bufOut) + 4) = fu_hdr;
            *bufLen = pktSize - 12 + 3;
        } else if (pos == 0x40) {
            *bufOut = src + 2;
            *bufLen = pktSize - 12 - 2;
            return 0;
        } else {
            *bufOut = src + 2;
            *bufLen = pktSize - 12 - 2;
        }
    }

    return -1;
}

这是我在QT中使用QThread接收包

void RtpRcver::run() {
    int pos = 0, flag = 0, size = 0, status = 0;
    uint8_t *ptr = (uint8_t *)malloc(1024 * 100);
    RTPPacket *pkt;
    struct nalu_list *nalu_node = NULL;

    while(!mStatus) {
        status = mSess.Poll();
        if (status < 0) {
            qDebug() << "failed to exec mSess.poll";
            break;
        }

        if (mSess.GotoFirstSourceWithData()) {
            do {
                while ((pkt = mSess.GetNextPacket()) != NULL) {

                    if (pkt->GetPayloadType() == 96) {
                        flag = getOneNalu(pkt->GetPacketData(), pkt->GetPacketLength(),
                                          pkt->GetPayloadLength(), (void **)&mData, &size);
                        if (size > 0) {
                            memcpy(ptr + pos, mData, size);
                            pos += size;
                        }

                        if (flag == 0) {
#ifdef RCV_RTP_FILE_DBG
                            fwrite(ptr, pos, 1, fp);
#endif
                            qDebug() << "rcv and parser one nalu";
                            nalu_node = new(struct nalu_list);
                            nalu_node->nalu = (uint8_t *)malloc(pos);
                            if (!nalu_node->nalu) {
                                qDebug() << "failed to malloc nalu_node->nalu";
                                break;
                            }
                            nalu_node->size = pos;

                            memcpy(nalu_node->nalu, ptr, pos);
                            list_add_tail(&nalu_node->list, &mHead.list);
                            emit sigRcvRemoteNalu();
                            pos = 0;
                        }
                    } else {
                        qDebug() << "unknow payload type:" << mPkt->GetPayloadType();
                    }

                    mSess.DeletePacket(mPkt);
                }
            } while(mSess.GotoNextSourceWithData());
        }
    }
}

代码的逻辑可能比较乱,暂时先这样,过段时间再整理一下.

你可能感兴趣的:(流媒体)