Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <gst/gst.h>
- #include <gst/app/gstappsrc.h>
- #include <gst/app/gstappsink.h>
- typedef struct
- {
- GMainLoop *loop;
- GstElement *source;
- GstElement *sink;
- } ProgramData;
- /* called when we get a GstMessage from the source pipeline when we get EOS, we
- * notify the appsrc of it. */
- static gboolean on_source_message(GstBus * bus, GstMessage * message, ProgramData * data)
- {
- GstElement *source;
- GError *err = NULL;
- gchar *dbg_info = NULL;
- switch (GST_MESSAGE_TYPE(message)) {
- case GST_MESSAGE_EOS:
- g_print("The source got dry\n");
- source = gst_bin_get_by_name(GST_BIN(data->sink), "testsource");
- gst_app_src_end_of_stream(GST_APP_SRC(source));
- gst_object_unref(source);
- break;
- case GST_MESSAGE_ERROR:
- gst_message_parse_error(message, &err, &dbg_info);
- g_printerr("Received error on source: %s\n", err->message);
- g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
- g_main_loop_quit(data->loop);
- break;
- default:
- break;
- }
- return TRUE;
- }
- /* called when the appsink notifies us that there is a new buffer ready for
- * processing */
- static GstFlowReturn on_new_sample_from_sink(GstElement * elt, ProgramData * data)
- {
- GstSample *sample;
- GstBuffer *app_buffer, *buffer;
- GstElement *source;
- GstFlowReturn ret;
- GstMapInfo info_in;
- guint8 *in;
- /* get the sample from appsink */
- sample = gst_app_sink_pull_sample(GST_APP_SINK(elt));
- buffer = gst_sample_get_buffer(sample);
- /* make a copy */
- app_buffer = gst_buffer_copy(buffer);
- /* we don't need the appsink sample anymore */
- gst_sample_unref(sample);
- /* get map and modify it */
- gst_buffer_map(app_buffer, &info_in, GST_MAP_WRITE);
- in = info_in.data;
- for (int i = 0; i < 10; i++) {
- in[i] = 0;
- }
- gst_buffer_unmap(app_buffer, &info_in);
- /* get source an push new buffer */
- source = gst_bin_get_by_name(GST_BIN(data->sink), "testsource");
- ret = gst_app_src_push_buffer(GST_APP_SRC(source), app_buffer);
- gst_object_unref(source);
- return ret;
- }
- /* called when we get a GstMessage from the sink pipeline when we get EOS, we
- * exit the mainloop and this testapp. */
- static gboolean on_sink_message(GstBus * bus, GstMessage * message, ProgramData * data)
- {
- GError *err = NULL;
- gchar *dbg_info = NULL;
- switch (GST_MESSAGE_TYPE(message)) {
- case GST_MESSAGE_EOS:
- g_print("Finished playback\n");
- g_main_loop_quit(data->loop);
- break;
- case GST_MESSAGE_ERROR:
- gst_message_parse_error(message, &err, &dbg_info);
- g_printerr("Received error on sink: %s\n", err->message);
- g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
- g_main_loop_quit(data->loop);
- break;
- default:
- break;
- }
- return TRUE;
- }
- int main()
- {
- gchar *filename = NULL;
- ProgramData *data = NULL;
- gchar *string = NULL;
- GstBus *bus = NULL;
- GstElement *testsink = NULL;
- GstElement *testsource = NULL;
- gst_init(NULL, NULL);
- filename = g_strdup("D:\\\\Visual Studio Files\\\\CudaGStreamer\\\\video.mp4");
- if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
- g_print("File %s does not exist\n", filename);
- return -1;
- }
- data = g_new0(ProgramData, 1);
- data->loop = g_main_loop_new(NULL, FALSE);
- /* setting up source pipeline */
- string = g_strdup_printf("filesrc location=\"%s\" ! decodebin ! appsink name=testsink", filename);
- // string = g_strdup_printf("filesrc location=\"%s\" ! appsink name=testsink", filename);
- g_free(filename);
- data->source = gst_parse_launch(string, NULL);
- g_free(string);
- if (data->source == NULL) {
- g_print("Bad source\n");
- return -1;
- }
- /* to be notified of messages from this pipeline, mostly EOS */
- bus = gst_element_get_bus(data->source);
- gst_bus_add_watch(bus, (GstBusFunc)on_source_message, data);
- gst_object_unref(bus);
- /* we use appsink in push mode, it sends us a signal when data is available
- * and we pull out the data in the signal callback. We want the appsink to
- * push as fast as it can, hence the sync=false */
- testsink = gst_bin_get_by_name(GST_BIN(data->source), "testsink");
- g_object_set(G_OBJECT(testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
- g_signal_connect(testsink, "new-sample", G_CALLBACK(on_new_sample_from_sink), data);
- gst_object_unref(testsink);
- /* setting up sink pipeline. We have no blocking behaviour on the src which means
- * that we will push the entire file into memory. */
- string = g_strdup_printf(
- "appsrc name=testsource ! "
- "filesink location=\"D:\\\\Visual Studio Files\\\\CudaGStreamer\\\\out.mp4\""
- );
- data->sink = gst_parse_launch(string, NULL);
- g_free(string);
- if (data->sink == NULL) {
- g_print("Bad sink\n");
- return -1;
- }
- testsource = gst_bin_get_by_name(GST_BIN(data->sink), "testsource");
- /* configure for time-based format */
- g_object_set(testsource, "format", GST_FORMAT_TIME, NULL);
- /* uncomment the next line to block when appsrc has buffered enough */
- // g_object_set (testsource, "block", TRUE, NULL);
- gst_object_unref(testsource);
- bus = gst_element_get_bus(data->sink);
- gst_bus_add_watch(bus, (GstBusFunc)on_sink_message, data);
- gst_object_unref(bus);
- /* launching things */
- gst_element_set_state(data->sink, GST_STATE_PLAYING);
- gst_element_set_state(data->source, GST_STATE_PLAYING);
- /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
- * error occurs in the source or sink pipelines. */
- g_print("Let's run!\n");
- g_main_loop_run(data->loop);
- g_print("Going out\n");
- gst_element_set_state(data->source, GST_STATE_NULL);
- gst_element_set_state(data->sink, GST_STATE_NULL);
- gst_object_unref(data->source);
- gst_object_unref(data->sink);
- g_main_loop_unref(data->loop);
- g_free(data);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement