为什么在运行大概一分钟后,接收方的视频图像开始变慢甚至停滞?
我想实现一个UDP协议的网络视频程序,
发送端的GRAPH是:VideoCapture-> DivX;)Fast-Motion-> NetSender
接收端的GRAPH是:NetRecv-> DivX Devoder-> VideoRender
我的思路是:NetSender接到一个 MediaSample后,通过GetPoint和GetActualDataLength得到视频帖数据和实际长度,然后对数据按1024长度进行分片发送。其算法是:
#define LEN_PIECE1024
typedef struct _UDPMediaPacket//UDP数据包结构
{
DWORDdwFrameNo;//帧序号
WORDwMaxPiece;//本帧共多少片
WORDwPieceNo;//本片序号
CHARData[LEN_PIECE];//分片的压缩视频数据
}UDPMEDIAPACKET, *LPUDPMEDIAPACKET;
{
...
UDPMEDIAPACKET UDPMediaPacket;
UDPMediaPacket.dwFrameNo = m_nFrameVideo;//类成员变量,记录从发送开始到当前的帧序号
m_nFrameVideo ++;//帧序号加1
BYTE *pSourceBuf = NULL;
pSample-> GetPointer(&pSourceBuf);//取压缩视频数据起始指针
int nSampleLength = pSample-> GetActualDataLength();//取帧数据长度
if ((nSampleLength % LEN_PIECE) > 0)//计算本帧共多少片
{
UDPMediaPacket.wMaxPiece = 1 + nSampleLength / LEN_PIECE;
}
else
{
UDPMediaPacket.wMaxPiece = nSampleLength / LEN_PIECE;
}
SOCKADDR_IN remote;
remote.sin_addr.S_un.S_addr = ...
remote.sin_family = AF_INET;
remote.sin_port = ...;
int nPieceNo = 0, nByteSent = 0;
while (nSampleLength > 0)
{
UDPMediaPacket.wPieceNo = nPieceNo;
memset(UDPMediaPacket.Data, 0, LEN_PIECE);
int nLenPacket = 0;
if (nSampleLength > LEN_PIECE)
{
nLenPacket = LEN_PIECE;
}
else
{
nLenPacket = nSampleLength;
}
CopyMemory(UDPMediaPacket.Data, pSourceBuf, nLenPacket);
nByteSent = sendto(socket, (char*)&UDPMediaPacket, nLenPacket + 8, 0, (SOCKADDR*)&remote, sizeof(remote));
nByteSent -= 8;
nSampleLength -= nByteSent;
pSourceBuf += nByteSent;
nPieceNo ++;
}
pSample-> Release();//本帧发送完毕
...
}
在接收端的思路是,根据接收到的UDP包中包含的帧、片序号进行拼帧,考虑UDP包的无序性,如果收到的数据帧序号错或者片丢失,则丢弃本帧,始终以完整的帧递增地交给DivX Devoder解码。其算法是:
DWORD dwFrame = 0;
WORD wPiece = 0;
int nLenVideoBuf = 0;
BYTE VideoBuf[304130], *pVideoBuf = NULL;
pVideoBuf = VideoBuf;
while(...)
{
memset(Buf, 0, 1024);
nBytesRecved = recvfrom(socket, (char*)Buf, 1024, 0, (SOCKADDR*)&remote, &dwSender);
if (nBytesRecved <= 0)
{
continue;
}
else
{
nBytesRecved -= 8;
pUDPMediaPacket = (LPUDPMEDIAPACKET)Buf;
if ((pUDPMediaPacket-> dwFrameNo == dwFrame) &&//收到的数据帧序号与片序号与应该接收的一致
(pUDPMediaPacket-> wPieceNo == wPiece))
{
CopyMemory(pVideoBuf, pUDPMediaPacket-> Data, nBytesRecved);
pVideoBuf += nBytesRecved;
nLenVideoBuf += nBytesRecved;
if (pUDPMediaPacket-> wPieceNo == (pUDPMediaPacket-> wMaxPiece - 1))//收到完整一帧
{
pSplFilter-> DistributeData(VideoBuf, nLenVideoBuf);//交NetRecv和DivX Decoder处理
dwFrame ++;
wPiece = 0;
pVideoBuf = VideoBuf;
nLenVideoBuf = 0;
}
else
{
wPiece ++;
}
}
else
{
dwFrame = pUDPMediaPacket-> dwFrameNo + 1;
wPiece = 0;
pVideoBuf = VideoBuf;
nLenVideoBuf = 0;
}
}
Sleep(15);
}
请问为什么在运行大概一分钟后,接收方的视频图像开始变慢甚至停滞?想知道哪些原因可能造成这个现象?谢谢。
[解决办法]
如果是在局域网中还发生这种现象,那肯定是网传部分没写好。可以试一下用ffmpeg decoder 替代解压的filter。接受端是否有缓存?
[解决办法]
ok,我来回答这个问题,根据我的经验,出现这样的问题很可能是实践戳的问题,你在你的解码filter的 Transform函数的最后,将sample的实践戳设置成NULL,like this, pOut-> SetTime(NULL,NULL); ,你先试一下这样行不?,如果不行,再考虑是否recv filter有没有问题
[解决办法]
变慢甚至停滞,应该是丢帧处理的不好,一般网速肯定达不到传完整视频数据,所以在发送端设缓冲,满了之后就丢一部分。丢的话,I和后面的PB都丢掉,直到下一个I帧出现,否则可能会有mosaic.
次序错是正常的,因为你用的是UDP,要自己收到后重新排序。