This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux: AM5728 GStreamer appsink issue



Tool/software: Linux

hello:

I want to save the h264 file using appsink.

Our gstreamer pipeline is like below:

V4l2src—>vpe —> ducatih264enc —>appsink

Here's the code I wrote:

#define WIDTH 1280
#define HEIGHT 720

GstFlowReturn sink_new_sample(GstElement* object, gpointer user_data)
{
GstSample *sample;
GstBuffer *buffer;
GstCaps *caps;
GstStructure *s;
int width, height;
int res;

sample = gst_app_sink_pull_sample(GST_APP_SINK(object));
if (sample == 0)
{
return GST_FLOW_OK;
}

caps = gst_sample_get_caps(sample);
if(!caps){
printf("could not get snapshot format\n");
}
s = gst_caps_get_structure(caps, 0);
res = gst_structure_get_int(s, "width", &width);
res |= gst_structure_get_int(s, "height", &height);
if(!res){
printf("could not get snapshot dimension\n");
}

printf("width = %d, height = %d\n", width, height);

buffer = gst_sample_get_buffer(sample);
if (buffer == 0)
{
return GST_FLOW_OK;
}

GstMapInfo map;

if (gst_buffer_map(buffer, &map, GST_MAP_READ))
{

printf("======= save h264 ======\n");
static FILE *fp = 0;
fp = fopen("./test.h264", "wb");
if (fp != NULL)
{

fwrite(map.data, 1, map.size, fp);
//fclose(fp);
}

gst_buffer_unmap(buffer, &map);
}

gst_sample_unref(sample);

return GST_FLOW_OK;

}

int main(int argc, char *argv[])
{
GstElement *pipeline, *v4l2src, *filter, *vpe, *filter1, *ducatih264enc, *queue, *appsink;
GstCaps *caps, *caps1;
static GMainLoop *loop;

gst_init(&argc, &argv);

loop = g_main_loop_new(NULL, FALSE);

pipeline = gst_pipeline_new("pipeline");
if (!pipeline) {
g_printerr("%d gst_pipeline_new error \n", __LINE__);
return -1;
}

v4l2src = gst_element_factory_make("v4l2src", "v4l2src0");
if (!v4l2src) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

filter = gst_element_factory_make("capsfilter", "capsfilter0");
if (!filter) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

vpe = gst_element_factory_make("vpe", "vpe0");
if (!vpe) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

filter1 = gst_element_factory_make("capsfilter", "capsfilter1");
if (!filter1) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

ducatih264enc = gst_element_factory_make("ducatih264enc", "ducatih264enc0");
if (!ducatih264enc) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

queue = gst_element_factory_make("queue", "queue0");
if (!queue) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

appsink = gst_element_factory_make("appsink", "appsink0");
if (!appsink) {
g_printerr("%d gst_element_factory_make error \n", __LINE__);
}

GstBus *bus;
bus = gst_pipeline_get_bus((GstPipeline*)pipeline);
gst_bus_add_watch(bus, (GstBusFunc)bus_callback, 0);
gst_object_unref(bus);

g_object_set(G_OBJECT(v4l2src), "device", "/dev/video1", NULL);
g_object_set(G_OBJECT(v4l2src), "io-mode", 4, NULL);
caps = gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, "YUY2",
"width", G_TYPE_INT, WIDTH,
"height", G_TYPE_INT, HEIGHT,
"framerate", GST_TYPE_FRACTION, 60, 1,
NULL);
g_object_set(G_OBJECT(filter), "caps", caps, NULL);
gst_caps_unref(caps);

g_object_set(G_OBJECT(vpe), "num-input-buffers", 8, NULL);
caps1 = 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, 60, 1,
NULL);
g_object_set(G_OBJECT(filter1), "caps", caps1, NULL);
gst_caps_unref(caps1);

//appsink
printf("====== appsink ====== \n");
GstCaps *sink_caps;

sink_caps = 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, 60, 1,
NULL);

g_object_set(appsink, "emit-signals", TRUE, "caps", sink_caps,"sync", FALSE, NULL);

g_signal_connect(appsink, "new-sample", G_CALLBACK(sink_new_sample), NULL);

gst_bin_add_many(GST_BIN(pipeline), v4l2src, filter, vpe, filter1, ducatih264enc, queue, appsink, NULL);

gst_element_link_many(v4l2src, filter, vpe, filter1, ducatih264enc, queue, appsink, NULL);

gst_element_set_state(pipeline, GST_STATE_PLAYING);

g_main_loop_run(loop);
g_main_loop_unref(loop);
return 0;
}

But I can not collect data,what is the reason?

  • The software team have been notified. They will respond here.
  • Hello,

    I would recommend you:
    1. Add h264parse element after encoder element;
    2.Replace appsink element with filesink element to verify that your code is working. If is not working with filesink element also, please post the error that you are observing.
    3. Check this tutorial for appsink usage:
    gstreamer.freedesktop.org/.../short-cutting-the-pipeline.html

    Hope this helps.

    BR
    Margarita

  • Hello,

    Make sure when you get a callback when the buffer is done write to the file and  close it on eos.

    BR
    Margarita

  • hello:

    1、Add h264parse after ducatih264enc. pipeline is as follows:

    V4l2src—>vpe —> ducatih264enc —>h264parse —> appsink

    Add gst_bus_add_watch(bus, (GstBusFunc)bus_callback, 0) in the code, to get GstMessage print information.

    static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr)
    {
    switch (GST_MESSAGE_TYPE(message)) {
    case GST_MESSAGE_ERROR: {
    gchar *debug;
    GError *err;

    gst_message_parse_error(message, &err, &debug);
    g_print("Error %s\n", err->message);
    g_error_free(err);
    g_free(debug);
    }
    break;
    case GST_MESSAGE_WARNING: {
    gchar *debug;
    GError *err;
    const gchar *name;
    gst_message_parse_warning(message, &err, &debug);
    g_print("Warning %s\nDebug %s\n", err->message, debug);
    name = GST_MESSAGE_SRC_NAME(message);
    g_print("Name of src %s\n", name ? name : "nil");
    g_error_free(err);
    g_free(debug);
    }
    break;
    case GST_MESSAGE_EOS:
    g_print("End of stream\n");
    break;
    case GST_MESSAGE_STATE_CHANGED:
    break;
    default:
    g_print("got message %s\n", \
    gst_message_type_get_name(GST_MESSAGE_TYPE(message)));
    break;
    }
    return TRUE;
    }

    Appsink caps set as follows:

    sink_caps = gst_caps_new_simple("video/x-h264",
            "stream-format",G_TYPE_STRING,"byte-stream",
            "width",G_TYPE_INT,WIDTH,
            "height",G_TYPE_INT,HEIGHT,
            NULL);
        g_object_set(appsink, "emit-signals", TRUE, "caps", sink_caps,"sync", FALSE, NULL);
        g_signal_connect(appsink, "new-sample", G_CALLBACK(sink_new_sample), NULL);

    Compile and execute, you can save the test.h264 file in the appsink signal function sink_new_sample. But "ls -lh" check test.h264 found no data

    GstMessage print information:

    got message stream-status
    got message stream-status
    got message stream-status
    got message stream-status
    got message stream-status
    got message stream-status
    got message new-clock
    got message stream-start
    got message qos
    got message tag
    got message async-done
    got message tag
    got message tag
    got message tag

    Keep printing the "got message tag".


    appsink does not set caps 

      g_object_set(appsink, "emit-signals", TRUE, "sync", FALSE, NULL);

      g_signal_connect(appsink, "new-sample", G_CALLBACK(sink_new_sample), NULL);
    The test results are the same as above.
     
    2、Replace appsink element with filesink element You can successfully save h264 files
    pipeline is as follows:
    gst-launch-1.0 v4l2src device=/dev/video1 io-mode=4 ! 'video/x-raw, format=(string)YUY2, width=(int)1280, height=(int)720, framerate=(fraction)60/1' ! vpe num-input-buffers=8 ! 'video/x-raw, format=(string)NV12, width=(int)1280, height=(int)720,framerate=(fraction)60/1' ! ducatih264enc bitrate=1000 ! h264parse ! filesink location=test.h264
     
    3、We want to use appsink to save the file, is there any good advice?

     

     

     

     

     

     

     

     

     

     

     

     

  • Hello,

    Please check the tutorial that I posted the gst_caps_from_string function for how the caps are set for appsrc&appsink. I would recommend you to check new_sample function in this tutorial also.

    BR
    Margarita