Newest 'x264' Questions - Stack Overflow

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

Les articles publiés sur le site

  • X264 : How to compile x264 with swscale support ?

    23 avril 2014, par user1884325

    Objective

    I am trying to build:

    • an x264 static library (.lib) with swscale support. I would like to use this library in a Visual Studio project where 24-bit RGB bitmap images are:

      1. Converted from RGB to YUV2
      2. The converted image is sent to the x264 encoder
      3. and the output of the encoder is streamed to a remote IP-endpoint via UDP.
    • an x264 executable (.exe) with swscale support. I would like to use the executable for the same purpose as described above. In another Visual Studio project, I will start the x264.exe up as a separate process and pipe bitmap data to the x264 process via its stdin and read out the encoded data from the process's stdout.

    Problem

    I am having some trouble figuring out how to compile with swscale support. I need swscale support for both the executable and the library.

    Status

    So far I have downloaded the latest x264 source from the x264 website.

    I have installed MINGW on my machine and when I run 'configure' and 'make' I get the x264 static library - but without swscale support.

    I haven't been able to find a detailed step-by-step guide on how to include swscale in the x264 library. The closest I've come to a description is this discussion:

    http://forum.doom9.org/showthread.php?t=165350

    So I downloaded libpack from:

    http://komisar.gin.by/mingw/index.html

    and extracted it to my harddrive:

    Then I executed 'make' and 'configure' (again) in my x264 directory:

    ./configure --extra-cflags="-I/m/somePath/libpack/libpack/libpack/include" --extra-ldflags="-L/m/somePath/libpack/libpack/libpack/lib"
    

    I have the following in the lib and include directory:

    lib directory

    incl directory

    When I execute the above 'configure' I get:

    platform:      X86
    system:        WINDOWS
    cli:           yes
    libx264:       internal
    shared:        no
    static:        no
    asm:           yes
    interlaced:    yes
    avs:           avisynth
    lavf:          no
    ffms:          no
    mp4:           lsmash
    gpl:           yes
    thread:        win32
    opencl:        yes
    filters:       crop select_every
    debug:         no
    gprof:         no
    strip:         no
    PIC:           no
    bit depth:     8
    chroma format: all
    
    You can run 'make' or 'make fprofiled' now.
    bash.exe"-3.1$
    

    When I execute 'make' I end up with this error:

    gcc.exe: error: unrecognized command line option '-fomit-frame-poin'
    gcc.exe: fatal error: no input files
    compilation terminated.
    make: *** [.depend] Error 1
    bash.exe"-3.1$
    

    Question What am I doing wrong??

  • libx264 encoder video plays too fast

    23 avril 2014, par Nick

    I'm trying to write a program that uses libx264 to encode the video frames. I've wrapped this code into a small class (see below). I have frames that are in YUV420 format. libx264 encodes the frames and I save them to a file. I can play the file back in VLC, all of the frames are there, but it plays back at several hundred times the actual frame rate. Currently I am capturing frames at 2.5 FPS, but they play back as if it was recorded at 250 or more FPS. I've tried to change the frame rate with no luck.

    I've also tried to set

    _param.b_vfr_input = 1
    

    and then set the time bases appropriately, but that causes my program to crash. Any ideas? My encode code is shown below. I've also included the output of ffprobe -show_frames

    Wrapper Class:

    x264wrapper::x264wrapper(int width, int height, int fps, int timeBaseNum, int timeBaseDen, int vfr)
    {
        x264_param_default_preset(&_param, "veryfast", "zerolatency");
        _param.i_threads = 1;
        _param.i_width = width;
        _param.i_height = height;
        _param.i_fps_num = fps;
        _param.i_fps_den = 1;
        // Intra refres:
        _param.i_keyint_max = fps;
        _param.b_intra_refresh = 1;
        //Rate control:
        _param.rc.i_rc_method = X264_RC_CRF;
        //_param.rc.i_rc_method = X264_RC_CQP;
        _param.rc.f_rf_constant = 25;
        _param.rc.f_rf_constant_max = 35;
        //For streaming:
        _param.b_repeat_headers = 1;
        _param.b_annexb = 1;    
        // misc
        _param.b_vfr_input = vfr;
        _param.i_timebase_num = timeBaseNum; 
        _param.i_timebase_den = timeBaseDen;
    
        _param.i_log_level = X264_LOG_DEBUG;
    
        _encoder = x264_encoder_open(&_param);
    
        cout << "Timebase " << _param.i_timebase_num << "/" << _param.i_timebase_den << endl;
        cout << "fps " << _param.i_fps_num << "/" << _param.i_fps_den << endl;
        _ticks_per_frame = (int64_t)_param.i_timebase_den * _param.i_fps_den / _param.i_timebase_num / _param.i_fps_num;
        cout << "ticks_per_frame " << _ticks_per_frame << endl;
        int result = x264_picture_alloc(&_pic_in, X264_CSP_I420, width, height);
        if (result != 0)
        {
            cout << "Failed to allocate picture" << endl;
            throw(1);
        }
    
        _ofs = new ofstream("output.h264", ofstream::out | ofstream::binary);
        _pts = 0;
    }
    
    
    x264wrapper::~x264wrapper(void)
    {
        _ofs->close();
    }
    
    
    
    void x264wrapper::encode(uint8_t * buf)
    {
        x264_nal_t* nals;
        int i_nals;
        convertFromBalserToX264(buf);
        _pts += _ticks_per_frame;
        _pic_in.i_pts = _pts;
        x264_picture_t pic_out;
        int frame_size = x264_encoder_encode(_encoder, &nals, &i_nals, &_pic_in, &pic_out);
        if (frame_size >= 0)
        {
            _ofs->write((char*)nals[0].p_payload, frame_size);
        }
        else
        {
            cout << "error: x264_encoder_encode failed" << endl;
        }
    }
    

    Output of ffprobe -show_frames:

    [FRAME]
    media_type=video
    key_frame=1
    pkt_pts=N/A
    pkt_pts_time=N/A
    pkt_dts=N/A
    pkt_dts_time=N/A
    pkt_duration=48000
    pkt_duration_time=0.040000
    pkt_pos=0
    width=1920
    height=1080
    pix_fmt=yuv420p
    sample_aspect_ratio=N/A
    pict_type=I
    coded_picture_number=0
    display_picture_number=0
    interlaced_frame=0
    top_field_first=0
    repeat_pict=0
    reference=0
    [/FRAME]
    [FRAME]
    media_type=video
    key_frame=0
    pkt_pts=N/A
    pkt_pts_time=N/A
    pkt_dts=N/A
    pkt_dts_time=N/A
    pkt_duration=N/A
    pkt_duration_time=N/A
    pkt_pos=54947
    width=1920
    height=1080
    pix_fmt=yuv420p
    sample_aspect_ratio=N/A
    pict_type=P
    coded_picture_number=1
    display_picture_number=0
    interlaced_frame=0
    top_field_first=0
    repeat_pict=0
    reference=0
    [/FRAME]
    [FRAME]
    media_type=video
    key_frame=0
    pkt_pts=N/A
    pkt_pts_time=N/A
    pkt_dts=N/A
    pkt_dts_time=N/A
    pkt_duration=N/A
    pkt_duration_time=N/A
    pkt_pos=57899
    width=1920
    height=1080
    pix_fmt=yuv420p
    sample_aspect_ratio=N/A
    pict_type=P
    coded_picture_number=2
    display_picture_number=0
    interlaced_frame=0
    top_field_first=0
    repeat_pict=0
    reference=0
    [/FRAME]
    
  • X264 : How to access NAL units from encoder ?

    18 avril 2014, par user1884325

    When I call

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

    and subsequently write each NAL to a file like this:

         if (frame_size >= 0)
         {
            int i;
            int j;
    
            for (i = 0; i < i_nals; i++)
            {
               printf("******************* NAL %d (%d bytes) *******************\n", i, nals[i].i_payload);
               fwrite(&(nals[i].p_payload[0]), 1, nals[i].i_payload, fid);
            }
         }
    

    then I get this

    Beginning of NAL file

    My questions are:

    1) Is it normal that there's readable parameters in the beginning of the file?

    2) How do I configure the X264 encoder so that the encoder returns frames that I can send via UDP without the packet getting fragmented (size must be below 1390 or somewhere around that).

    3) With the x264.exe I pass in these options:

    "--threads 1 --profile baseline --level 3.2 --preset ultrafast --bframes 0 --force-cfr --no-mbtree --sync-lookahead 0 --rc-lookahead 0 --keyint 1000 --intra-refresh" 
    

    How do I map those to the settings in the X264 parameters structure ? (x264_param_t)

    4) I have been told that the x264 static library doesn't support bitmap input to the encoder and that I have to use libswscale for conversion of the 24bit RGB input bitmap to YUV2. The encoder, supposedly, only takes YUV2 as input? Is this true? If so, how do I build libswscale for the x264 static library?

  • X264 Encoder API

    16 avril 2014, par user1884325

    I'm studying the X264 API for encoding images.

    So far I've built the X264 library and the following code snippet shows how far I am:

      int frame_size;
      x264_t* encoder;
      x264_picture_t pic_in, pic_out;
      x264_param_t x264Param;
      int fps = 20;
      int width = 1280;
      int height = 720;
      x264_nal_t* nals;
      int i_nals;
    
      x264_param_default_preset(&x264Param, "veryfast", "zerolatency");
      x264Param.i_threads = 1;
      x264Param.i_width = 1280;
      x264Param.i_height = 720;
      x264Param.i_fps_num = fps;
      x264Param.i_fps_den = 1;
      x264Param.i_keyint_max = fps;
      x264Param.b_intra_refresh = 1;
      x264Param.rc.i_rc_method = X264_RC_CRF;
      x264Param.rc.f_rf_constant = 25;
      x264Param.rc.f_rf_constant_max = 35;
      x264Param.b_repeat_headers = 1;
      x264Param.b_annexb = 1;
      x264_param_apply_profile(&x264Param, "baseline");
    
      encoder = x264_encoder_open(&x264Param);
    
      x264_picture_alloc(&pic_in, X264_CSP_BGR, width, height);
    
      /* How to fill in bitmap data? */
    
      frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
      if (frame_size >= 0)
      {
          printf("OK\n");
      }
    

    So I'm trying to encode a 24bit BGR bitmap image. However, the x264 header file doesn't show any API function for writing the bitmap image to the encoder. How is this done?

    EDIT

    This code snippet seems to work. I would appreciate a review and some comments. Thanks.

      int frame_size;
      int accum_frame_size;
      x264_t* encoder;
      x264_picture_t pic_in, pic_out;
      x264_param_t x264Param;
      int fps = 20;
      int width = 1280;
      int height = 720;
      x264_nal_t* nals;
      int i_nals;
      int64_t frameCount = 0;
      int k;
    
      for (k = 0; k < (1280*3*720); k++)
      {
         bgr[k] = rand();
      }
    
      x264_param_default_preset(&x264Param, "veryfast", "zerolatency");
      x264Param.i_threads = 1;
      x264Param.i_width = 1280;
      x264Param.i_height = 720;
      x264Param.i_fps_num = fps;
      x264Param.i_fps_den = 1;
      x264Param.i_keyint_max = fps;
      x264Param.b_intra_refresh = 1;
      x264Param.rc.i_rc_method = X264_RC_CRF;
      x264Param.i_csp = X264_CSP_BGR;
      x264Param.rc.f_rf_constant = 25;
      x264Param.rc.f_rf_constant_max = 35;
      x264Param.b_repeat_headers = 1;
      x264Param.b_annexb = 1;
      x264_param_apply_profile(&x264Param, "baseline");
    
      encoder = x264_encoder_open(&x264Param);
    
      x264_picture_alloc(&pic_in, X264_CSP_BGR, width, height);
    
      /* Load 24-bit BGR bitmap */
      pic_in.img.i_csp = X264_CSP_BGR;
      pic_in.img.i_plane = 1;
      pic_in.img.i_stride[0] = 3 * 1280;
      pic_in.img.plane[0] = bgr;
      pic_in.i_pts = frameCount;
      pic_in.i_type = X264_TYPE_AUTO;
      pic_out.i_pts = frameCount;
    
      /* Returns a frame size of 912 for first frame in this case */
      frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
    
      printf("Decoder returned frame size = %d \n", frame_size);
      printf("Decoder returned %d NAL units \n", i_nals);
      if (frame_size >= 0)
      {
         int i;
         int j;
    
    
         accum_frame_size = 0;
         for (i = 0; i < i_nals; i++)
         {
            printf("******************* NAL %d (%d bytes) *******************\n", i, nals[i].i_payload);
            for (j = 0; j < nals[i].i_payload; j++)
            {
               if (j == 0) printf("First 10 bytes: ");
               if (j < 10) printf("%02X |", nals[i].p_payload[j]);
               accum_frame_size++;
            }
            printf("\n");
    
         }
      }
    
      printf("Verified frame size = %d \n", accum_frame_size);
    

    EDIT #2 The encoder outputs this:

         x264 [error]: baseline profile doesn't support 4:4:4
         x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
         x264 [info]: profile High 4:4:4 Predictive, level 3.1, 4:4:4 8-bit
         Decoder returned frame size = 1467194
         Decoder returned 4 NAL units
         ******************* NAL 0 (31 bytes) *******************
         First 10 bytes: 00 |00 |00 |01 |67 |F4 |00 |1F |91 |89 |
         ******************* NAL 1 (8 bytes) *******************
         First 10 bytes: 00 |00 |00 |01 |68 |EF |1F |2C |
         ******************* NAL 2 (595 bytes) *******************
         First 10 bytes: 00 |00 |01 |06 |05 |FF |FF |4C |DC |45 |
         ******************* NAL 3 (1466560 bytes) *******************
         First 10 bytes: 00 |00 |01 |65 |88 |82 |0A |FF |F5 |B0 |
         Verified frame size = 1467194
    

    Isn't each NAL unit supposed to start with 0x00 0x00 0x00 0x01 ?

    szatmary : I appreciate your valuable feedback. So you're saying that each NAL unit does not necessarily start with 0,0,0,1. However, I'm a bit unclear on your answer. Are you implying that with a certain configuration the NAL units will start with 0,0,0,1 ? If so, which configuration is that? I need to make sure that each NAL unit I transmit out on the network to a remote receiver starts with 0,0,0,1. Prior to exploring the x264 library I was using the x264 exe and piped BMP data in and encoded data out from the x264 process. I then parsed the encoder output and looked for NAL units by looking for 0,0,0,1. How do I accomplish the same with the x264 library?

    Regarding libswscale:

    I downloaded the ffmpeg source and ran configure and make in MINGW. After the process had completed I couldn't find anything but a number of .exe files. How do I build actual static libraries (.lib) which I can use in a Visual Studio project?

  • x264/avcodec : Deduce frame sequence number from NAL unit

    4 avril 2014, par Dan Tumaykin

    I'm using avcodec H264 decoder in my project. I receive NAL units from network, stick together NALs from same frame (additional header is added on network layer) and than pass to the decoder. I was wondering if frame sequence number is encoded into NAL unit - it would be logical, as we need the reference to IDR frames.

    If this information is present - how can I extract it?

    Right now I looking into ITU-T H.264 specification, which is quite complex I can admit. So far I have not found the answer to my question.