我有以下管道:
现在,问题在于在阶段4和5之间同步数据.以下是我尝试过的同步解决方案.
glFlush - 并不真正起作用,因为它不能保证所有命令执行的完整性.
glFinish - 这个有效.但不推荐使用它,因为它最终确定了提交给驱动程序的所有命令.
ARB_sync 这里有人说它不推荐使用,因为它会严重影响性能.
glMemoryBarrier这个很有意思.但它根本行不通.
以下是代码示例:
glMemoryBarrier(GL_ALL_BARRIER_BITS);
Run Code Online (Sandbox Code Playgroud)
并尝试过:
glTextureBarrierNV()
Run Code Online (Sandbox Code Playgroud)
代码执行如下:
//rendered into the fbo...
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindImageTexture(imageUnit1, fboTex, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA8);
glBindImageTexture(imageUnit2, imageTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8));
glDispatchCompute(16, 16, 1);
glFinish(); // <-- must sync here,otherwise cuda buffer doesn't receive all the data
//cuda maps the image to CUDA buffer here..
Run Code Online (Sandbox Code Playgroud)
此外,我尝试在启动计算之前从上下文中取消绑定FBO和取消绑定纹理,我甚至尝试使用glMemoryBarrier
它们之间的集合启动一个计算,然后从第一次计算启动到CUDA获取目标图像.仍然没有同步.(嗯,这是有道理的,因为两个计算也彼此不同步)
在计算着色器阶段之后.它没有同步!只有当我更换glFinish
或完全停止管道的任何其他操作时.比如glMapBuffer()
,例如.
那么我应该使用glFinish(),还是我在这里遗漏了什么?为什么glMemoryBarrier()在CUDA接管控制之前不同步计算着色器工作?
UPDATE
我想稍微重构一下这个问题,因为原来的问题已经很久了.尽管如此,即使使用最新的CUDA和视频编解码器SDK(NVENC),问题仍然存在.所以,我不关心为什么glMemoryBarrier …
在尝试这样的简单编码时,我收到错误"找不到NVENC功能的设备",甚至跳过音频以确保它不是音频问题:
ffmpeg.exe -i input.mp4 -c:v hevc_nvenc -an out.mp4
Run Code Online (Sandbox Code Playgroud)
我还尝试了更多细节,比如设置像素格式,预设,速率控制和格式.
在文档页面上:https: //trac.ffmpeg.org/wiki/HWAccelIntro 它说如果我们得到这个错误,我们应该检查像素格式.视频在这里有yuv420p,甚至指定格式会导致相同的错误.
我还检查了NVidia支持的卡,它说的是GeForce,但没有关于这些型号的详细信息:https: //developer.nvidia.com/video-encode-decode-gpu-support-matrix#Encoder
我尝试了h264_nvenc并且它工作正常,但问题是只有hevc_nvenc有没有人遇到过这个问题?
完整控制台输出:
[h264 @ 0000000002534560] Reinit context to 1280x544, pix_fmt: yuv420p
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : isom
minor_version : 1
compatible_brands: isom
creation_time : 2014-05-23T13:04:15.000000Z
Duration: 01:54:03.95, start: 0.000000, bitrate: 3193 kb/s
Stream #0:0(und): Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(left), 1280x544 [SAR 1:1 DAR 40:17], 2750 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc …
Run Code Online (Sandbox Code Playgroud) 这将是一个自我回答的问题,因为它在整整一个星期的过程中让我疯狂,我希望让我的程序员免受我经历的挫折.
情况如下:您希望使用NVidia的NVEnc硬件编码器(分别在Kepler和Maxwell卡上提供,分别为GT(x)7xx和GT(x)9xx)来通过UDP流式传输图形应用程序的输出.这不是一条琐碎的道路,但它可以非常高效,因为它可以避免在编码阶段之前将帧从视频内存"下载"到系统内存,因为NVEnc能够直接访问视频内存.
我已经成功地完成了这项工作,只需要一帧又一帧地编写NVEnc的输出缓冲区来生成.h264 文件.VLC播放这样的文件没有问题,除了时间关闭(我没有尝试解决这个问题,因为我只需要该文件用于调试目的).
当我尝试通过UDP流式传输编码帧时出现问题:VLC和MPlayer都无法呈现视频.原来有两个原因,我将在答案中解释.
我正在尝试使用nvidia库在Windows中编译ffmpeg,以便使用MinGW/msys进行硬件加速.试图按照nvidias网站上的说明进行操作(部分:使用NVIDIA GPU开始使用FFmpeg/libav).配置为--enable-nonfree --disable-shared --enable-nvenc --enable-cuda --enable-cuvid --enable-libnpp --extra-cflags = -Ilocal/include --extra-cflags = -I ../common/inc --extra-ldflags = -L ../ common/lib/x64 --prefix = ffmpeg但停在"ERROR:找不到libnpp".从NVIDIA Video Codec SDK下载常用文件夹但没有npp libs或头文件.那有什么解决方案吗?感谢edvice.
如果 p 帧不改变当前解码视频中的任何像素(即没有运动向量,什么都没有),我们就将其称为空帧。
我需要的是能够根据请求手动将空 p 帧插入到视频流中(需要以恒定的帧速率将帧发送到流客户端,但是流服务器上的帧源可以提供具有不同/较低帧速率的帧一)。
因此,我需要能够正确形成代表当前分辨率的空 p 帧的字节序列(我想知道还需要哪些其他参数?)
理想情况下,我更喜欢独立于编码器的解决方案,因为我使用两种不同的解决方案:通过 Nvidia Video SDK 的 nvenc 和通过 FFmpeg 的 x264。
我应该去哪里寻找?
我使用 nvidia-docker 在 docker 容器内安装了Nvidia Video Codec SDK 8.2 + ffmpeg但当我运行此命令时
ffmpeg -f rawvideo -s:v 1920x1080 -r 30 -pix_fmt yuv420p -i HeavyHand_1080p.yuv -c:v h264_nvenc -preset slow -cq 10 -bf 2 -g 150 output.mp4
Run Code Online (Sandbox Code Playgroud)
我收到这个错误
无法加载 libnvidia-encode.so.1
nvenc 所需的最低 Nvidia 驱动程序为 390.25 或更高版本初始化输出流 0:0 时出错 - 打开输出流 #0:0 的编码器时出错 - 可能参数不正确,例如比特率、速率、宽度或高度
否则nvidia-smi显示此信息
使用的GPU是GeForce 1050 Ti,cuda版本是9.0
在尝试使用NVEnc将OpenGL帧作为H264进行流式传输时,我碰到了一堵完整的砖墙.我已经在这个特殊问题上待了将近8个小时而没有任何进展.
问题是调用nvEncRegisterResource()
,代码-23总是失败(枚举值NV_ENC_ERR_RESOURCE_REGISTER_FAILED,记录为"未能注册资源" - 感谢NVidia).
我正在尝试遵循奥斯陆大学本文档中概述的程序(第54页,"OpenGL互操作"),因此我知道这应该有用,但遗憾的是,该文档并未提供代码本身.
这个想法相当简单:
正如我所说,问题是第(3)步.以下是相关的代码片段(为简洁起见,我省略了错误处理.)
// Round up width and height
priv->encWidth = (_resolution.w + 31) & ~31, priv->encHeight = (_resolution.h + 31) & ~31;
// Allocate CUDA "pitched" memory to match the input texture (YUV, one byte per component)
cuErr = cudaMallocPitch(&priv->cudaMemPtr, &priv->cudaMemPitch, 3 * priv->encWidth, priv->encHeight);
Run Code Online (Sandbox Code Playgroud)
这应该分配设备上的CUDA内存("倾斜"类型,尽管我也尝试过非音调,但结果没有任何改变.)
// Register the CUDA buffer as an input resource
NV_ENC_REGISTER_RESOURCE regResParams = { 0 };
regResParams.version = NV_ENC_REGISTER_RESOURCE_VER;
regResParams.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; …
Run Code Online (Sandbox Code Playgroud) 我目前使用两个 nvidia p4 显卡。
在以前版本的 ffmpeg(3.2.0 之前)中,我可以使用选项“-gpu 0 或 1 等”来选择特定的 GPU 卡。
然而,在当前版本中,没有选择 GPU 卡的选项。
实际上,nvenc_h264.c 或 nvenc_hevc.c 中指定了“gpu”选项。
但在 nvenc.c 文件中,没有使用“gpu”选项的代码。
有什么办法可以选择特定的卡吗?
两张卡之间的负载均衡是如何实现的?
是在驱动级别完成的吗?
谢谢。
我正在尝试使用 ffmpeg 对 UHD HDR 视频流进行色调映射(和调整大小)。以下命令:
ffmpeg -vsync 0 -hwaccel cuda -init_hw_device opencl=ocl -filter_hw_device ocl
-threads 1 -extra_hw_frames 3 -c:v hevc_cuvid -resize 1920x1080 -i "INPUT.hevc"
-vf "hwupload,
tonemap_opencl=tonemap=mobius:param=0.01:desat=0:r=tv:p=bt709:t=bt709:m=bt709:format=nv12,
hwdownload,format=nv12,hwupload_cuda"
-c:v hevc_nvenc -b:v 8M "OUTPUT.hevc"
Run Code Online (Sandbox Code Playgroud)
似乎有效(RTX 3080 上大约 200 FPS)。然而,我注意到它仍然使用一个 CPU 核心,并且 GPU 使用率据报告仅为 60-70%。当我只在没有任何滤镜的情况下调整大小时,我会在 100% GPU 使用率下获得大约 400FPS 的速度。
我怀疑最后的hwdownload,format=nv12,hwupload_cuda
语句有问题,因为这增加了通过主内存的绕道。我尝试只使用hwupload_cuda
而不使用hwdownload
(就像这里建议的那样: https: //stackoverflow.com/a/55747785/929037在本答案末尾附近的过滤器示例中),但后来出现以下错误:
Impossible to convert between the formats supported by the filter 'Parsed_tonemap_opencl_1' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject …
Run Code Online (Sandbox Code Playgroud) 我使用的ffmpeg的可执行代码转换MPEGTS从h264码流与H265 nvenc和我有两个NVIDIA我的主板上安装图形卡:的GeForce GTX 690和Tesla K-10。ffmpeg中的nvenc是否有任何编解码器特定的参数,可以选择使用我想要的任何这些GPU进行编码?