live555 做RTSP Server推送实时流的时候,花屏问题采用的解决方法
应该有不少的地方都可以优化,目前只采用了3个策略解决:
由于对live555 错中复杂的类很不熟悉,这些都是经过浅显调试的结论:
1.StreamParser.cpp
按我的理解,这个参数是代表着一帧H264数据的大小,默认150K,如果分辨率大了,很可能会超出大小,可能每一帧都会因为丢数据花屏--------->但我只是改了; 并没有实际改大分辨率验证
#define BANK_SIZE 800000 //300 -> 800
2.修改maxSize 大小
OutPacketBuffer::maxSize = 1000000; //
在H264FramedLiveSource::doGetNextFrame()中,通常会对H264做内存拷贝的操作:
memcpy(fTo ,video_buf,fMaxSize);
fTo是live555 释放出来的指针,它指向的最大内存为maxSize ,随着每一次向fTo拷贝数据,fMaxSize会从maxSize 慢慢减小,直到0,然后重新指向一个maxSize 大小的内存
因此 我看到的现象是:将maxSize 的大小从200k增加,会发现花屏的问题得到了改善,但是,隔几十秒还是会花屏
3.利用FrameSource中的fNumTruncatedBytescans
接着上一条:,随着每一次向fTo拷贝数据,fMaxSize会从maxSize 慢慢减小,直到0,然后重新指向一个maxSize 大小的内存,那么在fTo的buf即将耗尽时,最后一帧H264数据放不下了,就会把放不下的数据,我手动给丢掉,然后就花屏了!喵的
那么fNumTruncatedBytescans是FrameSource中的一个参数,意思是被舍弃的包的数目,但其实直接操作它并没有作用。只能自定义一个数目来执行我的想法:
每一次fTo耗尽的时候,把丢掉的数据保存在本地,下一次回调doGetNextFrame()时,先把丢掉的数据写进去,再把这次要写的264包放到后面。
由于H264是有NALU的,有严格的头和尾的标志;所以这样做似乎OK的
然后,live555的buf不是直接操作fTo的那个buf,也不是这个buf就只能存一帧数据,这个也是之前的错误观念
上伪代码:
void H264FramedLiveSource::doGetNextFrame()
{
int ret = 0;
int h264_total_size = 0;
int64_t timeStamp;
unsigned char video_buf[MAX_VDATA_SIZE];
memset(video_buf,0,sizeof(video_buf));
getH264Data(&h264_total_size,&timeStamp ,video_buf);
if(h264_total_size > fMaxSize) { // buff耗尽的帧
memcpy(fTo ,video_buf,fMaxSize);
memcpy(truncatedBytes, video_buf+fMaxSize,h264_total_size-fMaxSize);
fNumTruncatedBytes = h264_total_size - fMaxSize;
NumTruncatedBytes = h264_total_size - fMaxSize;
fFrameSize = fMaxSize;
}
else
{
if(NumTruncatedBytes != 0)
{
memcpy(fTo ,truncatedBytes,NumTruncatedBytes);
memcpy(fTo+NumTruncatedBytes ,video_buf,h264_total_size);
fFrameSize = h264_total_size+NumTruncatedBytes;
fNumTruncatedBytes = 0;
NumTruncatedBytes = 0;
memset(truncatedBytes,0,sizeof(truncatedBytes));
}
else
{
memset(truncatedBytes,0,sizeof(truncatedBytes));
memcpy(fTo ,video_buf,h264_total_size);
fFrameSize = h264_total_size;
fNumTruncatedBytes = 0;
NumTruncatedBytes = 0;
}
}
FramedSource::afterGetting(this);
return;
}