使用JRtpLib库发送实时视频流

yajundaisy1213 2011-10-08 02:13:47
刚刚接触视频流不久,现在需要将编码后的视频流(H264编码)发送到局域网接收端并显示出来,发送端我使用了Jrtplib库,进行发送,接收端通过VLC接收并播放,功能都已经完全实现,但现在有一个问题,我的视频流是实时的,但是VLC接收并播放时,总是出现停顿几秒钟的现象,停顿后就继续播,而且与实际图像有延时,大概两三秒的样子,找不出来到底是什么问题,希望有过类似经验的兄弟姐妹们帮忙看看,万分感激。。。
...全文
1152 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
backylee 2013-12-02
  • 打赏
  • 举报
回复
也碰到这个问题
神勇小胖子 2013-06-28
  • 打赏
  • 举报
回复
关注,不知道到楼主解决这个问题了么
SoftSoftSoft2008 2013-04-08
  • 打赏
  • 举报
回复
楼主可能问题出现在时间戳上。 后来我把帧速算准,视频在VLC播放出来就很流畅,平滑了。
丰哥86 2012-08-31
  • 打赏
  • 举报
回复
最近做视频监控,楼主的代码很有用,帮顶
ralf 2011-11-30
  • 打赏
  • 举报
回复
请问一下,楼主解决问题了每,交流一下
wzt226 2011-10-18
  • 打赏
  • 举报
回复
关注,帮顶。
achibana 2011-10-17
  • 打赏
  • 举报
回复
VLC 播放网络流没有QuickTime好. 可以用Quicktime试试, 写个简单的sdp文件就行.
jid_223 2011-10-16
  • 打赏
  • 举报
回复
你用什么函数读取摄像头视频的啊??
微笑的鱼 2011-10-10
  • 打赏
  • 举报
回复
先抓包看看数据包是不是一下子就到了客户端,排查一下在哪边卡住了。
hyh0512h 2011-10-10
  • 打赏
  • 举报
回复
你做得出这样的程序,应该知道调试方法把,先测试出问题发生的模块位置,一点一滴的找到出错的地方就可以。
编码,打包传输,网络接收,解码 就四个模块,先自己用UDP,别用Jrtplib,测试(说句心里话,Jrtplib我用过,真不知道哪点比UDP强,局域网看不出效果,internet卡的要死,还不如UDP丢几个包,虽然有点花屏但很流畅),当然UDP要有点控制,至少包的顺序要调整。
你提的问题,别人不可能很正确的回答你,因为哪个模块都有可能发生这种问题,关键靠自己去发现。
yajundaisy1213 2011-10-10
  • 打赏
  • 举报
回复
调用FFMEPG编码函数后就调用这个类的SendRTPH264函数,将编码后的缓冲区和长度传入该函数
yajundaisy1213 2011-10-10
  • 打赏
  • 举报
回复

#include "StdAfx.h"
#include "RTPClass.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>


//////

CRTPClass::CRTPClass(void)
{
bInitRTP = false;
}

//////////////////////////////////////////////////////////////////////////

void CRTPClass::SetRTPParam(CString ip,int port)
{
rtp_ip = ip;
rtp_port = port;

}
bool CRTPClass::InitRTP()
{
//rtp_ip = ip;
//rtp_port = port;

if ( InitSocket())
{
//RTP+RTCP库初始化SOCKET环境
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/90000.0); //时间戳单位
sessparams.SetAcceptOwnPackets(true);


uint16_t portbase = rtp_port*10; //PORT_LOCAL;
transparams.SetPortbase(portbase);

int status;

status = sess.Create(sessparams,&transparams);
if (!checkerror(status))
{
return false;
}

uint32_t destip;
destip = inet_addr(rtp_ip);
destip = ntohl(destip);
uint16_t destport = rtp_port;
RTPIPv4Address addr(destip,rtp_port);
status = sess.AddDestination(addr);
if (!checkerror(status))
{
return false;
}

sess.SetDefaultPayloadType(96);
sess.SetDefaultMark(false);
sess.SetDefaultTimestampIncrement(3600);

bInitRTP = true;
return true;
}

return false;
}
bool CRTPClass::InitSocket()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
if(Error!=0)
{
return false;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return false;
}

}
return true;

}
void CRTPClass::SendRTPH264(unsigned char* m_h264Buf,int buflen)
{
if (!bInitRTP)
{
if (!InitRTP())
{
TRACE("InitRTP fail\n");
return;
}
}

unsigned char *pbuf = new unsigned char[buflen];
memcpy(pbuf,m_h264Buf,buflen);

char sendbuf[1400];
memset(sendbuf,0,1400);

int status;

if (buflen<=MAX_RTP_PKT_LENGTH)
{
memcpy(sendbuf,pbuf,buflen);
status = sess.SendPacket((void *)sendbuf,buflen/*,payload,false,timestamp*/);

checkerror(status);

}
else if(buflen>=MAX_RTP_PKT_LENGTH)
{
//TRACE("buflen = %d\n",buflen);
//得到该nalu需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送
int k=0,l=0;
k=buflen/MAX_RTP_PKT_LENGTH;
l=buflen%MAX_RTP_PKT_LENGTH;
int t=0;//用于指示当前发送的是第几个分片RTP包

char nalHeader =pbuf[0]; // NALU 头
while(t<k||(t==k&&l>0))
{
if((0==t)||(t<k&&0!=t))//第一包到最后一包的前一包
{
sendbuf[0] = (nalHeader & 0x60)|28;
sendbuf[1] = (nalHeader & 0x1f);
if (0==t)
{
sendbuf[1] |= 0x80;
}

memcpy(sendbuf+2,&pbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH+2);


status = sess.SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2/*,payload,false,timestamp*/);

checkerror(status);

t++;

}
//最后一包
else if((k==t&&l>0)||(t==(k-1)&&l==0)
{

int iSendLen;
if (l>0)
{
iSendLen = buflen-t*MAX_RTP_PKT_LENGTH;
}
else
iSendLen = MAX_RTP_PKT_LENGTH;

sendbuf[0] = (nalHeader & 0x60)|28;
sendbuf[1] = (nalHeader & 0x1f);
sendbuf[1] |= 0x40;

memcpy(sendbuf+2,&pbuf[t*MAX_RTP_PKT_LENGTH],iSendLen+2);
//TRACE("start = %d,len = %d\n",t*MAX_RTP_PKT_LENGTH,iSendLen);
status = sess.SendPacket((void *)sendbuf,iSendLen+2/*,payload,false,timestamp*/);

checkerror(status);
t++;
// Sleep(100);
}
}

#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif
RTPTime::Wait(RTPTime(0,500)); //第一个参数为秒,第二个参数为毫秒
}

delete []pbuf;

}
void CRTPClass::CloseSocket()
{

if (bInitRTP)
{

//发送一个BYE包离开会话,最多等待3秒钟,超时则不发送
sess.BYEDestroy(RTPTime(3,0),0,0);

#ifdef WIN32
WSACleanup();
#endif // WIN32
}
}

bool CRTPClass::checkerror(int rtperr)
{
if (rtperr < 0)
{
TRACE("ERROR:%s\n",RTPGetErrorString(rtperr));
return false;
}
return true;
}
yajundaisy1213 2011-10-10
  • 打赏
  • 举报
回复
谢谢楼上几位的回答,可能我问的不够具体
编码和发送,都是保证每秒钟25帧处理的,但是用JRTPLIB发送后,用VCL播放,就出现丢帧和延时了,大概2、3秒吧
我编码和发送即使需要时间处理,但也不可能延时2、3秒
我之前自己手动封装RTP包然后发送,就不会出现这么大延时,但是视频往往在播放时会中断,中断后就不能继续播放了,所以才想到加上RTCP协议,就用了JRTPLIB库了。
稍后我会把代码发上来,大家帮忙看一下。。
UDX协议 2011-10-09
  • 打赏
  • 举报
回复
丢包,解码失败的原因。
yajundaisy1213 2011-10-09
  • 打赏
  • 举报
回复
帖子沉了。。。恳求各位帮忙解答。。。
yajundaisy1213 2011-10-08
  • 打赏
  • 举报
回复
接收端用VLC播放时,视频不流畅,总是中断,跳帧。。这是怎么回事啊,整体还有延时。。
yajundaisy1213 2011-10-08
  • 打赏
  • 举报
回复
是不是我描述的很混乱啊。。

2,542

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧