Windows application not identifying objects correctly?

Nicolas Dufresne nicolas at ndufresne.ca
Sat Mar 30 14:09:26 UTC 2019


Le vendredi 29 mars 2019 à 14:51 -0700, Bernd Weber a écrit :
> Hey guys,
> 
> I'm having trouble figuring this out. I have an application that is in its simplest form creating a GStreamer pipeline with a UDP source, H264 decoder and video output. I'll post the code below.
> 1. I know I can run on the same machine the pipeline via gst-launch on the command-line and it works exactly as expected showing me the video stream:
>   gst-launch-1.0 udpsrc port=5000 ! application/x-rtp,encoding-name=H264, payload=96 ! rtph264depay ! h264parse ! queue ! avdec_h264 ! autovideosink sync=false
> 2. I can build the same code on Linux and it also works just as expected showing me the video stream.
> 
> Both of the above tell me:
> 1. Windows can handle the pipeline correctly and in general all is installed correctly.
> 2. The program code is also correct because I can see the stream correctly on Linux.
> 
> So when I run the application built with the below code on Windows I get the following error messages on the command line:
> (GStreamerWindowsHostSample.exe:133520): GLib-CRITICAL **: g_datalist_id_set_data_full: assertion 'key_id > 0' failed
> (GStreamerWindowsHostSample.exe:133520): GLib-GObject-CRITICAL **: g_param_spec_pool_lookup: assertion 'pool != NULL' failed
> (GStreamerWindowsHostSample.exe:133520): GLib-GObject-WARNING **: g_object_set_valist: object class '(NULL)' has no property named 'port'
> 
> (GStreamerWindowsHostSample.exe:133520): GLib-CRITICAL **: g_datalist_id_set_data_full: assertion 'key_id > 0' failed
> (GStreamerWindowsHostSample.exe:133520): GLib-GObject-CRITICAL **: g_param_spec_pool_lookup: assertion 'pool != NULL' failed
> (GStreamerWindowsHostSample.exe:133520): GLib-GObject-WARNING **: g_object_set_valist: object class '(NULL)' has no property named 'sync'

With environment G_DEBUG=fatal_criticals or G_DEBUG=fatal_warnings, you
can make GLib abort on these assertion. Using this and a debugger, you
can quickly find the location of the defect.

> 
> I don't see these errors in the other two examples. The above errors imply to me that gstreamer of glib is having trouble identifying the correct object type somehow. But why does it not have the problem when I run the gst-launch pipeline?
> 
> In the Visual Studio debugger I can see in the output window that it loads all the right dlls, like libgstudp.dll and libgstcoreelements.dll which contain the elements above. Btw I'm using VS2017, a CMake project and am running this on Windows 10 1709 with gstreamer version 1.14.1. No build errors whatsoever.
> 
> I'm at a loss as to what I'm missing. So any suggestion and help is appreciated! I'm sure it's something ridiculously simple...
> 
> -Bernd --
> 
> -------------------------------
> 
> GStreamerWindowsHostSample.cpp code:
> 
> #include "GStreamerWindowsHostSample.h"
> 
> using namespace std;
> 
> /* Structure holding GStreamer elements neccessary to control program/pipeline execution */
> typedef struct _ControlData {
> 	GstElement *pipeline;
> 	GMainLoop  *loop;
> } ControlData;
> 
> /* Bus message handler */
> static gboolean
> bus_call(GstBus     *bus,
> 	GstMessage *msg,
> 	gpointer    data)
> {
> 	GMainLoop *loop = (GMainLoop *)data;
> 
> 	switch (GST_MESSAGE_TYPE(msg)) {
> 
> 	case GST_MESSAGE_EOS:
> 		g_print("End of stream\n");
> 		g_main_loop_quit(loop);
> 		break;
> 
> 	case GST_MESSAGE_ERROR: {
> 		gchar  *debug;
> 		GError *error;
> 
> 		gst_message_parse_error(msg, &error, &debug);
> 		g_free(debug);
> 
> 		g_printerr("Error: %s\n", error->message);
> 		g_error_free(error);
> 
> 		g_main_loop_quit(loop);
> 		break;
> 	}
> 	default:
> 		break;
> 	}
> 
> 	return TRUE;
> }
> 
> /* Process keyboard input */
> static gboolean
> handle_keyboard(GIOChannel *source,
> 	GIOCondition cond,
> 	ControlData *data)
> {
> 	gchar *str = NULL;
> 
> 	if (g_io_channel_read_line(source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) {
> 		return TRUE;
> 	}
> 
> 	switch (g_ascii_tolower(str[0])) {
> 	case 'q':
> 		g_main_loop_quit(data->loop);
> 		break;
> 	default:
> 		break;
> 	}
> 
> 	g_free(str);
> 
> 	return TRUE;
> }
> 
> /* Main loop */
> int
> main(int   argc,
> 	char *argv[])
> {
> 	ControlData data;
> 	GIOChannel *io_stdin;
> 
> 	GstElement *source, *depayload, *parser, *decoder, *sink;
> 	GstElement *queue;
> 	GstCaps *source_caps;
> 	GstBus *bus;
> 	guint bus_watch_id;
> 
> 	/* Initialisation */
> 	gst_init(&argc, &argv);
> 
> 	/* Initialize our control structure */
> 	memset(&data, 0, sizeof(data));
> 
> 	data.loop = g_main_loop_new(NULL, FALSE);
> 
> 	/* Check input arguments */
> 	if (argc != 1) {
> 		g_printerr("USAGE: %s \n", argv[0]);
> 		return -1;
> 	}
> 
> 	/* Print usage map */
> 	g_print(
> 		"USAGE: \n"
> 		"Choose one of the following options, then press enter:\n"
> 		" 'Q' to quit\n");
> 
> 	/* Create gstreamer elements */
> 	data.pipeline = gst_pipeline_new("stream-player");
> 	source = gst_element_factory_make("udpsrc", "streaming-source");
> 	depayload = gst_element_factory_make("rtph264depay", "depay");
> 	parser = gst_element_factory_make("h264parse", "h264-parser");
> 	decoder = gst_element_factory_make("avdec_h264", "decoder");
> 	sink = gst_element_factory_make("autovideosink", "video-output");
> 
> 	queue = gst_element_factory_make("queue", "queue");
> 
> 	if (!data.pipeline || !source || !depayload || !parser || !queue || !decoder || !sink) {
> 		g_printerr("One element could not be created. Exiting.\n");
> 		return -1;
> 	}
> 
> 	/* Set up the pipeline */
> 
> 	/* Define the output window dimensions and position */
> 	/* This is where the first critical error occurs: */
> 	g_object_set(G_OBJECT(source),
> 		"port", 5000,
> 		NULL);
> 
> 	/* we set the source caps filter options */
> 	source_caps = gst_caps_new_simple("application/x-rtp",
> 		"encoding-name", G_TYPE_STRING, "H264",
> 		"payload", G_TYPE_INT, 96,
> 		NULL);
> 
> 	/* Define the output window dimensions and position */
> 	/* This is where the other critical error occurs: */
> 	g_object_set(G_OBJECT(sink),
> 		"sync", FALSE,
> 		NULL);
> 
> 	/* we add a message handler */
> 	bus = gst_pipeline_get_bus(GST_PIPELINE(data.pipeline));
> 	bus_watch_id = gst_bus_add_watch(bus, bus_call, data.loop);
> 	gst_object_unref(bus);
> 
> 	/* we add all elements into the pipeline */
> 	/* camera-source | depay | parse | queue | decode | sink  */
> 	gst_bin_add_many(GST_BIN(data.pipeline),
> 		source, depayload, parser, queue, decoder, sink, NULL);
> 
> 	/* we link the elements together using the caps filters we defined above */
> 	if ((gst_element_link_filtered(source, depayload, source_caps) != (gboolean)true) ||
> 		(gst_element_link_many(depayload, parser, queue, decoder, sink, NULL) != (gboolean)true))
> 	{
> 		g_printerr("Elements could not be linked\n");
> 		gst_object_unref(data.pipeline);
> 		return -1;
> 	}
> 
> 	/* Some cleanup */
> 	gst_caps_unref(source_caps);
> 
> 	/* Let's capture keyboard input to be able to react to user commands */
> 	io_stdin = g_io_channel_unix_new(_fileno(stdin));
> 	g_io_add_watch(io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);
> 
> 	/* Set the pipeline to "playing" state*/
> 	g_print("Now playing...\n");
> 	gst_element_set_state(data.pipeline, GST_STATE_PLAYING);
> 
> 	/* Iterate */
> 	g_print("Running...\n");
> 	g_main_loop_run(data.loop);
> 
> 	/* Out of the main loop, clean up nicely */
> 	g_print("Returned, stopping playback\n");
> 	gst_element_set_state(data.pipeline, GST_STATE_NULL);
> 
> 	g_print("Deleting pipeline\n");
> 	gst_object_unref(GST_OBJECT(data.pipeline));
> 	g_source_remove(bus_watch_id);
> 	g_main_loop_unref(data.loop);
> 	g_io_channel_unref(io_stdin);
> 
> 	return 0;
> }
> 
> GStreamerWindowsHostSample.h code:
> 
> #pragma once
> 
> #include <stdio.h>
> 
> #include <string.h>
> #include <glib.h>
> #include <gst/gst.h>
> 
> CMakeLists.txt:
> 
> cmake_minimum_required (VERSION 3.8)
> 
> # Add source to this project's executable.
> add_executable (GStreamerWindowsHostSample "GStreamerWindowsHostSample.cpp" "GStreamerWindowsHostSample.h")
> 
> set(GSTREAMER_BASE_PATH "C:/gstreamer/1.0/x86_64")
> set(GSTREAMER_LIB_BASE_PATH "${GSTREAMER_BASE_PATH}/lib")
> set(GSTREAMER_LIB_GST_PATH "${GSTREAMER_LIB_BASE_PATH}/gstreamer-1.0")
> 
> include_directories("${GSTREAMER_BASE_PATH}/include/gstreamer-1.0")
> include_directories("${GSTREAMER_BASE_PATH}/include/glib-2.0")
> include_directories("${GSTREAMER_LIB_BASE_PATH}/glib-2.0/include")
> 
> link_directories(${GSTREAMER_LIB_BASE_PATH})
> link_directories(${GSTREAMER_LIB_GST_PATH})
> 
> find_library(GLIB_LIBRARY glib-2.0 ${GSTREAMER_LIB_BASE_PATH})
> find_library(GOBJECT_LIBRARY gobject-2.0 ${GSTREAMER_LIB_BASE_PATH})
> find_library(GMODULE_LIBRARY gmodule-2.0 ${GSTREAMER_LIB_BASE_PATH})
> find_library(GTHREAD_LIBRARY gthread-2.0 ${GSTREAMER_LIB_BASE_PATH})
> find_library(GSTREAMER_LIBRARY gstreamer-1.0 ${GSTREAMER_LIB_BASE_PATH})
> find_library(GSTUDP_LIBRARY gstudp ${GSTREAMER_LIB_GST_PATH})
> 
> target_link_libraries(GStreamerWindowsHostSample ${GLIB_LIBRARY} ${GOBJECT_LIBRARY} ${GMODULE_LIBRARY} ${GTHREAD_LIBRARY} ${GSTREAMER_LIBRARY})
> 
> 
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel



More information about the gstreamer-devel mailing list