首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > 多媒体 >

为什么在运行大概一分钟后,接收方的视频图像开始变慢甚至停滞?该如何解决

2012-03-03 
为什么在运行大概一分钟后,接收方的视频图像开始变慢甚至停滞?我想实现一个UDP协议的网络视频程序,发送端

为什么在运行大概一分钟后,接收方的视频图像开始变慢甚至停滞?
我想实现一个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,要自己收到后重新排序。

热点排行