草庐IT

c++ - 将 openGL 上下文保存为视频输出

coder 2023-11-13 原文

我目前正在尝试将 openGL 中制作的动画保存到视频文件中。我曾尝试使用 openCVvideowriter 但没有任何优势。我已经成功地能够使用 SDL 库生成快照并将其保存为 bmp。如果我保存所有快照,然后使用 ffmpeg 生成视频,这就像收集 4 GB 的图像。不实用。 如何在渲染过程中直接写入视频帧? 这是我在需要时用来拍摄快照的代码:

void snapshot(){
SDL_Surface* snap = SDL_CreateRGBSurface(SDL_SWSURFACE,WIDTH,HEIGHT,24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
char * pixels = new char [3 *WIDTH * HEIGHT];
glReadPixels(0, 0,WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels);

for (int i = 0 ; i <HEIGHT ; i++)
    std::memcpy( ((char *) snap->pixels) + snap->pitch * i, pixels + 3 * WIDTH * (HEIGHT-i - 1), WIDTH*3 );

delete [] pixels;
SDL_SaveBMP(snap, "snapshot.bmp");
SDL_FreeSurface(snap);
}

我需要视频输出。我发现 ffmpeg 可用于从 C++ 代码创建视频,但一直无法弄清楚该过程。请帮忙!

编辑:我尝试使用 openCV CvVideoWriter 类,但程序崩溃(“段错误”)它被声明的那一刻。编译显示当然没有错误。有什么建议吗?

Python 用户解决方案(需要 Python2.7python-imagingpython-openglpython-opencv,你要写入的格式的编解码器,我在Ubuntu 14.04 64-bit):

def snap():
    pixels=[]
    screenshot = glReadPixels(0,0,W,H,GL_RGBA,GL_UNSIGNED_BYTE)
    snapshot = Image.frombuffer("RGBA",W,H),screenshot,"raw","RGBA",0,0)
    snapshot.save(os.path.dirname(videoPath) + "/temp.jpg")
    load = cv2.cv.LoadImage(os.path.dirname(videoPath) + "/temp.jpg")
    cv2.cv.WriteFrame(videoWriter,load)

这里的 WH 是窗口尺寸(宽度,高度)。我正在使用 PIL 将从 glReadPixels 命令读取的原始像素转换为 JPEG 图像。我正在将该 JPEG 加载到 openCV 图像中并写入视频编写器。我在将 PIL 图像直接用于视频编写器时遇到了某些问题(这将节省数百万个 I/O 时钟周期),但现在我没有在处理这个问题。 Image 是一个 PIL 模块 cv2 是一个 python-opencv 模块。

最佳答案

听起来好像您正在使用命令行实用程序:ffmpeg。与其使用命令行从一组静止图像中编码视频,不如使用 libavcodeclibavformat。这些是实际构建 ffmpeg 的库,将允许您编码视频并将其存储为标准流/交换格式(例如 RIFF/AVI),而无需使用单独的程序。

您可能不会找到很多关于实现它的教程,因为传统上人们希望使用 ffmpeg 走另一条路;也就是说,解码各种视频格式以在 OpenGL 中显示。我认为随着将游戏视频编码引入 PS4 和 Xbox One 游戏机,这种情况很快就会改变,对这一功能的需求会突然飙升。

但是,一般过程是这样的:

  1. 选择容器格式和编解码器
    • 通常一个决定另一个,(例如 MPEG-2 + MPEG 节目流)
  2. 开始用您的静止帧填充缓冲区
  3. 定期对您的静止帧缓冲区进行编码并写入您的输出(以 MPEG 术语写入数据包)
    • 您将在缓冲区变满时或每隔 n-many 毫秒执行此操作;根据您是否要直播视频,您可能更喜欢其中之一。
  4. 当您的程序终止时刷新缓冲区并关闭您的流

这样做的一个好处是您实际上不需要写入文件。由于您定期对静止帧缓冲区中的数据包进行编码,因此如果需要,您可以通过网络流式传输编码视频 - 这就是为什么编解码器和容器(交换)格式是分开的。

另一个好处是您不必同步 CPU 和 GPU,您可以设置一个像素缓冲区对象并让 OpenGL 将数据复制到 CPU 内存中,比 GPU 晚几帧。这使得视频的实时编码要求低得多,如果视频延迟要求并非不合理,您只需定期将视频编码并刷新到磁盘或通过网络刷新。这在实时渲染中非常有效,因为您有足够大的数据池来保持 CPU 线程始终忙于编码。

编码帧甚至可以在 GPU 上实时完成,为大量帧缓冲区提供足够的存储空间(因为最终编码数据必须从 GPU 复制到 CPU,并且您希望尽可能少地执行此操作) .显然这不是使用 ffmpeg 完成的,有专门的库使用 CUDA/OpenCL/计算着色器来达到这个目的。我从未使用过它们,但它们确实存在。

为了可移植性,您应该坚持使用 libavcodec 和像素缓冲区对象进行异步 GPU->CPU 复制。现在的 CPU 有足够的核心,如果你缓冲足够的帧并在多个同步线程中编码(这会增加同步开销并增加输出编码视频时的延迟)或者简单地丢帧/降低分辨率(穷人的解决方案)。

此处涵盖的许多概念远远超出了 SDL 的范围,但您确实询问了如何以比当前解决方案更好的性能来做到这一点。简而言之,使用 OpenGL Pixel Buffer Objects 传输数据,使用 libavcodec 进行编码。一个example application可以在 ffmpeg libavcodec examples 上找到对视频进行编码的页面。

关于c++ - 将 openGL 上下文保存为视频输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19070333/

有关c++ - 将 openGL 上下文保存为视频输出的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  5. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  6. ruby - 将 spawn() 的标准输出/标准错误重定向到 Ruby 中的字符串 - 2

    我想使用spawn(针对多个并发子进程)在Ruby中执行一个外部进程,并将标准输出或标准错误收集到一个字符串中,其方式类似于使用Python的子进程Popen.communicate()可以完成的操作。我尝试将:out/:err重定向到一个新的StringIO对象,但这会生成一个ArgumentError,并且临时重新定义$stdxxx会混淆子进程的输出。 最佳答案 如果你不喜欢popen,这是我的方法:r,w=IO.pipepid=Process.spawn(command,:out=>w,:err=>[:child,:out])

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  9. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  10. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

随机推荐