RTP 视频传输

RTP/RTCP 视频数据传输 直接进入正题,经过JPEG压缩后的数据时通过RTP/RTCP协议传输到网络上去的,本课题使用的是Jrtplib的RTP/RTCP协议栈,首先在网上获取Jrtplib包的源码,解压缩配置编译安装,没有bugs就ok了 在源码包里面有好几个examples,都可以借鉴。在设置Server端的时候,与TCP/IP协议不一样,首先在初始化打开的Session的时候,设置一个baseport端口,同时设置Client端的ip和port,然后再根据视频采样的频率设置时间戳,具体的设置函数都可以在examples中找到并且能很好的复用。 这里讲一下发送和接收的代码,发送和接收都是通过线程来实现的: 发送: ret = Send_rtppacket((unsigned char*)videoIn.ptframe[frameout],sizeof(struct frame_t)+headerframe->size); 在发送线程函数中直接发送ptframe[]指针指向的数据,数据大小为sizeof(struct frame_t)+headerframe->size,包含了该frame的数据,以及对该frame参数描述的数据结构。 int Send_rtppacket(unsigned char* framepointer,int framelength) { int done = 0; int flage; int sendbyte = 0; int n; do{ if(framelength > PacketMaxsize) //设置packetmaxsize: 1400 ,oversize情况下就要分割传输 flage = 0; else flage =1; if(flage = 1) { n = session.SendPacket(framepointer,framelength,26,1,1000); //发送函数 第四个参数决定是否是该frame最后 小于1400的数据 done = 1; //如果是 标示完成 sendbyte = framelength; }else{ n = session.SendPacket(framepointer,PacketMaxsize,26,0,1000); framepointer = framepointer + PacketMaxsize ; //update发送指针 framelength = framelength - PacketMaxsize ; sendbyte = sendbyte + PacketMaxsize; } if(n<0) { return -1;} RTPTime::Wait (delay); }while(!done); return sendbyte; } 接收: do { // 检索RTP数据源 sess.BeginDataAccess(); if (sess.GotoFirstSourceWithData() ) { do { RTPPacket* packet; RTPSourceData *srcdata; // 获取RTP数据报 packetflage =0; recvlength =0; //初始化接收数据 以及数据接收标示 while ((packet = sess.GetNextPacket()) != NULL && packetflage==0) { //标示为零 接收同一packet的剩余数据 //printf("Got packet !/n"); if(processpacket(*srcdata,*packet)){ packetflage = 1; //processpacket() 返回1 已经接受到所有的packet 可以调用解码,SDL显示 //printf("Debug...packetflage: %d/n",packetflage); jpegsize = readjpeg(&buf,headerframe); //printf("Debug...jpegsize: %d/n",jpegsize); if(!jpegsize && videoOk) close_sdlvideo(); if(jpegsize && !videoOk) { init_sdlvideo(); pscreen = SDL_SetVideoMode (owidth, oheight, bpp * 8,SDL_DOUBLEBUF | SDL_SWSURFACE); p=(unsigned char*)pscreen->pixels; } if(jpegsize && videoOk) { jpeg_decode(&picture,buf,&width,&height); resize (p,picture,owidth,oheight,width,height) ; SDL_WM_SetCaption (titre, NULL); SDL_Flip (pscreen); } if(SDL_PollEvent (&sdlevent)<0) goto error; } else packetflage =0; //返回0,packet还没接受完继续sess.GetNextPacket() delete packet; // 删除RTP数据报 } } while (sess.GotoNextSourceWithData()); //接收另一个packet } sess.EndDataAccess(); // 接受RTP数据 status = sess.Poll(); checkerror(status); RTPTime::Wait(RTPTime(1,0)); } while(1); int processpacket(const RTPSourceData &srcdat,const RTPPacket &rtppack) { unsigned char* payloadpointer = rtppack.GetPayloadData(); //接收该数据包数据 bool packetmarker = rtppack.HasMarker(); //察看部否是已经传完该数据包 int flage =1; //printf("Debug..........1/n"); if(!packetmarker) //未传完数据包 { memcpy(recvpointer+recvoffset,payloadpointer,rtppack.GetPayloadLength()); recvlength += rtppack.GetPayloadLength(); recvoffset += rtppack.GetPayloadLength(); //更新接收数据保存的指针 // printf("Debug..........2/n"); flage = 0; //标示接受位继续执行sess.GetNextPacket() } else{ memcpy(recvpointer +recvoffset,payloadpointer,rtppack.GetPayloadLength()); recvlength += rtppack.GetPayloadLength(); recvoffset = 0; //传完,初始化 // printf("Debug..........3/n"); } return flage; } 小结: RTP/RTCP传输数据的流程: Server端: 发送定长的数据报到Client端,发送的时候是分批以packet的形式发送到Client,就是说发送一个数据包需要几次packet发送来完成。发送成功以后发送下一个数据包,始终调用函数:session.SendPacket(); Client端: 依次循环调用sess.GetNextPacket()来接收某一数据包的packet数据,packet的到来不是按顺序到来的,完全接收到数据包所用的packets以后,RTP库在根据时间戳对接受的packet重新排序生成最终的数据包。接收数据包成功后,调用sess.GotoNextSourceWithData()开始接收下一个数据包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值