【问题标题】:Convert OpenGL output to H264 with x264使用 x264 将 OpenGL 输出转换为 H264
【发布时间】:2013-08-08 20:41:21
【问题描述】:

我想将 OpenGL 程序的输出转换为 h264 并流式传输输出。我在某处收集了大部分代码并得到了一个输出文件,但我不知道如何处理它,或者它是否有效。目前输出只是保存在 file.h264 中。

编辑:“全局”变量

    x264_param_t param;
    x264_t* encoder;
    x264_picture_t pic_in;
    x264_picture_t pic_out;

    x264_nal_t *headers;
    int i_nal;
    FILE* pFile;

我的初始化函数:

initX264() {
    pFile = fopen("file.h264", "wb");

    x264_param_t param;
    x264_param_default_preset(&param, "veryfast", "zerolatency");
    param.i_threads = 1;
    param.i_width = 1024;
    param.i_height = 768;
    param.i_fps_num = 30;
    param.i_fps_den = 1;

    param.i_keyint_max = 30;
    param.b_intra_refresh = 1;

    param.rc.i_rc_method = X264_RC_CRF;
    param.rc.f_rf_constant = 25;
    param.rc.f_rf_constant_max = 35;

    param.b_annexb = 0;
    param.b_repeat_headers = 0;

    param.i_log_level = X264_LOG_DEBUG;

    x264_param_apply_profile(&param, "baseline");

    encoder = x264_encoder_open(&param);
    x264_picture_alloc(&pic_in, X264_CSP_I420, 1024, 768);

    x264_encoder_parameters( encoder, &param );

    x264_encoder_headers( encoder, &headers, &i_nal );

    int size = headers[0].i_payload + headers[1].i_payload + headers[2].i_payload;
    fwrite( headers[0].p_payload, 1, size, pFile);
}

这进入渲染函数,每秒执行大约 30 次:

    GLubyte *data = new GLubyte[3 * 1024 * 768];
    GLubyte *PixelYUV = new GLubyte[3 * 1024 * 768];

    glReadPixels(0, 0, 1024, 768, GL_RGB, GL_UNSIGNED_BYTE, data);
    RGB2YUV(1024, 768, data, PixelYUV, PixelYUV + 1024 * 768, PixelYUV + 1024 * 768 + (1024 * 768) / 4, true);
    pic_in.img.plane[0] = PixelYUV;
    pic_in.img.plane[1] = PixelYUV + 1024 * 768;
    pic_in.img.plane[2] = PixelYUV + 1024 * 768 + (1024 * 768) / 4;

    x264_nal_t* nals;
    int i_nals;
    int frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);

    if( frame_size )
    {
        fwrite( (char*)nals[0].p_payload, frame_size, 1, pFile );

    }

我从http://svn.gnumonks.org/trunk/21c3-video/cutting_tagging/tools/mpeg4ip-1.2/server/util/rgb2yuv/rgb2yuv.c 获得了 GRB2YUV 功能

输出看起来像

x264 [debug]: frame=   0 QP=11.14 NAL=3 Slice:I Poc:0   I:3072 P:0    SKIP:0    size=21133 bytes
x264 [debug]: frame=   1 QP=20.08 NAL=2 Slice:P Poc:2   I:0    P:14   SKIP:3058 size=72 bytes
x264 [debug]: frame=   2 QP=18.66 NAL=2 Slice:P Poc:4   I:0    P:48   SKIP:3024 size=161 bytes
x264 [debug]: frame=   3 QP=18.23 NAL=2 Slice:P Poc:6   I:0    P:84   SKIP:2988 size=293 bytes

在 Linux 文件 file.h264 上返回数据。

【问题讨论】:

  • 它可以在 vlc 媒体播放器中播放吗?如果是这样,那么您就正确地对其进行了编码。如果不是,那么您的视频编码不正确。
  • no vlc 或 avplay 无法播放。
  • 你在哪里声明 pic_in?
  • 编辑:添加全局变量声明
  • x264 设置将根据您要写入的容器(或协议)而有所不同。流是发往 twitch.tv 等流媒体服务的吗?

标签: c++ c h.264 x264 libx264


【解决方案1】:
 X264 expects YUV420P data (I guess some others also, but that's the common one). You can use libswscale (from ffmpeg) to convert images to the right format. Initializing this is like this (i assume RGB data with 24bpp).

这很可能是您收不到任何可用视频的原因。你可以在这里找到更多关于做什么:How does one encode a series of images into H264 using the x264 C API?

缩放:

 sws_scale(convertCtx, &data, &srcstride, 0, h, pic_in.img.plane, pic_in.img.stride);
 //pic_in is your RGB data getting fed to scale. 

【讨论】:

  • 我想绕过使用 libffmpeg 来进行 YUV420P 转换。所以你觉得 RGB2YUV 功能坏了?
  • 没有损坏,但可能与您认为的不同。你是从哪个图书馆得到的?你确定它拿RGB去YUV420P吗?它可能正在做 YUV444 到 RGB888,这可能不起作用。
  • 我认为您必须对其进行扩展才能使其正常工作。似乎有一些关于在编码图像之前应该如何缩放图像的规范。使用我链接中的方式,我敢打赌它会起作用。
  • 那么如何将 RGB 数据提供给 sws_scale?
【解决方案2】:

您的文件格式不正确。什么都无法阅读。 A .264 使用在 IDR 帧前附加标头的附件 B。

更改这些参数,

param.b_annexb = 1;
param.b_repeat_headers = 1;

然后删除

x264_encoder_headers( encoder, &headers, &i_nal );
int size = headers[0].i_payload + headers[1].i_payload + headers[2].i_payload;
fwrite( headers[0].p_payload, 1, size, pFile);

最后,您应该能够获取您的输出并将其转换为 mp4。

ffmpeg -i file.264 -vcodec copy -an file.mp4

【讨论】:

  • 仅供参考。这适用于 .264 文件。如果要流式传输到 RTMP,则需要从 x264_encoder_headers() 创建一个序列头,然后切换回 b_annexb = 0;
  • 对于文件,这很好用。如何流式传输到 RTMP,我应该使用什么库(适用于 Linux 和 Windows)?
  • github.com/szatmary/RtmpBroadcaster。查看 rtmp.cpp、flvtag.cpp 和 encode.cpp。您在播放视频游戏吗?
  • 谢谢,我会看看。它不是电子游戏,只是一个使用 OpenGL 的模拟程序。
猜你喜欢
  • 2011-11-10
  • 1970-01-01
  • 2015-09-03
  • 2020-02-21
  • 1970-01-01
  • 2021-05-01
  • 2013-07-26
  • 1970-01-01
  • 2015-06-12
相关资源
最近更新 更多