Newest 'libx264' Questions - Stack Overflow

http://stackoverflow.com/questions/tagged/libx264

Les articles publiés sur le site

  • Does libx264 encoder support 12 bit pixel format such as yuv444p12le ?

    4 août 2020, par bazz01

    Libx264 show support for following input pixel formats:

    yuv420p yuvj420p yuv422p yuvj422p yuv444p yuvj444p nv12 nv16 nv21 yuv420p10le yuv422p10le yuv444p10le nv20le gray gray10le
    
    • For libx264 can support be added for 12 bit format like yuv444p12le?

    • Any other open source encoder which supports 12 bit format?

  • muxing streamable segmented mp4 with libav

    24 juillet 2020, par Elias Wagnerberger

    currently i have an application that is supposed to send fragmented mp4 data over a websocket to a client for it to be played there.

    i have a working implementation that pipes the raw frames to a spawned ffmpeg process and then reads fragmented mp4 segments from the output pipe before it sends those on to the client where the client then displays the video correctly.

    my problem is that when i try to make an implementation using libav it doesnt seem to work. my libav config uses libx264 to encode the frames before muxing them to a mp4, but when i try to play the provided segments in a browser using MSE it spits out an error. after having checked chrome://media-internals i have figured out that chrome complains when i provide the moov box that is one of the two initialization boxes of a fmp4 stream.

    chrome apparently has a problem with parsing that box when its sent from libav, but not when its sent from ffmpeg.

    my question is: What is the correct muxer configuration of libav so that it creates a fragmented mp4 stream where the client can recieve media boxes from the middle, after having been provided the init boxes?

  • Problems with muxing fmp4 stream with libav

    20 juillet 2020, par Elias Wagnerberger

    currently i have an application that is supposed to send fragmented mp4 data over a websocket to a client for it to be played there.

    i have a working implementation that pipes the raw frames to a spawned ffmpeg process and then reads fragmented mp4 segments from the output pipe before it sends those on to the client where the client then displays the video correctly.

    my problem is that when i try to make an implementation using libav it doesnt seem to work. my libav config uses libx264rgb to encode the frames before muxing them to a mp4, but when i try to play the provided segments in a browser using MSE it spits out an error. after having checked chrome://media-internals i have figured out that the problem lies in the moov box that is one of the two initialization boxes of a fmp4 stream.

    chrome apparently has a problem with parsing that box when its sent from libav, but not when its sent from ffmpeg.

    my question is: What is the correct muxer configuration of libav so that it creates a fragmented mp4 stream where the client can recieve media boxes from the middle, after having been provided the init boxes?

  • x264 output video is blank when threading is enabled

    15 juillet 2020, par NewbieCoder

    I am using libx264 compiled from source. It was configured to get both .dll and .lib by this command

    ./configure --disable-cli --enable-shared --extra-ldflags=-Wl,--output-def=libx264.def`

    I am using the libx264 API in my screen-sharing program with the preset - "veryfast", tune - "zerolatency", profile - "high" and also the following settings.

            param.i_csp = X264_CSP_BGRA;
            param.i_threads = 1;
            param.i_width = width;
            param.i_height = height;
            param.i_fps_num = fps;
            param.i_fps_den = 1;
            param.rc.i_bitrate = bitrate;
            param.rc.i_rc_method = X264_RC_ABR;
            param.rc.b_filler = true;
            param.rc.f_rf_constant = (float)0;
            param.rc.i_vbv_max_bitrate = param.rc.i_bitrate;
            param.rc.i_vbv_buffer_size = param.rc.i_bitrate;
            param.b_repeat_headers = 0;
            param.b_annexb = 1;
    

    For these settings the program works fine. I specified it as single threaded by setting param.i_threads = 1. If this is removed, x264 defaults to using multiple threads and sets param.i_threads as 1.5x of number of cores in the CPU automatically. This will give faster performance than running in single thread.

    But when I remove the param.i_threads = 1 to make it multi-threaded, the generated output is fully grey. I cannot see any output when I view the live stream with VLC or some times I can view a weird output.

    I am using this bitmap image as an example (https://imgur.com/a/l8LCd1l). Only this same image is being encoded multiple times. When it is saved into .h264 video, it is viewable clearly. But when the encoded payload is sent through rtmp, the live stream produces very bad and weird output (or sometimes no output). This is the weird output which im seeing most of the time for this image: https://imgur.com/a/VdyX1Zm

    This is the full example code in which I am both streaming and writing video file of the same picture. This is using the srs librtmp library. There is no error but the stream has weird output.

    In this code if you set add param.i_threads = 1; then only the output stream will be viewable. The problem is that it should be viewable in both single-threaded and multi-threaded encoding.

    #include 
    #include 
    #include 
    #include 
    #include "srs_librtmp.h"
    
    #pragma comment(lib, "C:/Softwares/x264/libx264.lib")
    
    using namespace std;
    
    int check_ret(int ret);
    
    int main()
    {
        int dts = 0;
    
        x264_param_t param;
        x264_t* h;
        x264_nal_t* nals;
        int i_nal;
        int pts = 0;
        int i_frame_size;
        x264_picture_t picIn;
        x264_picture_t picOut;
    
        x264_param_default_preset(&param, "veryfast", "zerolatency");
    
        //x264 settings
        param.i_csp = X264_CSP_BGRA;
        param.i_width = 1920;
        param.i_height = 1080;
        param.i_fps_num = 30;
        param.i_fps_den = 1;
        param.rc.i_bitrate = 2500;
        param.rc.i_rc_method = X264_RC_ABR;
        param.rc.b_filler = true;
        param.rc.f_rf_constant = (float)0;
        param.rc.i_vbv_max_bitrate = param.rc.i_bitrate;
        param.rc.i_vbv_buffer_size = param.rc.i_bitrate;
        param.b_repeat_headers = 0;
        param.b_annexb = 1;
    
        x264_param_apply_profile(&param, "high");
        h = x264_encoder_open(&param);
    
        //allocate picture
        x264_picture_alloc(&picIn, param.i_csp, param.i_width, param.i_height);
    
        //picture settings
        picIn.img.i_plane = 1;
        picIn.img.i_stride[0] = 4 * param.i_width;
        picIn.i_type = X264_TYPE_AUTO;
    
        int header_size = x264_encoder_headers(h, &nals, &i_nal);
        FILE* fptr;
        fopen_s(&fptr, "example1.h264", "wb");
        // write sps and pps in the video file
        fwrite(nals->p_payload, header_size, 1, fptr);
    
        int size = 1920 * 1080 * 4;
        char* bmp = new char[size];
        FILE* bitptr;
        errno_t err = fopen_s(&bitptr, "flower.bmp", "rb");
        fseek(bitptr, 54, SEEK_SET);
        fread(bmp, size, 1, bitptr);
        fclose(bitptr);
    
        srs_rtmp_t rtmp = srs_rtmp_create("127.0.0.1:1935/live/test");
    
        if (srs_rtmp_handshake(rtmp) != 0)
        {
            std::cout << "Simple handshake failed.";
            return -1;
        }
    
        std::cout << "Handshake completed successfully.\n";
    
        if (srs_rtmp_connect_app(rtmp) != 0) {
            std::cout << "Connecting to host failed.";
            return -1;
        }
    
        std::cout << "Connected to host successfully.\n";
    
        if (srs_rtmp_publish_stream(rtmp) != 0) {
            std::cout << "Publish signal failed.";
        }
    
        std::cout << "Publish signal success\n";
    
        // write sps and pps in the live stream
        int ret = srs_h264_write_raw_frames(rtmp, reinterpret_cast(nals->p_payload), header_size, 0, 0);
        ret = check_ret(ret);
        if (!ret)
            return -1;
        std::cout << "SPS and PPS sent.\n";
    
        // main loop
        std::cout << "Now streaming and encoding\n";
        int i = 1800;
        while (i--)
        {
    
            picIn.img.plane[0] = reinterpret_cast(bmp);
            picIn.i_pts = pts++;
            i_frame_size = x264_encoder_encode(h, &nals, &i_nal, &picIn, &picOut);
            if (i_frame_size)
            {
                for (int j = 0; j < i_nal; j++)
                {
    
                    x264_nal_t* nal = nals + j;
                    // write data in the video file
                    fwrite(nal->p_payload, nal->i_payload, 1, fptr);
                    // write data in the live stream
                    ret = srs_h264_write_raw_frames(rtmp, reinterpret_cast(nal->p_payload), nal->i_payload, dts, dts);
                    ret = check_ret(ret);
                    if (!ret)
                    {
                        return -1;
                    }
                }
            }
            else
            {
                std::cout << "i_frame_size = 0 (encoder failed)\n";
            }
            dts += 33;
        }
    
        while (x264_encoder_delayed_frames(h))
        {
            i_frame_size = x264_encoder_encode(h, &nals, &i_nal, NULL, &picOut);
            if (i_frame_size)
            {
                fwrite(nals->p_payload, i_frame_size, 1, fptr);
            }
        }
    
        std::cout << "\nAll done\n";
        std::cout << "Output video is example1.h264 and it is viewable in VLC";
    
        return 0;
    }
    
    int check_ret(int ret)
    {
        if (ret != 0) {
            if (srs_h264_is_dvbsp_error(ret)) {
                srs_human_trace("ignoring drop video error, code=%d", ret);
            }
            else if (srs_h264_is_duplicated_sps_error(ret)) {
                srs_human_trace("ignoring duplicated sps, code=%d", ret);
            }
            else if (srs_h264_is_duplicated_pps_error(ret)) {
                srs_human_trace("ignoring duplicated pps, code=%d", ret);
            }
            else {
                srs_human_trace("sending h264 raw data failed. ret=%d", ret);
                return 0;
            }
        }
        return 1;
    }
    

    If you would like to download the original flower.bmp file, here is the link: https://gofile.io/d/w2kX56 This error can be reproduced in any other bmp file also.

    Please tell me what is causing this problem when multi-threading is enabled. Am I setting wrong values? Is the code in which I am streaming the encoded data wrong?

  • FFmpeg - generate x264 CBR video transport stream with C-API

    6 juillet 2020, par ZeroDefect

    Using various posts sprinkled around the Internet, including this one here on SO, I've been able to understand how to use the FFmpeg cli to generate a CBR video bitrate using the x264 codec (wrapped in an MPEG-2 transport stream). Note: I'm concerned with the video bitrate - nothing else.

    ffmpeg -i cbr_test_file_input.mp4 -c:v libx264 -pix_fmt yuv420p -b:v 6000000 -preset fast -tune film -g 25 -x264-params vbv-maxrate=6000:vbv-bufsize=6000:force-cfr=1:nal-hrd=cbr -flags +ildct+ilme x264_cbr_test_output.ts
    

    However, I'm trying to approach this from an FFmpeg C-API point of view. I'm having issues. I've knocked together some code to try do something very similar to what is being done in the FFmpeg CLI. I can generate a transport stream of what I think should be CBR, but the profile of the video bitrate is very different from what I thought was the FFmpeg cli equivalent:

    The initialisation of the AVCodecContext looks something like:

          av_dict_set(&pDict, "preset", "faster", 0);
          av_dict_set(&pDict, "tune", "film", 0);
          av_dict_set_int(&pDict, "rc-lookahead", 25, 0);
    
          pCdcCtxOut->width = pCdcCtxIn->width;
          pCdcCtxOut->height = pCdcCtxIn->height;
          pCdcCtxOut->pix_fmt = AV_PIX_FMT_YUV420P;
          pCdcCtxOut->gop_size = 25;
    
          // Going for 6Mbit/s
          pCdcCtxOut->bit_rate = 6000000;
          //pCdcCtxOut->rc_min_rate = pCdcCtxOut->bit_rate;
          pCdcCtxOut->rc_max_rate = pCdcCtxOut->bit_rate;
          pCdcCtxOut->rc_buffer_size = pCdcCtxOut->bit_rate;
          pCdcCtxOut->rc_initial_buffer_occupancy = static_cast((pCdcCtxOut->bit_rate * 9) / 10);
    
          std::string strParams = "vbv-maxrate="
                                  + std::to_string(pCdcCtxOut->bit_rate / 1000)
                                  + ":vbv-bufsize="
                                  + std::to_string(pCdcCtxOut->bit_rate / 1000)
                                  + ":force-cfr=1:nal-hrd=cbr";
    
          av_dict_set(&pDict, "x264-params", strParams.c_str(), 0);
    
          pCdcCtxOut->field_order = AV_FIELD_TT;
          pCdcCtxOut->flags = (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME | AV_CODEC_FLAG_CLOSED_GOP);
    
          // WARN: Make some assumptions here!
          pCdcCtxOut->time_base = AVRational{1,25};
          pCdcCtxOut->framerate = AVRational{25,1};
          pCdcCtxOut->sample_aspect_ratio = AVRational{64,45};
    

    The output graphs appear very different:

    FFmpeg CLI output

    Above is the FFmpeg CLI output - video bitrate holds fairly steady.

    enter image description here

    Above is the output of my sample application - some significant dips in the video bitrate.

    I've taken this a step further and created a git repo consisting of:

    • Code of sample application
    • Test input file (.mp4)
    • Outputs (.ts file) of tests
    • Graphs of output bitrates.