我有一个程序,我有一个GLFW窗口,使用glReadPixels(0, 0,window_width, window_height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) Buffer);读取该窗口,然后使用Buffer通过ffmpeg对帧进行编码.它工作得很好,但分辨率有点低.

我试着改变比特率,但无济于事,所以我开始try 格式.通常我在我的编码器中使用AV_PIX_FMT_YUV420P作为我的格式,因为来自glfw窗口的数据是RGBA,但这种格式导致了上述低分辨率视频.结果视频比在GLFW窗口上看到的要像素化得多.

读取GLFW窗口的最佳像素格式是什么?有些格式笔直向上不工作,导致Specified pixel format yuyv422 is invalid or not supported错误.

这就是我的错误所在:

ret = avcodec_open2(c, codec, &opt);

当我使用YUV420以外的代码时,这行代码会导致我得到Specified pixel format yuyv422 is invalid or not supported错误.

我也有这个设置#define SCALE_FLAGS SWS_BICUBIC,我不确定它是做什么的,但也可能导致我的错误.(不太可能,因为这是在上面提到的行之后,但我可以将格式保留为YUV420并改为更改SWS_BICUBIC.)

我正在使用ubuntu、ffmpeg、glfw和grear(GLSL)来渲染帧中写入的纹理.我从ffmpegs muxing.c示例中得到了编码器.

编辑:使用AV_PIX_FMT_RGBA也会导致类似的错误.

编辑:以下是我将Buffer转换为ffmepg格式的示例代码:

#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P
...
void video_encoder::set_frame_yuv_from_rgb(AVFrame *frame, struct SwsContext *sws_context) {
    const int in_linesize[1] = { 4 * width };

    sws_context = sws_getContext(
            width, height, AV_PIX_FMT_RGBA,
            width, height, STREAM_PIX_FMT,
            SWS_BICUBIC, 0, 0, 0);

    sws_scale(sws_context, (const uint8_t * const *)&rgb_data, in_linesize, 0,
            height, frame->data, frame->linesize);
}

推荐答案

并不是每个编解码器都支持每种像素格式.有几种方法可以确定要使用哪种像素格式.

AVCodec有一个名为pix_fmts的字段

支持的像素格式的数组,如果未知,则数组以-1结尾

按照底部名为"参考..."的链接进行操作.以便更好地了解如何利用这一财产.

当谈到转换,找到最好的像素格式是强制性的,看看avcodec_find_best_pix_fmt_of_list

在给定的源像素格式下找到要转换为的最佳像素格式.

而伸缩是一个完全不同的故事(许多过滤选项),可以看到here.

但不知何故,我怀疑你的像素化输出仅仅是重新zoom (像素转换)的结果.有时postprocessing个人会有帮助.查看可用的后处理过滤器上的变量pp_help.


Hint

在使用ffmpeg API库编程之前,我建议将OpenGL渲染存储为高质量(无损编解码器)图像序列(例如,BMP、TGA、PNG以及可能是最简单的ppm,来自Netpbm包,当然还有SGI).然后try 使用工具ffmpeg进行实验,直到获得所需的结果.在此之后,将使用的选项实现到您的程序中.


一些有用的链接:
(如果您想了解AVCodecContext字段的含义)

C++相关问答推荐

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

Zig将std.os.argv转换为C类型argv

malloc实现:判断正确的分配对齐

为什么GCC在每次循环迭代时都会生成一个数组的mov&S使用[]访问数组?(-03,x86)

C由四个8位整数组成无符号32位整数

Rust FFI--如何用给出返回引用的迭代器包装C风格的迭代器?

fwrite无法写入满(非常大)缓冲区

为什么我可以在GCC的标签后声明变量,但不能声明Clang?

C将数组传递给函数以修改数组

-Wnonnull-Compare警告不是具有误导性吗?

递归打印二维数组(C编程)

链表删除 node 错误

Valgrind正在使用一个Fexecve电话报告不可能发生的事情

如何摆脱-WIMPLICIT-Function-声明

无算术运算符和循环的二进制乘法

Malloc和对齐

如何不断地用C读取文件?

GDB 跳过动态加载器代码

获取 struct 中匿名 struct 的大小

Clang 是否为内联汇编生成了错误的代码?