Issue in a pipeline with appsrc and filesink

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Issue in a pipeline with appsrc and filesink

Manoj Nirala
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;
}


_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel