Issue in a pipeline with appsrc and filesink

Manoj Nirala nirala.manoj at gmail.com
Tue Aug 14 05:30:58 UTC 2018


Hi All,

I am trying to create a pipeline in C++ with appsrc as a source and
filesink as a sink element. For simplicity I am creating a buffer with
alternating black and white frames and pushing it into appsrc. My goal is
to create an mp4 video as output. The program is creating the file that
grows in size with time of execution. But when I open it to read, it
doesn't open up.
Could someone please point me in the right direction to solve the problem?

Thanks in advance.

Best,
Manoj


Here goes the code:

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

static GMainLoop *loop;
GstElement *pipeline, *appsrc, *filter1, *conv, *filter2, *encoder,
*parser, *muxer, *filesink;
GstCaps *filter1_caps;
GstCaps *filter2_caps;
GstBus *bus;
guint bus_watch_id;

static void cb_need_data(GstElement *appsrc, guint unused_size,
gpointer user_data) {
static gboolean white = FALSE;
static GstClockTime timestamp = 0;
GstBuffer *buffer;
guint size;
GstFlowReturn ret;

size = 640 * 480 * 3;

buffer = gst_buffer_new_allocate(NULL, size, NULL);
/* this makes the image black/white */
gst_buffer_memset(buffer, 0, white ? 0xff : 0x0, size);

white = !white;

GST_BUFFER_PTS (buffer) = timestamp;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 2);
timestamp += GST_BUFFER_DURATION(buffer);

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

if (ret != GST_FLOW_OK) {
/* something wrong, send EOS event and stop pushing */
gst_element_send_event(pipeline, gst_event_new_eos());
g_main_loop_quit(loop);
}
}

static gboolean my_bus_callback(GstBus *bus, GstMessage *message,
gpointer data) {
g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(message));

switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_ERROR: {
GError *err;
gchar *debug;

gst_message_parse_error(message, &err, &debug);
g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src),
err->message);
g_printerr("Debugging info: %s\n", (debug) ? debug : "none");
g_error_free(err);
g_free(debug);

std::cin.get();
g_main_loop_quit(loop);
break;
}
case GST_MESSAGE_EOS:
/* end-of-stream */
std::cin.get();
g_main_loop_quit(loop);
break;
default:
g_print("Debug raw message: %s\n", message);
break;
}

return TRUE;
}

gint main(gint argc, gchar *argv[]) {
/* init GStreamer */
gst_init(&argc, &argv);
gst_debug_set_default_threshold(GST_LEVEL_INFO);
loop = g_main_loop_new(NULL, FALSE);

/* setup pipeline */
pipeline = gst_pipeline_new("pipeline");
appsrc = gst_element_factory_make("appsrc", "source");
filter1  = gst_element_factory_make ("capsfilter", "filter1");
conv = gst_element_factory_make("autovideoconvert", "conv");
encoder = gst_element_factory_make("x264enc", "encoder");
filter2 = gst_element_factory_make ("capsfilter", "filter2");
parser = gst_element_factory_make ("h264parse", "parser");
muxer = gst_element_factory_make("mp4mux", "muxer");
filesink = gst_element_factory_make("filesink", "filesink");

/* setup appsrc */
g_object_set(G_OBJECT(appsrc),
"stream-type", GST_APP_STREAM_TYPE_STREAM,
"format", GST_FORMAT_TIME,
NULL);
g_signal_connect(appsrc, "need-data", G_CALLBACK (cb_need_data), NULL);

/* setup */
g_object_set(G_OBJECT(appsrc), "caps",
gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, "RGB",
"width", G_TYPE_INT, 640,
"height", G_TYPE_INT, 480,
"framerate", GST_TYPE_FRACTION, 0, 1,
NULL), NULL);
filter1_caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "RGB",
"width", G_TYPE_INT, 640,
"height", G_TYPE_INT, 480,
NULL);

filter2_caps = gst_caps_new_simple ("video/x-h264",
"stream-format", G_TYPE_STRING, "byte-stream",
NULL);
g_object_set (G_OBJECT (filter1), "caps", filter1_caps, NULL);
g_object_set (G_OBJECT (filter2), "caps", filter2_caps, NULL);
gst_caps_unref (filter1_caps);
gst_caps_unref (filter2_caps);

g_object_set(G_OBJECT(filesink), "location",
"C:\\CppWorkspace\\GstreamerApps\\testout.mp4", NULL);

gst_bin_add_many(GST_BIN(pipeline), appsrc, filter1, conv, encoder,
filter2, parser, muxer, filesink, NULL);
gst_element_link_many(appsrc, filter1, conv, encoder, filter2, parser,
muxer, filesink, NULL);

/* adds a watch for new message on our pipeline's message bus to
* the default GLib main context, which is the main context that our
* GLib main loop is attached to below
*/
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
bus_watch_id = gst_bus_add_watch(bus, my_bus_callback, NULL);
std::cout << bus_watch_id;

/* play */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(loop);

/* clean up */
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
gst_object_unref(bus);
g_main_loop_unref(loop);

return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20180814/2c77fecf/attachment-0001.html>


More information about the gstreamer-devel mailing list