编码OpenGL在C中捕获的缓冲区

应颖

我试图使用OpenGL捕获计算机屏幕的后缓冲区,然后使用FFMPEG的libavcodec对缓冲区进行H.264编码我遇到的问题是我想对视频进行编码AV_PIX_FMT_420P,但是OpenGL提供的后缓冲区捕获功能glReadPixels()仅支持格式GL_RGB如下所示,我尝试使用FFMPEG的swscale()功能将RGB转换为YUV,但是以下代码在此swscale()崩溃关于如何编码OpenGL Backbuffer的任何想法?

// CAPTURE BACK BUFFER USING OPENGL
    int width = 1280, height = 720;
    BYTE* pixels = (BYTE *) malloc(sizeof(BYTE));
    glReadPixels(0, 720, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);

//CREATE FFMPEG VARIABLES
    avcodec_register_all();

    AVCodec *codec;
    AVCodecContext *context;
    struct SwsContext *sws;
    AVPacket packet;
    AVFrame *frame;

    codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    context = avcodec_alloc_context3(encoder->codec);
    context->dct_algo = FF_DCT_FASTINT;
    context->bit_rate = 400000;
    context->width = width;
    context->height = height;
    context->time_base.num = 1;
    context->time_base.den = 30;
    context->gop_size = 1;
    context->max_b_frames = 1;
    context->pix_fmt = AV_PIX_FMT_YUV420P;

    avcodec_open2(context, codec, NULL);

// CONVERT TO YUV AND ENCODE
    int frame_size = avpicture_get_size(AV_PIX_FMT_YUV420P, out_width, out_height);
    encoder->frame_buffer = malloc(frame_size);
    avpicture_fill((AVPicture *) encoder->frame, (uint8_t *) encoder->frame_buffer, AV_PIX_FMT_YUV420P, out_width, out_height);
    sws = sws_getContext(in_width, in_height, AV_PIX_FMT_RGB32, out_width, out_height, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, 0, 0, 0);

    uint8_t *in_data[1] = {(uint8_t *) pixels};
    int in_linesize[1] = {width * 4};


// PROGRAM CRASHES HERE


    sws_scale(encoder->sws, in_data, in_linesize, 0, encoder->in_height, encoder->frame->data, encoder->frame->linesize);

    av_free_packet(&packet);
    av_init_packet(&packet);
    int success;

    avcodec_encode_video2(context, &packet, frame, &success);
雅科夫·加尔卡(Yakov Galka)

您的pixels缓冲区太小;malloc只有一个 BYTE而不是width*height*4字节:

BYTE* pixels = (BYTE *) malloc(width*height*4);

您的glReadPixels电话也不正确:

  • 通过y=720会使它在窗口之外读取。请记住,OpenGL坐标系的y轴指向上方。
  • AV_PIX_FMT_RGB32期望每个像素四个字节,而每个像素GL_RGB写入三个字节,因此需要GL_RGBAor GL_BGRA
  • 我非常确定这两个应该是GL_BGRAAV_PIX_FMT_RGB32将像素视为32位整数,因此在小端蓝色上是第一位。OpenGL将每个通道视为一个字节,因此应该GL_BGRA匹配。

总结一下尝试:

glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);

此外,由于OpenGL y轴指向上方,而ffmpeg y轴指向下方,则可能需要翻转图像。可以使用以下技巧来完成:

uint8_t *in_data[1] = {(uint8_t *) pixels + (height-1)*width*4}; // address of the last line
int in_linesize[1] = {- width * 4}; // negative stride

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

android 4.1(API 16)中捕获的缓冲区到缓冲区的编码/解码

来自分类Dev

OpenGL中的缓冲区绘图

来自分类Dev

在openGL中多次绑定缓冲区

来自分类Dev

在OpenGL中查看深度缓冲区

来自分类Dev

OpenGL缓冲区问题

来自分类Dev

C ++中的缓冲区大小

来自分类Dev

C ++中的位缓冲区

来自分类Dev

在C ++中解析协议缓冲区

来自分类Dev

C中的缓冲区溢出与获取

来自分类Dev

在C#中同步缓冲区

来自分类Dev

C中自发的缓冲区溢出

来自分类Dev

捕获c ++ system()命令的缓冲区输出

来自分类Dev

在一个函数(OpenGL和C ++)中多次交换缓冲区

来自分类Dev

在OpenGL中创建不可变缓冲区

来自分类Dev

在OpenGL中更新模具缓冲区时的问题

来自分类Dev

GLSL:结构数组与OpenGL缓冲区中数组的结构

来自分类Dev

避免OpenGL缓冲区中的重复数据

来自分类Dev

在OpenGL中清除双精度缓冲区

来自分类Dev

c + +和DX11中的动态常量缓冲区或动态顶点缓冲区

来自分类Dev

您将如何限制缓冲区大小并返回c ++中的缓冲区限制?

来自分类Dev

捕获麦克风的缓冲区

来自分类Dev

捕获到缓冲区 QT

来自分类Dev

C ++中的Tensorflow:成功读取LSTM编码器解码器模型的协议缓冲区

来自分类Dev

OpenGL复制顶点缓冲区对象

来自分类Dev

如何增加OpenGL缓冲区?

来自分类Dev

使用OpenCL获取OpenGL缓冲区

来自分类Dev

OpenGL glMultiDrawElementsIndirect与交错缓冲区

来自分类Dev

OpenGL:glLoadMatrix和深度缓冲区

来自分类Dev

OpenGL帧缓冲区+ LibGDX