FFMPEG解码优化,过滤绿屏,灰屏问题

项目中对接gb28181码流,总会遇到一些流,在播放的时候出现绿屏或者灰屏的情况,造成这种情况的原因很多,网络丢包,乱序等等,也有可能码流本身就有问题,所以也是在网上找了很多资料目前参考两篇文章比较有参考价值.

https://blog.csdn.net/huangyifei_1111/article/details/97263485?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-13.control&dist_request_id=c6843e25-10e9-4055-b029-dfe726ae0127&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-13.control

和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;
   }

 

你可能感兴趣的:(C,C++)