Mohamed El-Sayed
Mohamed El-Sayed

Reputation: 501

encode x264(libx264) raw yuv frame data

I am trying to encode an MP4 video using raw YUV frames data, but I am not sure how can I fill the plane data (preferably without using other libraries like ffmpeg)

The frame data is already encoded in I420, and does not need conversion.

Here is what I am trying to do:

const char *frameData = /* Raw frame data */;

x264_t *encoder = x264_encoder_open(&param);
x264_picture_t imgInput, imgOutput;
x264_picture_alloc(&imgInput, X264_CSP_I420, width, height);

// how can I fill the struct data of imgInput

x264_nal_t *nals;
int i_nals;
int frameSize = x264_encoder_encode(encoder, &nals, &i_nals, &imgInput, &imgOutput);

The equivalent command line that I have found is :

 x264 --output video.mp4 --fps 15 --input-res 1280x800 imgdata_01.raw 

But I could not figure out how the app does it.

Thanks.

Upvotes: 2

Views: 5696

Answers (2)

nobody555
nobody555

Reputation: 2374

Look at libx264 API usage example. This example use fread() to fill frame allocated by x264_picture_alloc() with actual i420 data from stdin. If you already have i420 data in memory and want to skip memcpy step than instead of it you can:

  1. Use x264_picture_init() instead of x264_picture_alloc() and x264_picture_clean(). Because you don't need allocate memory on heap for frame data.
  2. Fill x264_picture_t.img struct fields:
  • i_csp = X264_CSP_I420;
  • i_plane = 3;
  • plane[0] = pointer to Y-plane;
  • i_stride[0] = stride in bytes for Y-plane;
  • plane[1] = pointer to U-plane;
  • i_stride[1] = stride in bytes for U-plane;
  • plane[2] = pointer to V-plane;
  • i_stride[2] = stride in bytes for V-plane;

Upvotes: 3

Mohamed El-Sayed
Mohamed El-Sayed

Reputation: 501

To complete the answer above, this is an example to fill an x264_picture_t image.

int fillImage(uint8_t* buffer, int width, int height, x264_picture_t*pic){
    int ret = x264_picture_alloc(pic, X264_CSP_I420, width, height);
    if (ret < 0) return ret;
    pic->img.i_plane = 3; // Y, U and V
    pic->img.i_stride[0] = width;
    // U and V planes are half the size of Y plane
    pic->img.i_stride[1] = width / 2;
    pic->img.i_stride[2] = width / 2;
    int uvsize = ((width + 1) >> 1) * ((height + 1) >> 1);
    pic->img.plane[0] = buffer; // Y Plane pointer
    pic->img.plane[1] = buffer + (width * height); // U Plane pointer
    pic->img.plane[2] = pic->img.plane[1] + uvsize; // V Plane pointer
    return ret;
}

Upvotes: 0

Related Questions