From 35da4a51ea688941211326a6b7063d9997055e18 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 1 Feb 2021 19:04:39 +0000 Subject: [PATCH] d/vf: Refactor code to add videotestsrc capability and break out gstreamer detection --- CMakeLists.txt | 5 +- src/xrt/drivers/CMakeLists.txt | 2 +- src/xrt/drivers/vf/vf_driver.c | 139 ++++++++++++------ src/xrt/drivers/vf/vf_interface.h | 17 ++- src/xrt/include/xrt/meson.build | 4 - .../include/xrt/xrt_config_have.h.cmake_in | 2 +- src/xrt/state_trackers/prober/p_prober.c | 6 +- src/xrt/targets/common/CMakeLists.txt | 2 +- 8 files changed, 113 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dcf94ab0..e639db3fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,6 @@ cmake_dependent_option(XRT_HAVE_OPENGL "Enable OpenGL Graphics API support" ON " cmake_dependent_option(XRT_HAVE_OPENGLES "Enable OpenGL-ES Graphics API support" ON "OpenGLES_FOUND" OFF) cmake_dependent_option(XRT_HAVE_EGL "Enable OpenGL on EGL Graphics API support" ON "EGL_FOUND; XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES" OFF) cmake_dependent_option(XRT_HAVE_DBUS "Enable dbus support (for BLE support)" ON "DBUS_FOUND" OFF) -cmake_dependent_option(XRT_HAVE_VF "Enable gstreamer support (for video file support)" ON "GST_FOUND" OFF) cmake_dependent_option(XRT_FEATURE_COMPOSITOR_MAIN "Build main compositor host functionality" ON "XRT_HAVE_VULKAN; XRT_HAVE_WAYLAND OR XRT_HAVE_XCB OR ANDROID OR WIN32" OFF) cmake_dependent_option(XRT_FEATURE_OPENXR "Build OpenXR runtime target" ON "XRT_FEATURE_COMPOSITOR_MAIN" OFF) cmake_dependent_option(XRT_FEATURE_SERVICE "Enable separate service module for OpenXR runtime" ON "NOT WIN32" OFF) @@ -172,6 +171,7 @@ cmake_dependent_option(XRT_HAVE_LIBUVC "Enable libuvc video driver" ON "LIBUVC_F cmake_dependent_option(XRT_HAVE_FFMPEG "Enable ffmpeg testing video driver" ON "FFMPEG_FOUND" OFF) cmake_dependent_option(XRT_HAVE_SDL2 "Enable use of SDL2" ON "SDL2_FOUND AND XRT_HAVE_OPENGL" OFF) cmake_dependent_option(XRT_HAVE_SYSTEM_CJSON "Enable cJSON from system, instead of bundled source" ON "CJSON_FOUND" OFF) +cmake_dependent_option(XRT_HAVE_GST "Enable gstreamer" ON "GST_FOUND" OFF) cmake_dependent_option(XRT_BUILD_DRIVER_PSVR "Enable PSVR HMD driver" ON "HIDAPI_FOUND" OFF) @@ -191,6 +191,7 @@ cmake_dependent_option(XRT_BUILD_DRIVER_HDK "Enable HDK driver" ON "XRT_HAVE_INT cmake_dependent_option(XRT_BUILD_DRIVER_PSMV "Enable Playstation Move driver" ON "XRT_HAVE_INTERNAL_HID" OFF) cmake_dependent_option(XRT_BUILD_DRIVER_HYDRA "Enable Hydra driver" ON "XRT_HAVE_INTERNAL_HID" OFF) cmake_dependent_option(XRT_BUILD_DRIVER_NS "Enable North Star driver" ON "XRT_HAVE_INTERNAL_HID" OFF) +cmake_dependent_option(XRT_BUILD_DRIVER_VF "Build video frame driver (for video file support, uses gstreamer)" ON "XRT_HAVE_GST" OFF) # This one defaults to off, even if we find the deps. cmake_dependent_option(XRT_BUILD_DRIVER_SURVIVE "Enable libsurvive driver" ON "SURVIVE_FOUND" OFF) @@ -216,6 +217,7 @@ list(APPEND AVAILABLE_DRIVERS "REMOTE" "SURVIVE" "V4L2" + "VF" "VIVE" ) @@ -348,5 +350,6 @@ message(STATUS "# DRIVER_PSVR: ${XRT_BUILD_DRIVER_PSVR}") message(STATUS "# DRIVER_RS: ${XRT_BUILD_DRIVER_RS}") message(STATUS "# DRIVER_REMOTE: ${XRT_BUILD_DRIVER_REMOTE}") message(STATUS "# DRIVER_SURVIVE: ${XRT_BUILD_DRIVER_SURVIVE}") +message(STATUS "# DRIVER_VF: ${XRT_BUILD_DRIVER_VF}") message(STATUS "# DRIVER_VIVE: ${XRT_BUILD_DRIVER_VIVE}") message(STATUS "#####----- Config -----#####") diff --git a/src/xrt/drivers/CMakeLists.txt b/src/xrt/drivers/CMakeLists.txt index 383c3f509..fb1f02c3c 100644 --- a/src/xrt/drivers/CMakeLists.txt +++ b/src/xrt/drivers/CMakeLists.txt @@ -192,7 +192,7 @@ if(XRT_HAVE_V4L2) list(APPEND ENABLED_DRIVERS v4l2) endif() -if(XRT_HAVE_VF) +if(XRT_BUILD_DRIVER_VF) set(VF_SOURCE_FILES vf/vf_driver.c ) diff --git a/src/xrt/drivers/vf/vf_driver.c b/src/xrt/drivers/vf/vf_driver.c index c5d9225c4..0210f8980 100644 --- a/src/xrt/drivers/vf/vf_driver.c +++ b/src/xrt/drivers/vf/vf_driver.c @@ -61,7 +61,6 @@ struct vf_fs struct os_thread_helper play_thread; - const char *path; GMainLoop *loop; GstElement *source; GstElement *testsink; @@ -280,7 +279,7 @@ on_new_sample_from_sink(GstElement *elt, struct vf_fs *vid) gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); - VF_DEBUG(vid, "video size is %dx%d\n", width, height); + VF_DEBUG(vid, "video size is %dx%d", width, height); vid->got_sample = true; vid->width = width; vid->height = height; @@ -303,8 +302,8 @@ print_gst_error(GstMessage *message) gchar *dbg_info = NULL; gst_message_parse_error(message, &err, &dbg_info); - U_LOG_E("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message); - U_LOG_E("Debugging info: %s\n", (dbg_info) ? dbg_info : "none"); + U_LOG_E("ERROR from element %s: %s", GST_OBJECT_NAME(message->src), err->message); + U_LOG_E("Debugging info: %s", (dbg_info) ? dbg_info : "none"); g_error_free(err); g_free(dbg_info); } @@ -315,11 +314,11 @@ on_source_message(GstBus *bus, GstMessage *message, struct vf_fs *vid) /* nil */ switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_EOS: - VF_DEBUG(vid, "Finished playback\n"); + VF_DEBUG(vid, "Finished playback."); g_main_loop_quit(vid->loop); break; case GST_MESSAGE_ERROR: - VF_ERROR(vid, "Received error\n"); + VF_ERROR(vid, "Received error."); print_gst_error(message); g_main_loop_quit(vid->loop); break; @@ -333,9 +332,9 @@ run_play_thread(void *ptr) { struct vf_fs *vid = (struct vf_fs *)ptr; - VF_DEBUG(vid, "Let's run!\n"); + VF_DEBUG(vid, "Let's run!"); g_main_loop_run(vid->loop); - VF_DEBUG(vid, "Going out\n"); + VF_DEBUG(vid, "Going out!"); gst_object_unref(vid->testsink); gst_element_set_state(vid->source, GST_STATE_NULL); @@ -347,56 +346,35 @@ run_play_thread(void *ptr) return NULL; } -struct xrt_fs * -vf_fs_create(struct xrt_frame_context *xfctx, const char *path) +static struct xrt_fs * +alloc_and_init_common(struct xrt_frame_context *xfctx, // + enum xrt_format format, // + enum xrt_stereo_format stereo_format, // + gchar *pipeline_string) // { - if (path == NULL) { - U_LOG_E("No path given"); - return NULL; - } - - struct vf_fs *vid = U_TYPED_CALLOC(struct vf_fs); - vid->path = path; vid->got_sample = false; + vid->format = format; + vid->stereo_format = stereo_format; - gchar *loop = "false"; - - gchar *string = NULL; GstBus *bus = NULL; - - gst_init(0, NULL); - - if (!g_file_test(path, G_FILE_TEST_EXISTS)) { - VF_ERROR(vid, "File %s does not exist\n", path); + int ret = os_thread_helper_init(&vid->play_thread); + if (ret < 0) { + VF_ERROR(vid, "Failed to init thread"); + g_free(pipeline_string); + free(vid); return NULL; } vid->loop = g_main_loop_new(NULL, FALSE); + VF_DEBUG(vid, "Pipeline: %s", pipeline_string); -#if 0 - const gchar *caps = "video/x-raw,format=RGB"; - vid->format = XRT_FORMAT_R8G8B8; - vid->stereo_format = XRT_STEREO_FORMAT_SBS; -#endif - -#if 1 - const gchar *caps = "video/x-raw,format=YUY2"; - vid->format = XRT_FORMAT_YUYV422; - vid->stereo_format = XRT_STEREO_FORMAT_SBS; -#endif - - string = g_strdup_printf( - "multifilesrc location=\"%s\" loop=%s ! decodebin ! videoconvert ! " - "appsink caps=\"%s\" name=testsink", - path, loop, caps); - VF_DEBUG(vid, "Pipeline: %s\n", string); - vid->source = gst_parse_launch(string, NULL); - g_free(string); + vid->source = gst_parse_launch(pipeline_string, NULL); + g_free(pipeline_string); if (vid->source == NULL) { - VF_ERROR(vid, "Bad source\n"); + VF_ERROR(vid, "Bad source"); g_main_loop_unref(vid->loop); free(vid); return NULL; @@ -410,16 +388,21 @@ vf_fs_create(struct xrt_frame_context *xfctx, const char *path) gst_bus_add_watch(bus, (GstBusFunc)on_source_message, vid); gst_object_unref(bus); - int ret = os_thread_helper_start(&vid->play_thread, run_play_thread, vid); - if (!ret) { - VF_ERROR(vid, "Failed to start thread"); + ret = os_thread_helper_start(&vid->play_thread, run_play_thread, vid); + if (ret != 0) { + VF_ERROR(vid, "Failed to start thread '%i'", ret); + g_main_loop_unref(vid->loop); + free(vid); + return NULL; } - // we need one sample to determine frame size + // We need one sample to determine frame size. + VF_DEBUG(vid, "Waiting for frame"); gst_element_set_state(vid->source, GST_STATE_PLAYING); while (!vid->got_sample) { os_nanosleep(100 * 1000 * 1000); } + VF_DEBUG(vid, "Got first sample"); gst_element_set_state(vid->source, GST_STATE_PAUSED); vid->base.enumerate_modes = vf_fs_enumerate_modes; @@ -443,3 +426,61 @@ vf_fs_create(struct xrt_frame_context *xfctx, const char *path) return &(vid->base); } + +struct xrt_fs * +vf_fs_videotestsource(struct xrt_frame_context *xfctx, uint32_t width, uint32_t height) +{ + gst_init(0, NULL); + + enum xrt_format format = XRT_FORMAT_R8G8B8; + enum xrt_stereo_format stereo_format = XRT_STEREO_FORMAT_NONE; + + gchar *pipeline_string = g_strdup_printf( + "videotestsrc name=source ! " + "videoconvert ! " + "videoscale ! " + "video/x-raw,format=RGB,width=%u,height=%u ! " + "appsink name=testsink", + width, height); + + return alloc_and_init_common(xfctx, format, stereo_format, pipeline_string); +} + +struct xrt_fs * +vf_fs_open_file(struct xrt_frame_context *xfctx, const char *path) +{ + if (path == NULL) { + U_LOG_E("No path given"); + return NULL; + } + + gst_init(0, NULL); + + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { + U_LOG_E("File %s does not exist", path); + return NULL; + } + +#if 0 + const gchar *caps = "video/x-raw,format=RGB"; + enum xrt_format format = XRT_FORMAT_R8G8B8; + enum xrt_stereo_format stereo_format = XRT_STEREO_FORMAT_NONE; +#endif + +#if 1 + const gchar *caps = "video/x-raw,format=YUY2"; + enum xrt_format format = XRT_FORMAT_YUYV422; + enum xrt_stereo_format stereo_format = XRT_STEREO_FORMAT_SBS; +#endif + + gchar *loop = "false"; + + gchar *pipeline_string = g_strdup_printf( + "multifilesrc location=\"%s\" loop=%s ! " + "decodebin ! " + "videoconvert ! " + "appsink caps=\"%s\" name=testsink", + path, loop, caps); + + return alloc_and_init_common(xfctx, format, stereo_format, pipeline_string); +} diff --git a/src/xrt/drivers/vf/vf_interface.h b/src/xrt/drivers/vf/vf_interface.h index 7919f83db..4f0ef1b2e 100644 --- a/src/xrt/drivers/vf/vf_interface.h +++ b/src/xrt/drivers/vf/vf_interface.h @@ -1,4 +1,4 @@ -// Copyright 2029, Collabora, Ltd. +// Copyright 2020-2021, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -11,6 +11,7 @@ #include "xrt/xrt_frameserver.h" + #ifdef __cplusplus extern "C" { #endif @@ -23,14 +24,22 @@ extern "C" { */ /*! - * Create a vf frameserver + * Create a vf frameserver by opening a video file. * * @ingroup drv_vf */ struct xrt_fs * -vf_fs_create(struct xrt_frame_context *xfctx, const char *path); +vf_fs_open_file(struct xrt_frame_context *xfctx, const char *path); + +/*! + * Create a vf frameserver that uses the videotestsource. + * + * @ingroup drv_vf + */ +struct xrt_fs * +vf_fs_videotestsource(struct xrt_frame_context *xfctx, uint32_t width, uint32_t height); + #ifdef __cplusplus } - #endif diff --git a/src/xrt/include/xrt/meson.build b/src/xrt/include/xrt/meson.build index edb000a8f..4abefaa95 100644 --- a/src/xrt/include/xrt/meson.build +++ b/src/xrt/include/xrt/meson.build @@ -68,10 +68,6 @@ if has_v4l2_header and 'v4l2' in drivers have_conf.set('XRT_HAVE_V4L2', true) endif -if 'vf' in drivers - have_conf.set('XRT_HAVE_VF', true) -endif - if true have_conf.set('XRT_HAVE_VULKAN', true) endif diff --git a/src/xrt/include/xrt/xrt_config_have.h.cmake_in b/src/xrt/include/xrt/xrt_config_have.h.cmake_in index fa3637f68..e490a0f82 100644 --- a/src/xrt/include/xrt/xrt_config_have.h.cmake_in +++ b/src/xrt/include/xrt/xrt_config_have.h.cmake_in @@ -10,9 +10,9 @@ #pragma once #cmakedefine XRT_HAVE_DBUS -#cmakedefine XRT_HAVE_VF #cmakedefine XRT_HAVE_EGL #cmakedefine XRT_HAVE_FFMPEG +#cmakedefine XRT_HAVE_GST #cmakedefine XRT_HAVE_JPEG #cmakedefine XRT_HAVE_LIBUDEV #cmakedefine XRT_HAVE_LIBUSB diff --git a/src/xrt/state_trackers/prober/p_prober.c b/src/xrt/state_trackers/prober/p_prober.c index 1fc0f2455..76383e7e7 100644 --- a/src/xrt/state_trackers/prober/p_prober.c +++ b/src/xrt/state_trackers/prober/p_prober.c @@ -20,7 +20,7 @@ #include "v4l2/v4l2_interface.h" #endif -#ifdef XRT_HAVE_VF +#ifdef XRT_BUILD_DRIVER_VF #include "vf/vf_interface.h" #endif @@ -742,10 +742,10 @@ open_video_device(struct xrt_prober *xp, { XRT_MAYBE_UNUSED struct prober_device *pdev = (struct prober_device *)xpdev; -#if defined(XRT_HAVE_VF) +#if defined(XRT_BUILD_DRIVER_VF) const char *path = debug_get_option_vf_path(); if (path != NULL) { - struct xrt_fs *xfs = vf_fs_create(xfctx, path); + struct xrt_fs *xfs = vf_fs_open_file(xfctx, path); if (xfs) { *out_xfs = xfs; return 0; diff --git a/src/xrt/targets/common/CMakeLists.txt b/src/xrt/targets/common/CMakeLists.txt index a44fa9027..0bdd0e997 100644 --- a/src/xrt/targets/common/CMakeLists.txt +++ b/src/xrt/targets/common/CMakeLists.txt @@ -72,7 +72,7 @@ if(XRT_HAVE_V4L2) target_link_libraries(target_lists PRIVATE drv_v4l2) endif() -if(XRT_HAVE_VF) +if(XRT_BUILD_DRIVER_VF) target_link_libraries(target_lists PRIVATE drv_vf) endif()