直接进入正题,经过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();