/* GStreamer * Copyright (C) 2024 Seungha Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #define CUSTOM_META_NAME "GstCudaIpcTestMeta" static GstPadProbeReturn server_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstBuffer *buf; GstCustomMeta *meta; GstStructure *s; gchar *str; buf = GST_PAD_PROBE_INFO_BUFFER (info); meta = gst_buffer_add_custom_meta (buf, CUSTOM_META_NAME); s = gst_custom_meta_get_structure (meta); gst_structure_set (s, "foo", G_TYPE_STRING, "bar", "timestamp", G_TYPE_UINT64, GST_BUFFER_PTS (buf), NULL); str = gst_structure_serialize_full (s, GST_SERIALIZE_FLAG_NONE); gst_println ("Added custom meta %s", str); return GST_PAD_PROBE_OK; } static GstElement * server_process (const gchar * address) { GError *error = NULL; GstPad *sinkpad; GstElement *sink; GstElement *pipeline = gst_parse_launch ("videotestsrc ! video/x-raw,format=RGBA,framerate=1/1 ! " "queue ! cudaupload ! cudaipcsink name=sink", &error); if (!pipeline) { gst_printerrln ("couldn't create pipeline, err: %s", error->message); g_clear_error (&error); return NULL; } sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); g_assert (sink); if (address) g_object_set (sink, "address", address, NULL); sinkpad = gst_element_get_static_pad (sink, "sink"); gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) server_probe_cb, NULL, NULL); gst_object_unref (sinkpad); return pipeline; } static GstPadProbeReturn client_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstBuffer *buf; GstCustomMeta *meta; buf = GST_PAD_PROBE_INFO_BUFFER (info); meta = gst_buffer_get_custom_meta (buf, CUSTOM_META_NAME); if (!meta) { gst_printerrln ("Buffer without meta"); } else { GstStructure *s; gchar *str; s = gst_custom_meta_get_structure (meta); str = gst_structure_serialize_full (s, GST_SERIALIZE_FLAG_NONE); gst_println ("Found custom meta \"%s\"", str); g_free (str); } return GST_PAD_PROBE_OK; } static GstElement * client_process (const gchar * address) { GError *error = NULL; GstPad *srcpad; GstElement *src; GstElement *pipeline = gst_parse_launch ("cudaipcsrc name=src ! fakesink", &error); if (!pipeline) { gst_printerrln ("couldn't create pipeline, err: %s", error->message); g_clear_error (&error); return NULL; } src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); g_assert (src); if (address) g_object_set (src, "address", address, NULL); srcpad = gst_element_get_static_pad (src, "src"); gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback) client_probe_cb, NULL, NULL); gst_object_unref (srcpad); return pipeline; } gint main (gint argc, gchar ** argv) { GstElement *pipeline = NULL; GstStateChangeReturn sret; GError *error = NULL; GOptionContext *option_ctx; gboolean is_server = FALSE; gchar *address = NULL; gboolean ret; static const gchar *tags[] = { NULL }; GOptionEntry options[] = { {"server", 0, 0, G_OPTION_ARG_NONE, &is_server, "Launch server process", NULL}, {"address", 0, 0, G_OPTION_ARG_STRING, &address, "IPC communication address"}, {NULL} }; GMainLoop *loop; option_ctx = g_option_context_new ("CUDA IPC example"); g_option_context_add_main_entries (option_ctx, options, NULL); g_option_context_add_group (option_ctx, gst_init_get_option_group ()); ret = g_option_context_parse (option_ctx, &argc, &argv, &error); g_option_context_free (option_ctx); if (!ret) { g_printerr ("option parsing failed: %s\n", error->message); g_clear_error (&error); return 1; } loop = g_main_loop_new (NULL, FALSE); gst_meta_register_custom ("GstCudaIpcTestMeta", tags, NULL, NULL, NULL); if (is_server) pipeline = server_process (address); else pipeline = client_process (address); if (!pipeline) return 1; sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (sret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Pipeline doesn't want to playing\n"); } else { g_main_loop_run (loop); } gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); g_main_loop_unref (loop); g_free (address); return 0; }