简体   繁体   English

使用x264将OpenGL输出转换为H264

[英]Convert OpenGL output to H264 with x264

I want to convert the output of an OpenGL Program to h264 and stream the output. 我想将OpenGL程序的输出转换为h264并输出输出。 I got collected most of the code somewhere and I get an output file but I have no Idea what to do with it, or if it is valid. 我收集了大部分代码并得到了一个输出文件,但我不知道如何处理它,或者它是否有效。 Currently the output is just saved in file.h264. 目前输出只保存在file.h264中。

Edit: "Global" Variables 编辑:“全局”变量

    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;

My init function: 我的init函数:

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);
}

This goes in the Render function and is executed about 30 times per second: 这在Render函数中进行,每秒执行约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 );

    }

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

The output looks like 输出看起来像

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

On Linux file file.h264 returns data. 在Linux文件中,file.h264返回数据。

Your file format is bad. 你的文件格式不好。 Nothing will be able to read that. 没有什么能够读到这一点。 A .264 uses annexB with headers prepended to IDR frames. .264使用附件B,头部前面加上IDR帧。

change these parameters, 改变这些参数,

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

And delete 并删除

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);

Finally you should be able to take your output and convert it to an mp4. 最后,您应该能够获取输出并将其转换为mp4。

ffmpeg -i file.264 -vcodec copy -an file.mp4
 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).

That's most likely why you're not getting any usable video. 这很可能是因为你没有获得任何可用的视频。 You can find more about what to do here: How does one encode a series of images into H264 using the x264 C API? 您可以在此处找到有关如何操作的更多信息: 如何使用x264 C API将一系列图像编码为H264?

To scale: 缩放:

 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. 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM