c++gstreamerh.264gstreamer-1.0x264

Encode NV12 frames to h264 using x264enc (appsrc and appsink)


I am trying to encode NV12 frames to h264 files. For that I found a following code that is encoding raw frames to jpeg using jpegenc. The code works fine with jpeg encoder after some minor changes for NV12 frames. However x264enc encode only first frame and the rest of them are outputting the pps error when running with mplayer.

First frame output

[h264 @ 0x7f1ea2ed3600]decoding for stream 0 failed
[lavf] stream 0: video (h264), -vid 0
VIDEO:  [H264]  1920x1080  0bpp  1.000 fps    0.0 kbps ( 0.0 kbyte/s)
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.54.100 (external)
Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)
==========================================================================
Load subtitles in ./
Audio: no sound
Starting playback...
Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
VO: [vdpau] 1920x1080 => 1920x1080 Planar YV12

Error frame output:


[h264 @ 0x7f9c2e44f4c0]non-existing PPS 0 referenced
[h264 @ 0x7f9c2e44f4c0]non-existing PPS 0 referenced
[h264 @ 0x7f9c2e44f4c0]decode_slice_header error

[h264 @ 0x7f9c2eece600]decoding for stream 0 failed
[h264 @ 0x7f9c2eece600]Could not find codec parameters for stream 0 (Video: h264, none): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
[lavf] stream 0: video (h264), -vid 0
VIDEO:  [H264]  0x0  0bpp  25.000 fps    0.0 kbps ( 0.0 kbyte/s)
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.54.100 (external)
Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)

I have changed the pipeline, block size and added queue. Pipeline:

pipeline = gst_pipeline_new("mypipeline");
appsrc = gst_element_factory_make("appsrc", "mysource");
queue1 = gst_element_factory_make("queue", "myqueue1");
jpegenc = gst_element_factory_make("x264enc", "myenc");
//parser = gst_element_factory_make("h264parse", "parser");
appsink = gst_element_factory_make("appsink", "mysink");


...
g_object_set(G_OBJECT(appsrc), "format", GST_FORMAT_TIME, "is-live", TRUE, "do-timestamp", TRUE, NULL);
g_object_set(G_OBJECT(jpegenc), "tune", 0x00000004, NULL); // 0x00000004 is the ultrafast preset

...
capsappsrc2Jpegenc = gst_caps_new_simple("video/x-raw", "format",
            G_TYPE_STRING, "NV12", "width", G_TYPE_INT, width, "height",
            G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, 1, 1, 
            "interlace-mode", G_TYPE_STRING, "progressive",
            "colorimetry", G_TYPE_STRING, "bt601",
            NULL);

    // blocksize is important for jpegenc to know how many data to expect from appsrc in a single frame, too
    char szTemp[64];
    sprintf(szTemp, "%d", 3110400);
    g_object_set(G_OBJECT (appsrc), "blocksize", szTemp,
            NULL);


Solution

  • Encoder Setting

    g_object_set(G_OBJECT(appsrc), "format", GST_FORMAT_TIME, "is-live", TRUE, "do-timestamp", TRUE, NULL);
    g_object_set(G_OBJECT(jpegenc), "tune", 0x00000004, NULL); // 0x00000004 is the ultrafast preset    
    g_object_set(G_OBJECT(jpegenc), "speed-preset", 1, NULL);   //g_object_set(G_OBJECT(jpegenc), "bitrate", 500, NULL);
    g_object_set(G_OBJECT(jpegenc), "key-int-max", 1, NULL); //Maximal distance between two key-frames  
    g_object_set(G_OBJECT(jpegenc), "b-adapt", TRUE, NULL);     g_object_set(G_OBJECT(jpegenc), "bframes", 1, NULL);