appsrc - appsink -> only one buffer received

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

appsrc - appsink -> only one buffer received

gst_starter
This post was updated on .
Hello,

I am new to gstreamer and tried to create a simple pipeline example that
contains an appsrc and an appsink element. I am trying to continuously send
a custom format buffer (simple 1Byte uint8 buffer) from appsrc to appsink.
To achieve this I continuously push buffers into appsrc and wait for the
"new_sample" callback to inform me about the arrival of new buffers at the
sink side. The example code I posted below works as expected for the first
buffer. The problem is that "new_sample" is only called once, even if I
continuously push data into appsrc, which then results into a growing buffer
on the source side.
How can I fix appsink such that new_sample is called for every buffer pushed
into appsrc?

My code:
#include <gst/gst.h>
#include <string.h>
#include <gst_dependencies_aux.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>

#define CHUNK_SIZE 1   /* Amount of bytes we are sending in each buffer */

/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
	GstElement *pipeline, *app_source, *app_sink;
	guint sourceid;        /* To control the GSource */
	GMainLoop *main_loop;  /* GLib's Main Loop */
} CustomData;

/* This method is called by the idle GSource in the mainloop, to feed CHUNK_SIZE bytes into appsrc.
* The ide handler is added to the mainloop when appsrc requests us to start sending data (need-data signal)
* and is removed when appsrc has enough data (enough-data signal).
*/
static gboolean push_data(CustomData *data) {
	GstBuffer *buffer;
	GstFlowReturn ret;
	int i;
	GstMapInfo map;
	gint8 *raw;

	/* Create a new empty buffer */
	buffer = gst_buffer_new_and_alloc(CHUNK_SIZE);

	/* Generate simple uint8 buffer */
	gst_buffer_map(buffer, &map, GST_MAP_WRITE);
	raw = (gint8 *)map.data;
	for (i = 0; i < CHUNK_SIZE; i++) {
		raw[i] = (gint8)(65);  //Push simple uint8
	}
	gst_buffer_unmap(buffer, &map);

	/* Push the buffer into the appsrc */
	g_signal_emit_by_name(data->app_source, "push-buffer", buffer, &ret);

	/* Free the buffer now that we are done with it */
	gst_buffer_unref(buffer);


	if (ret != GST_FLOW_OK) {
		/* We got some error, stop sending data */
		return FALSE;
	}

	return TRUE;
}

/* This signal callback triggers when appsrc needs data. Here, we add an idle handler
* to the mainloop to start pushing data into the appsrc */
static void start_feed(GstElement *source, guint size, CustomData *data) {
	if (data->sourceid == 0) {
		g_print("Start feeding\n");
		data->sourceid = g_idle_add((GSourceFunc)push_data, data);
	}
}

/* This callback triggers when appsrc has enough data and we can stop sending.
* We remove the idle handler from the mainloop */
static void stop_feed(GstElement *source, CustomData *data) {
	if (data->sourceid != 0) {
		g_print("Stop feeding\n");
		g_source_remove(data->sourceid);
		data->sourceid = 0;
	}
}

/* The appsink has received a buffer */
static void new_sample(GstElement *sink, CustomData *data) {
	GstSample *sample;

	/* Retrieve the buffer */
	g_signal_emit_by_name(sink, "pull-sample", &sample);

	if (sample) {

		GstBuffer* buffer = gst_sample_get_buffer(sample);
		GstMapInfo info;
		gboolean mapping_succ = gst_buffer_map(buffer, &info, GST_MAP_READ);

		// Confirm that correct buffer was received...
		g_print("Appsink: Buffer Received: Content = %u!\n", *info.data);

		g_print("received something...\n");
		gst_buffer_unmap(buffer, &info);
		gst_buffer_unref((GstBuffer*)sample);
	}
}

/* This function is called when an error message is posted on the bus */
static void error_cb(GstBus *bus, GstMessage *msg, CustomData *data) {
	GError *err;
	gchar *debug_info;

	/* Print error details on the screen */
	gst_message_parse_error(msg, &err, &debug_info);
	g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
	g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
	g_clear_error(&err);
	g_free(debug_info);

	g_main_loop_quit(data->main_loop);
}

/* This function is called when an error message is posted on the bus */
static void eos_cb(GstBus *bus, GstMessage *msg, CustomData *data) {
	g_print("End-Of-Stream reached.\n");
}

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

	std::ostringstream gstPluginsPath("C:/svn/Microscope_Plattform_Sandbox/gst_video_playback/x64/Debug/gstreamer-1.0");
	_putenv_s("GST_DEBUG_DUMP_DOT_DIR", "C:\\Temp\\");
	_putenv_s("GST_PLUGIN_PATH_1_0", gstPluginsPath.str().c_str());

	CustomData data;
	GstBus *bus;

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

	/* Initialize GStreamer */
	gst_init(&argc, &argv);

	/* Create the elements */
	data.app_source = gst_element_factory_make("appsrc", "app_source");
	data.app_sink = gst_element_factory_make("appsink", "app_sink");

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

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

	/* Create custom properties*/
	g_object_set(G_OBJECT(data.app_source), "caps",
		gst_caps_new_simple("custom",
			"format", G_TYPE_STRING, "U8",
			"width", G_TYPE_INT, 1,
			"height", G_TYPE_INT, 1,
			"framerate", GST_TYPE_FRACTION, 0, 1,
			NULL), NULL);

	g_object_set(G_OBJECT(data.app_sink), "caps",
		gst_caps_new_simple("custom",
			"format", G_TYPE_STRING, "U8",
			"width", G_TYPE_INT, 1,
			"height", G_TYPE_INT, 1,
			"framerate", GST_TYPE_FRACTION, 0, 1,
			NULL), NULL);

	/* Configure appsrc */
	//g_object_set(data.app_source, "format", GST_FORMAT_TIME, NULL);
	g_signal_connect(data.app_source, "need-data", G_CALLBACK(start_feed), &data);
	//g_signal_connect(data.app_source, "enough-data", G_CALLBACK(stop_feed), &data);


	/* Configure appsink */
	g_object_set(data.app_sink, "emit-signals", TRUE, NULL);
	//g_object_set(data.app_sink, "sync", TRUE, NULL);

	g_signal_connect(data.app_sink, "new-sample", G_CALLBACK(new_sample), &data);

	/* Link all elements that can be automatically linked because they have "Always" pads */
	gst_bin_add_many(GST_BIN(data.pipeline), data.app_source, data.app_sink, NULL);
	if (gst_element_link_many(data.app_source, data.app_sink, NULL) != TRUE) {
		g_printerr("Elements could not be linked.\n");
		gst_object_unref(data.pipeline);
		return -1;
	}

	/* Instruct the bus to emit signals for each received message, and connect to the interesting signals */
	/* gst_element_get_bus is the same as gst_pipeline_get_but -> In this example pipeline is element, therfore the former...*/
	bus = gst_element_get_bus(data.pipeline);
	gst_bus_add_signal_watch(bus);
	g_signal_connect(G_OBJECT(bus), "message::error", (GCallback)error_cb, &data);
	g_signal_connect(G_OBJECT(bus), "message::eos", (GCallback)eos_cb, &data);

	gst_object_unref(bus);

	/* Start playing the pipeline */
	gst_element_set_state(data.pipeline, GST_STATE_PLAYING);

	if (!(data.app_source->current_state == GST_STATE_PLAYING));
	{
		g_print("Wait for transition to playing state!\n");
	}

	GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS((GstBin*)data.pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "show_pipeline");

	/* Create a GLib Main Loop and set it to run */
	data.main_loop = g_main_loop_new(NULL, FALSE);

	g_main_loop_run(data.main_loop);


	/* Free resources */
	gst_element_set_state(data.pipeline, GST_STATE_NULL);
	gst_object_unref(data.pipeline);
	return 0;
}
Thanks!




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

Re: appsrc - appsink -> only one buffer received

gst_starter
The code not accepted in my original post. You find the complete example
under:

http://gstreamer-devel.966125.n4.nabble.com/appsrc-appsink-gt-only-one-buffer-received-td4685731.html



--
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
|

Re: appsrc - appsink -> only one buffer received

Tim Müller
On Fri, 2017-12-22 at 06:55 -0700, gst_starter wrote:

> The code not accepted in my original post. You find the complete
> example under:
>
> http://gstreamer-devel.966125.n4.nabble.com/appsrc-appsink-gt-only-on
> e-buffer-received-td4685731.html

You're supposed to return a GstFlowReturn from the new-sample callback
function, see gst-inspect-1.0 appsink.

Try returning GST_FLOW_OK.

Cheers
-Tim

--
Tim Müller, Centricular Ltd - http://www.centricular.com
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: appsrc - appsink -> only one buffer received

Denis Shienkov
In reply to this post by gst_starter
Hi,

most likelly, you need to add the nanosecond-timestamps to each of pushed buffer.

BR,
Denis

2017-12-22 16:55 GMT+03:00 gst_starter <[hidden email]>:
The code not accepted in my original post. You find the complete example
under:

http://gstreamer-devel.966125.n4.nabble.com/appsrc-appsink-gt-only-one-buffer-received-td4685731.html



--
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: appsrc - appsink -> only one buffer received

gst_starter
In reply to this post by Tim Müller
Thank you Tim! The return value fixed the problem...



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