RTP协议和RTCP协议都是流媒体传输协议 都是实时流媒体传输协议的一部分
1. RTP协议规定流媒体传输的打包格式
2. RTCP协议控制流媒体传输质量
JRTPLIB是一个外国人开源的RTP项目,包括对RTP和RTCP的支持
github的仓库地址为
https://github.com/j0r1/JRTPLIB
项目有一个官方的网站 http://research.edm.uhasselt.be/jori/page/CS/Jrtplib.html
值得一提的项目的开源协议是MIT
无论是个人还是商用都没有什么顾虑
JRTPLIB依赖于JTHREAD项目 两个项目的作者是同一个
编译JRTPLIB前需要先编译JTHREAD
这里展示一个使用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());
}
}
}
代码的逻辑可能比较乱,暂时先这样,过段时间再整理一下.