OpenCV 中的 VideoReader 已弃用。是否有来自 OpenCV 的任何更新或任何替代?

VideoReader in OpenCV is deprecated. Is there any update from OpenCV or any substitution?

我正在进行视频解码以抓取一些 post 视频处理的帧。我正在使用 opencv Cuda,所以我真的需要来自 opencv cuda 的视频 reader。然而,我意识到:

在 NVIDIA Video Codec SDK 8.2.15 中,它表示

Support for CUvideosource and the associated APIs including cuvidCreateVideoSource,cuvidCreateVideoSourceW, cuvidDestroyVideoSource, cuvidSetVideoSourceState, cuvidGetVideoSourceState, cuvidGetSourceVideoFormat, cuvidGetSourceAudioFormat will be removed from the decoder API in future SDK versions. Please note that the new decode sample applications in the SDK do not use these APIs, but use FFmpeg instead.

但是要在OpenCV Cuda中使用"createVideoReader",我们需要link "dynlink_nvcuvid.h"包含

tcuvidCreateVideoSource               *cuvidCreateVideoSource;
tcuvidCreateVideoSourceW              *cuvidCreateVideoSourceW;
tcuvidDestroyVideoSource              *cuvidDestroyVideoSource;
tcuvidSetVideoSourceState             *cuvidSetVideoSourceState;
tcuvidGetVideoSourceState             *cuvidGetVideoSourceState;
tcuvidGetSourceVideoFormat            *cuvidGetSourceVideoFormat;
tcuvidGetSourceAudioFormat            *cuvidGetSourceAudioFormat;

opencv 有视频解码的更新吗?我们如何在 OpenCV 中使用 FFmpeg 来替换 "dynlink_nvcuvid.h"?我正在尝试使用 NVIDIA 视频解码,但我一直坚持将视频帧转换为 GpuMat。

我正在使用 Ubuntu 18 库达 9.2 OpenCV 3.4.2

对于 Cuda 部分,我使用了以下代码进行解码:

FFmpegDemuxer demuxer(szInFilePath);
NvDecoder dec(cuContext, demuxer.GetWidth(), demuxer.GetHeight(), true, FFmpeg2NvCodecId(demuxer.GetVideoCodec()));
FramePresenterGL presenter(cuContext, demuxer.GetWidth(), demuxer.GetHeight());
uint8_t *dpFrame = 0;
int nPitch = 0;
int nVideoBytes = 0, nFrameReturned = 0, nFrame = 0;
uint8_t *pVideo = NULL;
uint8_t **ppFrame;
do {
    demuxer.Demux(&pVideo, &nVideoBytes);
    dec.Decode(pVideo, nVideoBytes, &ppFrame, &nFrameReturned);
    if (!nFrame && nFrameReturned)
        LOG(INFO) << dec.GetVideoInfo();

    for (int i = 0; i < nFrameReturned; i++) {
        presenter.GetDeviceFrameBuffer(&dpFrame, &nPitch);
        if (dec.GetBitDepth() == 8)
            Nv12ToBgra32((uint8_t *)ppFrame[i], dec.GetWidth(), (uint8_t *)dpFrame, nPitch, dec.GetWidth(), dec.GetHeight());
        else
            P016ToBgra32((uint8_t *)ppFrame[i], 2 * dec.GetWidth(), (uint8_t *)dpFrame, nPitch, dec.GetWidth(), dec.GetHeight());

        cv::Size sz(dec.GetWidth(),dec.GetHeight());
        cv::Mat mat1(sz,CV_8UC3, ppFrame);
        cv::imshow ("test", mat1);
        cv::waitKey(0);
    }
    nFrame += nFrameReturned;
} while (nVideoBytes);

有没有人有将 opencv cuda 与实际视频编解码器一起使用的经验 api?如何将视频帧放入 GpuMat?

更新:

我试过转换uint8_t但是图片显示错误,如下图:

我使用的代码已在上面更新。我应该更改什么才能正确显示图像?我试过 但是下面的代码的 downloadedLeft 是空的。

cv::Mat downloadedLeft;
cv::cuda::GpuMat gpuLeft;

cudaMalloc((void **)&ppFrame, gpuLeft.rows*gpuLeft.step);
cudaMemcpyAsync(ppFrame, gpuLeft.ptr<uint8_t>(), gpuLeft.rows*gpuLeft.step, cudaMemcpyDeviceToDevice);

gpuLeft.download(downloadedLeft);
cv::imshow ("test", downloadedLeft);
cv::waitKey(1);

我找到了一种无需任何第 3 方即可读取图像的简单 C 方法。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int read_image(FILE *rfile, void *buf, int width, int height, int stride, int elem_size)
{
    char *byte_ptr = buf;
    int i;
    int ret = 1;

    if (width <= 0 || height <= 0 || elem_size <= 0)
    {
        goto fail_or_end;
    }

    for (i = 0; i < height; ++i)
    {
        if (fread(byte_ptr, elem_size, width, rfile) != (size_t)width)
        {
            goto fail_or_end;
        }

        byte_ptr += stride;
    }

    ret = 0;

fail_or_end:
    return ret;
}

感谢 netflix vmaf 开源 (file_io.c)。谢谢Netflix。 看完图像后,我设法继续用 cuda 处理它。