项目中对接gb28181码流,总会遇到一些流,在播放的时候出现绿屏或者灰屏的情况,造成这种情况的原因很多,网络丢包,乱序等等,也有可能码流本身就有问题,所以也是在网上找了很多资料目前参考两篇文章比较有参考价值.
和https://blog.csdn.net/huangyifei_1111/article/details/103196797
主要两点一个是设置解码错误验证
m_pCodecCtx->err_recognition|=AV_EF_EXPLODE;
pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);
设置该标记后,如果解码校验失败则会在avcodec_decode_video2的时候返回失败,这样就可以不去解码错误的码流,这个可以过滤部分花屏的码流,但是灰屏和绿屏还是不能解决,
这时候就需要特殊的处理,处理原理就是根据灰屏和绿屏的特征,根据像素的颜色判断,整个图像有多少位灰色或者绿色,就认为该图像无效
主要代码
bool CheckY(int iwidth, int iHeight, unsigned char*Buf)
{
unsigned char * pNewPoint = Buf;
int iCountu = 0, iCountv = 0, iCountY = 0;
int iValues = 0;
unsigned char uBytes = 0;
//定位最后一行Y
pNewPoint = Buf;
//uBytes = pNewPoint[0];
//获得新的像素位置
pNewPoint = Buf + (iHeight - 8)*iwidth;
//遍历Y信息的所有高
for (int i = 0; i < 8; i++)
{
unsigned char *pNewPoint2 = pNewPoint + i*iwidth;
//遍历Y信息的宽
for (int j = 0; j < iwidth; j+=24)
{
int a = memcmp(pNewPoint2 + j, pNewPoint2 + j + 8, 8);
int b = memcmp(pNewPoint2 + j + 8, pNewPoint2 + j + 16, 8);
//判断连续两个8像素宏块,是否相同,并且在这个值范围内(0x7A~0x80)
if (a == b && b == 0 && pNewPoint2[j] > 0x7A&& pNewPoint2[j] <= 0x80)
{
printf("%d%d%d%d%d%d", pNewPoint2[0], pNewPoint2[1], pNewPoint2[2], pNewPoint2[3], pNewPoint2[4], pNewPoint2[5]);
iCountY++;
}
if (a == b && b == 0 && pNewPoint2[j] == 0x00)//判断绿屏
{
printf("%d%d%d%d%d%d", pNewPoint2[0], pNewPoint2[1], pNewPoint2[2], pNewPoint2[3], pNewPoint2[4], pNewPoint2[5]);
iCountY++;
}
}
}
if(iCountY>100)
return false;
return true;
}
使用方式
bool bRes = CheckY(m_pCodecCtx->height,m_pCodecCtx->height,m_pFrame->data[0]);
if(!bRes)
{
printf("灰屏或者绿屏不显示");
avcodec_flush_buffers(m_pCodecCtx);
return FALSE;
}