gpt4 book ai didi

c++ - 如何将像素格式 AV_PIX_FMT_CUDA 的 FFmpeg AVFrame 转换为像素格式 AV_PIX_FMT_RGB 的新 AVFrame

转载 作者:行者123 更新时间:2023-12-01 16:12:27 52 4
gpt4 key购买 nike

我有一个简单的 C++ 应用程序,它使用 FFmpeg 3.2 接收 H264 RTP 流。为了节省CPU,我使用编解码器h264_cuvid进行解码部分。我的 FFmpeg 3.2 是在启用硬件加速的情况下编译的。事实上,如果我执行命令:

ffmpeg -hwaccels

我明白了

cuvid

这意味着我的 FFmpeg 设置可以与我的 NVIDIA 卡“对话”。函数 avcodec_decode_video2 为我提供的帧具有像素格式 AV_PIX_FMT_CUDA。我需要使用 AV_PIX_FMT_RGB 将这些帧转换为新帧。不幸的是,我无法使用众所周知的函数 sws_getContextsws_scale 进行转换,因为不支持像素格式 AV_PIX_FMT_CUDA。如果我尝试使用 swscale 我会收到错误:

“不支持 cuda 作为输入像素格式”

您知道如何将 FFmpeg AVFrameAV_PIX_FMT_CUDA 转换为 AV_PIX_FMT_RGB 吗?(非常感谢代码片段)

最佳答案

这是我对最新 FFMPeg 4.1 版本硬件解码的理解。以下是我研究源码后的结论。

首先,我建议您从 hw_decode 示例中获得启发:

https://github.com/FFmpeg/FFmpeg/blob/release/4.1/doc/examples/hw_decode.c

使用新 API,当您使用 avcodec_send_packet() 将数据包发送到编码器时,然后使用 avcodec_receive_frame()检索解码的帧。

有两种不同类型的AVFrame:软件,一种存储在“CPU”内存(也称为 RAM)中,硬件> 1,存储在显卡内存中。

从硬件获取AVFrame

检索硬件帧并将其转换为可读、可转换(使用 swscaler)AVFrameav_hwframe_transfer_data()需要用于从图形卡检索数据。然后看检索到的帧的像素格式,使用nVidia解码时通常是NV12格式。

// According to the API, if the format of the AVFrame is set before calling 
// av_hwframe_transfer_data(), the graphic card will try to automatically convert
// to the desired format. (with some limitation, see below)
m_swFrame->format = AV_PIX_FMT_NV12;

// retrieve data from GPU to CPU
err = av_hwframe_transfer_data(
m_swFrame, // The frame that will contain the usable data.
m_decodedFrame, // Frame returned by avcodec_receive_frame()
0);

const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)m_decodedFrame->format);
const char* cpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)m_swFrame->format);

列出支持的“软件”像素格式

这里请注意,如果您想选择像素格式,并非所有 AVPixelFormat 都受支持。 AVHWFramesConstraints这里是你的 friend 吗:

AVHWDeviceType type = AV_HWDEVICE_TYPE_CUDA;
int err = av_hwdevice_ctx_create(&hwDeviceCtx, type, nullptr, nullptr, 0);
if (err < 0) {
// Err
}

AVHWFramesConstraints* hw_frames_const = av_hwdevice_get_hwframe_constraints(hwDeviceCtx, nullptr);
if (hw_frames_const == nullptr) {
// Err
}

// Check if we can convert the pixel format to a readable format.
AVPixelFormat found = AV_PIX_FMT_NONE;
for (AVPixelFormat* p = hw_frames_const->valid_sw_formats;
*p != AV_PIX_FMT_NONE; p++)
{
// Check if we can convert to the desired format.
if (sws_isSupportedInput(*p))
{
// Ok! This format can be used with swscale!
found = *p;
break;
}
}

// Don't forget to free the constraint object.
av_hwframe_constraints_free(&hw_frames_const);

// Attach your hw device to your codec context if you want to use hw decoding.
// Check AVCodecContext.hw_device_ctx!

最后,更快的方法可能是 av_hwframe_transfer_get_formats()功能,但至少需要解码一帧。

希望这会有所帮助!

关于c++ - 如何将像素格式 AV_PIX_FMT_CUDA 的 FFmpeg AVFrame 转换为像素格式 AV_PIX_FMT_RGB 的新 AVFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47049312/

52 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com