繁体   English   中英

使用 Intel Quick Sync 和 Opencv 的实时视频编码速度很慢

[英]Live Video Encoding Using Intel Quick Sync and Opencv Is Slow

我想开发一种软​​件,从 4K 相机中获取帧并同时对其进行编码。 现在我可以获取帧并将其压缩为 .h264 文件。 但是,问题是,我想从我的视频中获得 10 FPS。(我的意思是视频最终变成 10 FPS,但是在编码过程中,它并没有得到所有的帧。(我在 3-5 FPS 之间) .当我挖掘代码时,我意识到,编码功能还可以,但转换BGR-> YUV的功能很慢。另外,在我的情况下,这个软件有一台专用的计算机和相机。那台计算机只有一个英特尔集成 GPU。(因此,无法将 FFMPEG 与 NVIDIA GPU 一起使用。)我怎样才能让它更快?这是我正在使用的代码:` int main() {

Mat frame;
VideoCapture vcap(0);
vcap.set(3, 3840);
vcap.set(4, 2160);

if (!vcap.isOpened()) {
    std::cout << "Error opening video stream or file" << std::endl;
    return -1;
}


int frame_width = vcap.get(3);
int frame_height = vcap.get(4);
VideoWriter video;
std::cout << video.open("out.h264", CAP_INTEL_MFX, VideoWriter::fourcc('H', '2', '6', '4'), 10, Size(frame_width, frame_height), true);
for (;;) {

    vcap >> frame;
    video.write(frame);
}


return  -1;

}`

转换函数 BGR->YUV 大约需要 0.20 秒(~5 FPS)。 编码功能大约需要 0.045(~20FPS) 秒。

我在想编码需要时间,但显然转换部分需要更多时间,这很奇怪。 必须有一个解决方案。

GPU:英特尔(R) UDH 显卡 620

CPU:英特尔酷睿 i5-8350U 1.70GHZ(8 核)

好的,这是来自 OpenCV 的 write_one() 函数,它将帧转换为 YUV 并对其进行编码。这个函数在每一帧中都被调用。 名为 cvtBGRtoTwoPlaneYUV() 的函数从 BGR->YUV 进行转换。(TAKES 200 MS)

    bool VideoWriter_IntelMFX::write_one(cv::InputArray bgr)
{
   
 mfxStatus res;
    mfxFrameSurface1 *workSurface = 0;
    mfxSyncPoint sync;
    clock_t start1 = clock();
    if (!bgr.empty() && (bgr.dims() != 2 || bgr.type() != CV_8UC3 || bgr.size() != frameSize))
    {
        MSG(cerr << "MFX: invalid frame passed to encoder: "
            << "dims/depth/cn=" << bgr.dims() << "/" << bgr.depth() << "/" << bgr.channels()
            << ", size=" << bgr.size() << endl);
        return false;

    }

    if (!bgr.empty())
    {
        workSurface = pool->getFreeSurface();
        if (!workSurface)
        {
            // not enough surfaces
            MSG(cerr << "MFX: Failed to get free surface" << endl);
            return false;
        }
        Mat src = bgr.getMat();
        hal::cvtBGRtoTwoPlaneYUV(src.data, src.step,
                                 workSurface->Data.Y, workSurface->Data.UV, workSurface->Data.Pitch,
                                 workSurface->Info.CropW, workSurface->Info.CropH,
                                 3, false, 1);
    }
    clock_t end1 = clock();
   
    clock_t start = clock();
    while (true)
    {
     
        outSurface = 0;
        DBG(cout << "Calling with surface: " << workSurface << endl);
        res = encoder->EncodeFrameAsync(NULL, workSurface, &bs->stream, &sync);
        if (res == MFX_ERR_NONE)
        {
            res = session->SyncOperation(sync, getWriterTimeoutMS()); // TODO: provide interface to modify timeout
            if (res == MFX_ERR_NONE)
            {
                // ready to write
                if (!bs->write())
                {
                    MSG(cerr << "MFX: Failed to write bitstream" << endl);
                    return false;
                }
                else
                {
                    DBG(cout << "Write bitstream" << endl);
                    /*RSI*/
                    clock_t end = clock();
                    frame_info[0] += (double(end - start) / CLOCKS_PER_SEC);
                    frame_info[2] += (double(end1 - start1) / CLOCKS_PER_SEC);
                    frame_info[1]++;
                    /*RSI*/
                    return true;
                }
            }
            else
            {
                MSG(cerr << "MFX: Sync error: " << res << endl);
                return false;
            }
        }
        else if (res == MFX_ERR_MORE_DATA)
        {
            DBG(cout << "ERR_MORE_DATA" << endl);
            return false;
        }
        else if (res == MFX_WRN_DEVICE_BUSY)
        {
            DBG(cout << "Waiting for device" << endl);
            sleep_ms(1000);
            continue;
        }
        else
        {
            MSG(cerr << "MFX: Bad status: " << res << endl);
            return false;
        }
      
    }
   
}

对于任何面临同样问题的人。 经过深入搜索,我发现intel还有一个使用硬件加速进行BGR->YUV转换的功能。 与上面的 cvtBGRtoTwoPlaneYUV() 函数相比,速度很快(大约快 4 倍)。 但是,对于我的用例来说,它仍然很慢。 我必须使用 Intel(R) UDH Graphics 620 获得 30FPS,显然目前唯一的解决方案是获得更好的 GPU。 用例示例: https ://github.com/sivabudh/intel-media-sdk-tutorials/tree/master/simple_6_encode_vmem_vpp_preproc

我刚刚添加了 OpenCV X86 库,并且我编写了自己的函数,该函数从 CV::MAT 而不是文件中读取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM