Using appsrc in pull mode

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Using appsrc in pull mode

Nostalgia
Hi ,

I am writing a code that read an yuv file, encode it and save the results of
encoding in a new file using this pipeline :
appsrc -> encoder -> capsfilter -> filesink

So I use appsrc to push data from the file to the pipeline, knowing the size
of the file I then use appsrc in pull mode. My code runs correctly and I
obtain the right output but the problem that it doesn't return to the main
function when finishing reading the file :

//g++ -Wall -std=c++11  PullMode.cpp -o pm $(pkg-config --cflags --libs
gstreamer-app-1.0) -ldl

#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <cstring>
#include <iostream>
#include <unistd.h>

using namespace std;

#define WIDTH 640
#define HEIGHT 360
#define FORMAT "I420"
#define FRAME_RATE 25
#define FRAME_TIME 40000000
#define FRAME_SIZE ((WIDTH*HEIGHT*3) >> 1 )
#define FRAME_NUMBER(x) (int)(x/FRAME_SIZE)
#define Input_FILE
"/media/ubuntu/6634-3132/Hanine/InitialFiles/Basketball.yuv"
#define Output_FILE
"/media/ubuntu/6634-3132/Hanine/Basketball_appsource_pull.264"

static GstClockTime timestamp = 0;
static FILE *yuv_file;
static int num_buffers_to_send;
static int nbuffers = 0;

typedef struct _CustomData {

  GstElement *pipeline, *source, *encoder, *filter, *fsink;
  GMainLoop *loop;
   
} CustomData;

static void cb_need_data (GstElement *appsrc,
   CustomData * data) {

        char* ptr;
        GstBuffer *buffer;
        GstFlowReturn ret;

        ptr = (char*)malloc (FRAME_SIZE);
        g_assert(ptr != NULL);

        fread(ptr, 1 , FRAME_SIZE, yuv_file);

        buffer = gst_buffer_new_wrapped (ptr, FRAME_SIZE);
        buffer->pts = timestamp;
        buffer->dts = timestamp;
        buffer->duration = FRAME_TIME;

        g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);

        gst_buffer_unref(buffer);

        timestamp += FRAME_TIME;
        nbuffers +=1;

        if (ret != GST_FLOW_OK) {
                g_main_loop_quit (data->loop);
                printf(" Error in pushing data to appsrc\n");
        }
}

int main (int argc, char *argv[]) {

        CustomData data;
        GstCaps *input_enc_caps, *output_enc_caps;
        GstStateChangeReturn state_ret;

        /* Get a pointer to the YUV input file*/
        yuv_file = fopen(Input_FILE, "rb");
        g_assert(yuv_file != NULL);

        /* Get the size of the input file*/
        fseek (yuv_file , 0 , SEEK_END);
        long int size = ftell (yuv_file);
        rewind (yuv_file);
        num_buffers_to_send = FRAME_NUMBER(size);
       

        /* Initialize cumstom data structure */
        memset (&data, 0, sizeof (data));

        /* Initialize GStreamer and create the mainloop */
        gst_init (&argc, &argv);
        data.loop = g_main_loop_new (NULL, FALSE);

        /* Create the elements */
        data.source = gst_element_factory_make ("appsrc", "myapp_source");
        data.encoder = gst_element_factory_make ("omxh264enc", "myapp_encoder");
        data.filter = gst_element_factory_make ("capsfilter", "myapp_filter");
        data.fsink = gst_element_factory_make ("filesink", "myapp_sink");

        /* Create the empty pipeline */
        data.pipeline = gst_pipeline_new ("myapp_pipeline");

        if (!data.pipeline || !data.source || !data.encoder || !data.filter
                || !data.fsink)
        {
                g_printerr ("Not all elements could be created.\n");
                return -1;
        }

        /* Configure source, filter and fsink */
        input_enc_caps = gst_caps_new_simple ("video/x-raw",
                     "format", G_TYPE_STRING, FORMAT,
                     "width", G_TYPE_INT, WIDTH,
                     "height", G_TYPE_INT, HEIGHT,
                     "framerate", GST_TYPE_FRACTION, FRAME_RATE, 1, NULL);

        output_enc_caps = gst_caps_new_simple ("video/x-h264",
                        "stream-format", G_TYPE_STRING, "byte-stream", NULL);

        g_object_set (G_OBJECT (data.source), "caps", input_enc_caps,
                                                "stream-type", 0,
                                                "size", size,
                                                "num-buffers", num_buffers_to_send,
                                                NULL);
        g_signal_connect (data.source, "need-data", G_CALLBACK (cb_need_data),
&data);

        g_object_set (G_OBJECT (data.filter), "caps", output_enc_caps, NULL);
        g_object_set (G_OBJECT (data.fsink), "location", Output_FILE, NULL);

        gst_caps_unref (input_enc_caps);
        gst_caps_unref (output_enc_caps);


        /* Link all elements that can be automatically linked*/
        gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.encoder,
        data.filter, data.fsink, NULL);

        if ((gst_element_link_many (data.source, data.encoder, data.filter,
        data.fsink, NULL)) != TRUE )
        {
                g_printerr ("Elements could not be linked.\n");
                gst_object_unref (data.pipeline);
                return -1;
        }

        /* Start playing the pipeline */
        state_ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
        if (state_ret == GST_STATE_CHANGE_FAILURE) {
                g_printerr ("Unable to set the pipeline to the playing state.\n");
                gst_object_unref (data.pipeline);
                return -1;
        }

        /* Set the MainLoop to run */
        g_main_loop_run (data.loop);

        //gst_app_src_end_of_stream((GstAppSrc*) data.source);

        /* Clean up */
        fclose (yuv_file);
        gst_element_set_state (data.pipeline, GST_STATE_NULL);
        gst_object_unref (GST_OBJECT (data.pipeline));
        g_main_loop_unref (data.loop);
        printf("\n End of Stream \n");
        return 0;
}

Can someone help me please to know the issues.

Thanks in advance.



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

AW: Using appsrc in pull mode

Thornton, Keith
Hi, when you have read the last part of your file, you have to push an eos to the pipeline. (gst_app_src_end_of_stream(appsrc);
You also need a bus handler to let you know when the filesink has received the eos. Only then can you shutdown your pipeline.
Why aren't you just using filesrc :-)

-----Urspr√ľngliche Nachricht-----
Von: gstreamer-devel [mailto:[hidden email]] Im Auftrag von Nostalgia
Gesendet: Montag, 26. Februar 2018 13:58
An: [hidden email]
Betreff: Using appsrc in pull mode

Hi ,

I am writing a code that read an yuv file, encode it and save the results of encoding in a new file using this pipeline :
appsrc -> encoder -> capsfilter -> filesink

So I use appsrc to push data from the file to the pipeline, knowing the size of the file I then use appsrc in pull mode. My code runs correctly and I obtain the right output but the problem that it doesn't return to the main function when finishing reading the file :

//g++ -Wall -std=c++11  PullMode.cpp -o pm $(pkg-config --cflags --libs
gstreamer-app-1.0) -ldl

#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <cstring>
#include <iostream>
#include <unistd.h>

using namespace std;

#define WIDTH 640
#define HEIGHT 360
#define FORMAT "I420"
#define FRAME_RATE 25
#define FRAME_TIME 40000000
#define FRAME_SIZE ((WIDTH*HEIGHT*3) >> 1 ) #define FRAME_NUMBER(x) (int)(x/FRAME_SIZE) #define Input_FILE "/media/ubuntu/6634-3132/Hanine/InitialFiles/Basketball.yuv"
#define Output_FILE
"/media/ubuntu/6634-3132/Hanine/Basketball_appsource_pull.264"

static GstClockTime timestamp = 0;
static FILE *yuv_file;
static int num_buffers_to_send;
static int nbuffers = 0;

typedef struct _CustomData {

  GstElement *pipeline, *source, *encoder, *filter, *fsink;
  GMainLoop *loop;
   
} CustomData;

static void cb_need_data (GstElement *appsrc,
   CustomData * data) {

        char* ptr;
        GstBuffer *buffer;
        GstFlowReturn ret;

        ptr = (char*)malloc (FRAME_SIZE);
        g_assert(ptr != NULL);

        fread(ptr, 1 , FRAME_SIZE, yuv_file);

        buffer = gst_buffer_new_wrapped (ptr, FRAME_SIZE);
        buffer->pts = timestamp;
        buffer->dts = timestamp;
        buffer->duration = FRAME_TIME;

        g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);

        gst_buffer_unref(buffer);

        timestamp += FRAME_TIME;
        nbuffers +=1;

        if (ret != GST_FLOW_OK) {
                g_main_loop_quit (data->loop);
                printf(" Error in pushing data to appsrc\n");
        }
}

int main (int argc, char *argv[]) {

        CustomData data;
        GstCaps *input_enc_caps, *output_enc_caps;
        GstStateChangeReturn state_ret;

        /* Get a pointer to the YUV input file*/
        yuv_file = fopen(Input_FILE, "rb");
        g_assert(yuv_file != NULL);

        /* Get the size of the input file*/
        fseek (yuv_file , 0 , SEEK_END);
        long int size = ftell (yuv_file);
        rewind (yuv_file);
        num_buffers_to_send = FRAME_NUMBER(size);
       

        /* Initialize cumstom data structure */
        memset (&data, 0, sizeof (data));

        /* Initialize GStreamer and create the mainloop */
        gst_init (&argc, &argv);
        data.loop = g_main_loop_new (NULL, FALSE);

        /* Create the elements */
        data.source = gst_element_factory_make ("appsrc", "myapp_source");
        data.encoder = gst_element_factory_make ("omxh264enc", "myapp_encoder");
        data.filter = gst_element_factory_make ("capsfilter", "myapp_filter");
        data.fsink = gst_element_factory_make ("filesink", "myapp_sink");

        /* Create the empty pipeline */
        data.pipeline = gst_pipeline_new ("myapp_pipeline");

        if (!data.pipeline || !data.source || !data.encoder || !data.filter
                || !data.fsink)
        {
                g_printerr ("Not all elements could be created.\n");
                return -1;
        }

        /* Configure source, filter and fsink */
        input_enc_caps = gst_caps_new_simple ("video/x-raw",
                     "format", G_TYPE_STRING, FORMAT,
                     "width", G_TYPE_INT, WIDTH,
                     "height", G_TYPE_INT, HEIGHT,
                     "framerate", GST_TYPE_FRACTION, FRAME_RATE, 1, NULL);

        output_enc_caps = gst_caps_new_simple ("video/x-h264",
                        "stream-format", G_TYPE_STRING, "byte-stream", NULL);

        g_object_set (G_OBJECT (data.source), "caps", input_enc_caps,
                                                "stream-type", 0,
                                                "size", size,
                                                "num-buffers", num_buffers_to_send,
                                                NULL);
        g_signal_connect (data.source, "need-data", G_CALLBACK (cb_need_data), &data);

        g_object_set (G_OBJECT (data.filter), "caps", output_enc_caps, NULL);
        g_object_set (G_OBJECT (data.fsink), "location", Output_FILE, NULL);

        gst_caps_unref (input_enc_caps);
        gst_caps_unref (output_enc_caps);


        /* Link all elements that can be automatically linked*/
        gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.encoder,
        data.filter, data.fsink, NULL);

        if ((gst_element_link_many (data.source, data.encoder, data.filter,
        data.fsink, NULL)) != TRUE )
        {
                g_printerr ("Elements could not be linked.\n");
                gst_object_unref (data.pipeline);
                return -1;
        }

        /* Start playing the pipeline */
        state_ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
        if (state_ret == GST_STATE_CHANGE_FAILURE) {
                g_printerr ("Unable to set the pipeline to the playing state.\n");
                gst_object_unref (data.pipeline);
                return -1;
        }

        /* Set the MainLoop to run */
        g_main_loop_run (data.loop);

        //gst_app_src_end_of_stream((GstAppSrc*) data.source);

        /* Clean up */
        fclose (yuv_file);
        gst_element_set_state (data.pipeline, GST_STATE_NULL);
        gst_object_unref (GST_OBJECT (data.pipeline));
        g_main_loop_unref (data.loop);
        printf("\n End of Stream \n");
        return 0;
}

Can someone help me please to know the issues.

Thanks in advance.



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: AW: Using appsrc in pull mode

Nostalgia
Hi Keith,

Thanks for your help. I made these changes and my code runs correctly. I
want to use appsrc later in push-mode for live-streaming, but at the
beginning and as new in gstreamer I try to use it with file as input so why
I use it in pull mode.

But finally, we can say that using appsrc in pull mode is equivalent to
using filesrc ? because in the documentation, they said that pull-mode can
be used for file access or other randomly accessable sources.

Regards,



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel