+// stringify the un-quoted string to quoted C string
+#define xstr(a) str(a)
+#define str(a) #a
+
+GstElement* create_pipeline(int* argc, char** argv[])
+{
+ GError *error = NULL;
+ const char *camera_device = NULL;
+ const char *width_str = NULL;
+ const char *height_str = NULL;
+ int width;
+ int height;
+
+ // pipewire is default.
+ char *v4l2_path = getenv("ENABLE_V4L2_PATH");
+ bool v4l2 = false;
+
+ char pipeline_str[1024];
+
+ camera_device = getenv("DEFAULT_V4L2_DEVICE");
+ if (!camera_device)
+ camera_device = get_first_camera_device();
+
+ width_str = getenv("DEFAULT_DEVICE_WIDTH");
+ if (!width_str)
+ width = WINDOW_WIDTH_SIZE;
+ else
+ width = atoi(width_str);
+
+ height_str = getenv("DEFAULT_DEVICE_HEIGHT");
+ if (!height_str)
+ height = WINDOW_HEIGHT_SIZE;
+ else
+ height = atoi(height_str);
+
+ if (v4l2_path == NULL)
+ v4l2 = false;
+ else if (g_str_equal(v4l2_path, "yes") || g_str_equal(v4l2_path, "true"))
+ v4l2 = true;
+
+ memset(pipeline_str, 0, sizeof(pipeline_str));
+
+ if (v4l2)
+ snprintf(pipeline_str, sizeof(pipeline_str), "v4l2src device=%s ! video/x-raw,width=%d,height=%d ! waylandsink",
+ camera_device, width, height);
+ else if (gst_pipeline_failed == TRUE) {
+ snprintf(pipeline_str, sizeof(pipeline_str), "filesrc location=%s/still-image.jpg ! decodebin ! videoconvert ! imagefreeze ! waylandsink",
+ xstr(APP_DATA_PATH));
+ fallback_gst_pipeline_tried = TRUE;
+ }
+ else {
+ snprintf(pipeline_str, sizeof(pipeline_str), "pipewiresrc ! waylandsink");
+ }
+
+ fprintf(stdout, "Using pipeline: %s\n", pipeline_str);
+
+ GstElement *pipeline = gst_parse_launch(pipeline_str, &error);
+
+ if (error || !pipeline) {
+ fprintf(stderr, "gstreamer pipeline construction failed!\n");
+ free(argv);
+ return NULL;
+ }
+
+ return pipeline;
+}
+
+int main(int argc, char* argv[])