summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/CMakeLists.txt2
-rw-r--r--app/main.cpp117
-rw-r--r--app/still-image.jpgbin0 -> 1057603 bytes
3 files changed, 84 insertions, 35 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index fc71e8f..d7935f3 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -117,3 +117,5 @@ target_link_libraries(${PROJECT_NAME}
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
include(GNUInstallDirs)
install(FILES ${PROJECT_NAME}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
+install(FILES still-image.jpg DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/data)
+add_definitions(-DAPP_DATA_PATH=${CMAKE_INSTALL_FULL_DATADIR}/applications/data)
diff --git a/app/main.cpp b/app/main.cpp
index 2068143..2d286ba 100644
--- a/app/main.cpp
+++ b/app/main.cpp
@@ -97,6 +97,8 @@ struct receiver_data {
};
static int running = 1;
+static bool gst_pipeline_failed = FALSE;
+static bool fallback_gst_pipeline_tried = FALSE;
static void
redraw(void *data, struct wl_callback *callback, uint32_t time);
@@ -491,6 +493,19 @@ bus_sync_handler(GstBus *bus, GstMessage *message, gpointer user_data)
goto drop;
}
+ else if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR) {
+ GError* err = NULL;
+ gchar* dbg_info = NULL;
+
+ gst_message_parse_error(message, &err, &dbg_info);
+ g_printerr("ERROR from element %s: %s code %d\n",
+ GST_OBJECT_NAME(message->src), err->message, err->code);
+ g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
+ gst_pipeline_failed = TRUE;
+ g_error_free(err);
+ g_free(dbg_info);
+ goto drop;
+ }
return GST_BUS_PASS;
@@ -700,13 +715,13 @@ destroy_display(struct display *display)
free(display);
}
-int main(int argc, char *argv[])
+// 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[])
{
- int ret = 0;
- struct sigaction sa;
- struct receiver_data receiver_data = {};
- struct display *display;
- struct window *window;
+ GError *error = NULL;
const char *camera_device = NULL;
const char *width_str = NULL;
const char *height_str = NULL;
@@ -718,19 +733,6 @@ int main(int argc, char *argv[])
bool v4l2 = false;
char pipeline_str[1024];
- GError *error = NULL;
- const char *app_id = "camera-gstreamer";
-
- sa.sa_sigaction = signal_int;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
- sigaction(SIGINT, &sa, NULL);
-
- int gargc = 2;
- char **gargv = static_cast<char **>(calloc(2, sizeof(char *)));
-
- gargv[0] = strdup(argv[0]);
- gargv[1] = strdup("--gst-debug-level=2");
camera_device = getenv("DEFAULT_V4L2_DEVICE");
if (!camera_device)
@@ -758,24 +760,57 @@ int main(int argc, char *argv[])
if (v4l2)
snprintf(pipeline_str, sizeof(pipeline_str), "v4l2src device=%s ! video/x-raw,width=%d,height=%d ! waylandsink",
camera_device, width, height);
- else
- snprintf(pipeline_str, sizeof(pipeline_str), "pipewiresrc ! video/x-raw,width=%d,height=%d ! waylandsink",
- width, height);
-
- gst_init(&gargc, &gargv);
-
- setbuf(stdout, NULL);
+ else if (gst_pipeline_failed == TRUE) {
+ snprintf(pipeline_str, sizeof(pipeline_str), "filesrc location=%s/still-image.jpg ! decodebin ! videoconvert ! imagefreeze ! waylandsink fullscreen=true",
+ xstr(APP_DATA_PATH), width, height);
+ fallback_gst_pipeline_tried = TRUE;
+ }
+ else {
+ snprintf(pipeline_str, sizeof(pipeline_str), "pipewiresrc ! video/x-raw,width=%d,height=%d ! waylandsink", width,
+ height);
+ }
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(gargv);
- return EXIT_FAILURE;
+ free(argv);
+ return NULL;
}
- receiver_data.pipeline = pipeline;
+ return pipeline;
+}
+
+int main(int argc, char* argv[])
+{
+ int ret = 0;
+ struct sigaction sa;
+ struct receiver_data receiver_data = {};
+ struct display* display;
+ struct window* window;
+ const char* app_id = "camera-gstreamer";
+
+ sa.sa_sigaction = signal_int;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
+ sigaction(SIGINT, &sa, NULL);
+
+ int gargc = 2;
+ char** gargv = static_cast<char**>(calloc(2, sizeof(char*)));
+
+ gargv[0] = strdup(argv[0]);
+ gargv[1] = strdup("--gst-debug-level=2");
+
+ setbuf(stdout, NULL);
+
+ gst_init(&gargc, &gargv);
+
+ receiver_data.pipeline = create_pipeline(&gargc, &gargv);
+
+ if (!receiver_data.pipeline)
+ return EXIT_FAILURE;
display = create_display(argc, argv);
if (!display)
@@ -809,22 +844,34 @@ int main(int argc, char *argv[])
redraw(window, NULL, 0);
}
- GstBus *bus = gst_element_get_bus(pipeline);
+ GstBus *bus = gst_element_get_bus(receiver_data.pipeline);
gst_bus_add_signal_watch(bus);
g_signal_connect(bus, "message::error", G_CALLBACK(error_cb), &receiver_data);
gst_bus_set_sync_handler(bus, bus_sync_handler, &receiver_data, NULL);
gst_object_unref(bus);
- gst_element_set_state(pipeline, GST_STATE_PLAYING);
+ gst_element_set_state(receiver_data.pipeline, GST_STATE_PLAYING);
fprintf(stdout, "gstreamer pipeline running\n");
// run the application
- while (running && ret != -1)
+ while (running && ret != -1) {
ret = wl_display_dispatch(display->wl_display);
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- gst_object_unref(pipeline);
+ if (gst_pipeline_failed && fallback_gst_pipeline_tried == FALSE) {
+ gst_element_set_state(receiver_data.pipeline, GST_STATE_NULL);
+ gst_object_unref(receiver_data.pipeline);
+ /* retry with fallback pipeline */
+ receiver_data.pipeline = create_pipeline(&gargc, &gargv);
+ GstBus *bus = gst_element_get_bus(receiver_data.pipeline);
+ gst_bus_add_signal_watch(bus);
+ g_signal_connect(bus, "message::error", G_CALLBACK(error_cb), &receiver_data);
+ gst_bus_set_sync_handler(bus, bus_sync_handler, &receiver_data, NULL);
+ gst_object_unref(bus);
+ gst_element_set_state(receiver_data.pipeline, GST_STATE_PLAYING);
+ }
+ }
+ gst_element_set_state(receiver_data.pipeline, GST_STATE_NULL);
+ gst_object_unref(receiver_data.pipeline);
destroy_window(window);
destroy_display(display);
diff --git a/app/still-image.jpg b/app/still-image.jpg
new file mode 100644
index 0000000..994778c
--- /dev/null
+++ b/app/still-image.jpg
Binary files differ