乐趣区

关于c++:SkeyePlayer渲染引擎D3DRender实现视频图像高效率渲染解决方案附源码

SkeyePlayer 播放器以其低延时播放 RTSP、RTMP 等流而闻名,而低延时播放除了低延时的拉流库以及高编解码效率外,视频图像的高速渲染也尤为重要;

本篇以及系列文章次要解说 SkeyePlayer 播放器的渲染引擎 D3DRender,该渲染引擎反对基于 GDI 和 D3D 两种渲染形式,GDI 形式也是咱们熟知的 windows 图像绘制接口,广泛利用于 win32 以及 MFC 界面编程,以及图形元素的绘制;然而因为应用纯软的 windows 零碎 api 接口进行绘制,其效率通常比拟低,而 D3D 能够启用硬件加速,所以,通常其效率会比拟高,上面咱们将具体解说 D3DRende 视频图像渲染流程。

1. D3DRender 初始化

D3DRender 库别离为 GDI 和 D3D 两种渲染模式提供不同 API 接口进行渲染初始化,调用如下代码段实现其初始化:

        // 创立 D3dRender
        if (pThread->renderFormat == GDI_FORMAT_RGB24)
        {if (NULL == pThread->d3dHandle)    RGB_InitDraw(&pThread->d3dHandle);
        }
        else if ((NULL == pThread->d3dHandle) && ((unsigned int)time(NULL)-deviceLostTime >= 2) )
        {
            D3D_FONT    font;
            memset(&font, 0x00, sizeof(D3D_FONT));
            font.bold    =    0x00;
            wcscpy(font.name, TEXT("Arial Black"));

            font.size    =    (int)(float)((width)*0.2f);// 32;
            if (pThread->showOSD)
            {font.size    =    pThread->osd.size;// 32;}
            font.width    =    (int)(float)((font.size)/2.5f);//13;
            if (NULL!=pThread->hWnd && (IsWindow(pThread->hWnd)) )
            {D3D_Initial(&pThread->d3dHandle, pThread->hWnd, width, height, 0, 1, pThread->renderFormat, &font);
        }

留神 D3D_Initial 初始化 D3D 渲染模式须要设置 OSD 叠加的相干参数,如 OSD 叠加文字的字体、大小等参数,OSD 叠加具体解说将在后续的文章中进行解说,本文不做过多赘述。

2. D3DRender 渲染一帧视频图像

D3DRender 渲染图像反对多种图像色调格局,具体如下枚举构造体所示:

// 目前反对的格局
typedef enum
{D3D_FORMAT_YUY2        =    MAKEFOURCC('Y','U','Y','2'),    //844715353            -->decode output format:    PIX_FMT_YUYV422        1
    D3D_FORMAT_YV12        =    MAKEFOURCC('Y','V','1','2'),    //842094169
    D3D_FORMAT_UYVY        =    MAKEFOURCC('U', 'Y', 'V', 'Y'),    //1498831189        -->decode output format:    PIX_FMT_UYVY422        17
    D3D_FORMAT_A8R8G8B8    =    21,                                //                    -->decode output format:    PIX_FMT_BGRA        30
    D3D_FORMAT_X8R8G8B8    =    22,                                //                    -->decode output format:    PIX_FMT_BGRA        30
    D3D_FORMAT_RGB565    =    23,                                //                    -->decode output format:    PIX_FMT_RGB565LE    44
    D3D_FORMAT_RGB555    =    25,                                //                    -->decode output format:    PIX_FMT_RGB555LE    46

    GDI_FORMAT_RGB24,
}D3D_SUPPORT_FORMAT;

其中指定色调格局 RGB24 为 GDI 渲染,其余色调格局均为 D3D 渲染形式,具体视频图像渲染调用如下:

            if (pThread->renderFormat == GDI_FORMAT_RGB24)
            {RGB_DrawData(pThread->d3dHandle, pThread->hWnd, pThread->yuvFrame[iDispalyYuvIdx].pYuvBuf, width, height, &rcSrc, pThread->ShownToScale, RGB(0x3c,0x3c,0x3c), 0, osdLines, osd);
            }
            else if (NULL != pThread->d3dHandle)
            {D3D_UpdateData(pThread->d3dHandle, 0, (unsigned char*)pThread->yuvFrame[iDispalyYuvIdx].pYuvBuf, width, height, &rcSrc, NULL, osdLines, osd);
                ret = D3D_Render(pThread->d3dHandle, pThread->hWnd, pThread->ShownToScale, &rcDst);
                if (ret < 0)
                {deviceLostTime = (unsigned int)time(NULL);
                    pThread->resetD3d = true;                        // 须要重建 D3D
                }
            }

如上代码段所示,GDI 模式通过 RGB_DrawData 函数进行渲染,D3D 模式通过 D3D_UpdateData 进行渲染,只须要传入 YUV 或者 RGB 数据缓冲区以及视频图像长宽即可,如果须要叠加 OSD 文字信息,则填充 osd 信息即可,这在后续的系列文章中会讲到。

3. D3DRender 敞开渲染

当渲染流程走完后,咱们须要关掉 D3DRender 渲染引擎,调用敞开渲染接口接口接口实现,如下代码所示:

    if (pThread->renderFormat == GDI_FORMAT_RGB24)
    {RGB_DeinitDraw(&pThread->d3dHandle);
    }
    else
    {D3D_Release(&pThread->d3dHandle);
    }
退出移动版