如何让 FFMPEG 从 OpenCV 获取帧并将它们流式传输到 HTTP 服务器

How to let FFMPEG fetch frames from OpenCV and stream them to HTTP server

有一台每秒拍摄 20 帧的相机。每帧是 4000x3000 像素。 这些帧被发送到其中包含 openCV 的软件。 OpenCV 将帧大小调整为 1920x1080,然后必须将它们发送到 FFMPEG 以使用 Nvidia Nvenc 编码为 H264 或 H265。 编码后的视频然后通过 HTTP 传输到最多 10 台设备。

基础设施非常好(10 GB 局域网),配备最先进的交换机、路由器等...

现在,从 Nvme SSD 编码图像时,我可以获得 90 FPS。这意味着达到了所需的编码速度。

问题是如何将图像从 OpenCV 获取到 FFMPEG? 流将在使用 MERN 堆栈制作的网络应用程序上观看(假设这是相关的)。

对于 cv::Mat 你有 cv::VideoWriter。如果你想使用 FFMpeg,假设 Mat 是连续的,可以强制执行:

if (! mat.isContinuous())
{ 
    mat = mat.clone();
}

你可以简单地将 mat.data 填入 sws_scale

sws_scale(videoSampler, mat.data, stride, 0, mat.rows, videoFrame->data, videoFrame->linesize);

或直接进入AVFrame

对于 cv::cuda::GpuMat,VideoWriter 实现不可用,但您可以使用 NVIDIA Video Codec SDK 并类似地将 cv::cuda::GpuMat::data 馈送到 NvEncoderCuda,只需确保您的 GpuMat 有 4 个通道( BGRA):

NV_ENC_BUFFER_FORMAT eFormat = NV_ENC_BUFFER_FORMAT_ABGR;
std::unique_ptr<NvEncoderCuda> pEnc(new NvEncoderCuda(cuContext, nWidth, nHeight, eFormat));

...
cv::cuda::cvtColor(srcIn, srcIn, cv::ColorConversionCodes::COLOR_BG2BGRA);
NvEncoderCuda::CopyToDeviceFrame(cuContext, srcIn.data, 0, (CUdeviceptr)encoderInputFrame->inputPtr,
            (int)encoderInputFrame->pitch,
            pEnc->GetEncodeWidth(),
            pEnc->GetEncodeHeight(),
            CU_MEMORYTYPE_HOST,
            encoderInputFrame->bufferFormat,
            encoderInputFrame->chromaOffsets,
            encoderInputFrame->numChromaPlanes);

Here是我将 GpuMat 与 NVIDIA Video Codec SDK 结合使用的完整示例