summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-08-12 03:43:54 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2022-08-12 03:43:54 +0200
commit0fe98e7e4001f41b2e6d9520dcb5cde1c3e631e6 (patch)
tree1083a9bef5adc7052e4a780cbce9d461ce51896f
parent3271562e33a8f19416bff2ca122c75b98e85ed7d (diff)
Replaced zbar dependency with gstreamer pipeline
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--Makefile4
-rw-r--r--src/ui/new_contact.c374
-rw-r--r--src/ui/new_contact.h13
3 files changed, 245 insertions, 146 deletions
diff --git a/Makefile b/Makefile
index aa14fdf..41c8fa1 100644
--- a/Makefile
+++ b/Makefile
@@ -48,11 +48,11 @@ LIBRARIES = gnunetchat
PACKAGES = gnunetutil\
glib-2.0\
gstreamer-1.0\
+ gstreamer-app-1.0\
gtk+-3.0\
libhandy-1\
libnotify\
- libqrencode\
- zbar
+ libqrencode
INCLUDES = submodules/gnome-characters/lib
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
index 094dd67..b4de414 100644
--- a/src/ui/new_contact.c
+++ b/src/ui/new_contact.c
@@ -24,6 +24,8 @@
#include "new_contact.h"
+#include <gstreamer-1.0/gst/app/gstappsink.h>
+
#include "../application.h"
static void
@@ -89,61 +91,25 @@ handle_id_drawing_area_draw(GtkWidget* drawing_area,
gtk_render_background(context, cairo, 0, 0, width, height);
- GdkPixbuf *image = NULL;
-
if (!(handle->image))
return FALSE;
uint w, h;
- zbar_image_get_size(handle->image, &w, &h);
-
- uint x, y, min_size;
- min_size = (w < h? w : h);
- x = (w - min_size) / 2;
- y = (h - min_size) / 2;
-
- const void* data = (const void*) (
- (const char*) zbar_image_get_data(handle->image) +
- (x + y * w) * 3
- );
-
- image = gdk_pixbuf_new_from_data(
- data,
- GDK_COLORSPACE_RGB,
- FALSE,
- 8,
- min_size,
- min_size,
- w * 3,
- NULL,
- NULL
- );
+ w = gdk_pixbuf_get_width(handle->image);
+ h = gdk_pixbuf_get_height(handle->image);
- GString *scan_result = (GString*) zbar_image_get_userdata(handle->image);
+ uint min_size = (w < h? w : h);
- if (!scan_result)
- goto render_image;
-
- gtk_entry_set_text(handle->id_entry, scan_result->str);
- g_string_free(scan_result, TRUE);
-
-render_image:
- if (!image)
- return FALSE;
-
- int dwidth = gdk_pixbuf_get_width(image);
- int dheight = gdk_pixbuf_get_height(image);
-
- double ratio_width = 1.0 * width / dwidth;
- double ratio_height = 1.0 * height / dheight;
+ double ratio_width = 1.0 * width / min_size;
+ double ratio_height = 1.0 * height / min_size;
const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
- dwidth = (int) (dwidth * ratio);
- dheight = (int) (dheight * ratio);
+ w = (uint) (min_size * ratio);
+ h = (uint) (min_size * ratio);
- double dx = (width - dwidth) * 0.5;
- double dy = (height - dheight) * 0.5;
+ double dx = (width - w) * 0.5;
+ double dy = (height - h) * 0.5;
const int interp_type = (ratio >= 1.0?
GDK_INTERP_NEAREST :
@@ -151,9 +117,9 @@ render_image:
);
GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
- image,
- dwidth,
- dheight,
+ handle->image,
+ w,
+ h,
interp_type
);
@@ -162,36 +128,78 @@ render_image:
cairo_fill(cairo);
g_object_unref(scaled);
- g_object_unref(image);
-
- zbar_image_destroy(handle->image);
- handle->image = NULL;
-
return FALSE;
}
static void
-_disable_video_processing(UI_NEW_CONTACT_Handle *handle)
+_disable_video_processing(UI_NEW_CONTACT_Handle *handle,
+ gboolean drop_pipeline)
{
gtk_stack_set_visible_child(handle->preview_stack, handle->fail_box);
- if (!(handle->video))
+ if (0 != handle->idle_processing)
+ g_source_remove(handle->idle_processing);
+
+ handle->idle_processing = 0;
+
+ if ((!(handle->pipeline)) || (!drop_pipeline))
return;
- const zbar_error_t error_code = zbar_video_get_error_code(handle->video);
+ gst_element_set_state(handle->pipeline, GST_STATE_NULL);
+}
- if (ZBAR_OK != error_code)
- {
- const char *error_msg = zbar_video_error_string(handle->video, 0);
+static void
+_handle_video_sample(UI_NEW_CONTACT_Handle *handle,
+ GstAppSink *appsink)
+{
+ GstSample *sample = gst_app_sink_try_pull_sample(appsink, 10);
- if (error_msg)
- fprintf(stderr, "%s", error_msg);
- else
- fprintf(stderr, "ERROR: Unknown error with zbar (%d)\n",
- (int) error_code);
- }
+ if (!sample)
+ return;
- handle->idle_processing = 0;
+ GstCaps *caps = gst_sample_get_caps(sample);
+
+ GstStructure *s = gst_caps_get_structure(caps, 0);
+
+ gint width, height;
+ gst_structure_get_int(s, "width", &width);
+ gst_structure_get_int(s, "height", &height);
+
+ uint x, y, min_size;
+ min_size = (width < height? width : height);
+ x = (width - min_size) / 2;
+ y = (height - min_size) / 2;
+
+ GstBuffer *buffer = gst_sample_get_buffer(sample);
+ GstMapInfo map;
+
+ gst_buffer_map(buffer, &map, GST_MAP_READ);
+
+ if (handle->image)
+ g_object_unref(handle->image);
+
+ const void* data = (const void*) (
+ (const char*) (map.data) + (x + y * width) * 3
+ );
+
+ handle->image = gdk_pixbuf_new_from_data(
+ data,
+ GDK_COLORSPACE_RGB,
+ FALSE,
+ 8,
+ min_size,
+ min_size,
+ width * 3,
+ NULL,
+ NULL
+ );
+
+ gst_buffer_unmap(buffer, &map);
+
+ if (handle->id_drawing_area)
+ gtk_widget_queue_draw(GTK_WIDGET(handle->id_drawing_area));
+
+ gst_sample_unref(sample);
}
static gboolean
@@ -202,72 +210,168 @@ idle_video_processing(gpointer user_data)
if (0 == handle->idle_processing)
return FALSE;
- zbar_image_t *image = zbar_video_next_image(handle->video);
+ GstAppSink *appsink = GST_APP_SINK(handle->sink);
- if (!image)
+ if (!appsink)
{
- _disable_video_processing(handle);
+ _disable_video_processing(handle, TRUE);
return FALSE;
}
- GString *scan_result = NULL;
+ _handle_video_sample(handle, appsink);
+ return TRUE;
+}
- zbar_image_t *y8 = zbar_image_convert(
- image,
- zbar_fourcc('Y', '8', '0', '0')
- );
+static void
+msg_error_cb(UNUSED GstBus *bus,
+ GstMessage *msg,
+ gpointer *data)
+{
+ UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
+
+ GError* error;
+ gst_message_parse_error(msg, &error, NULL);
+
+ if (!error)
+ fprintf(stderr, "ERROR: Unknown error\n");
+ else if (error->message)
+ fprintf(stderr, "ERROR: %s (%d)", error->message, error->code);
+ else
+ fprintf(stderr, "ERROR: Unknown error (%d)\n", error->code);
- if (zbar_scan_image(handle->scanner, y8) <= 0)
- goto cleanup_scan;
+ gst_element_set_state(handle->pipeline, GST_STATE_READY);
+
+ if (!(handle->preview_stack))
+ return;
- const zbar_symbol_set_t* set = zbar_image_scanner_get_results(
- handle->scanner
+ gtk_stack_set_visible_child(
+ handle->preview_stack,
+ handle->fail_box
);
+}
- const zbar_symbol_t* symbol = zbar_symbol_set_first_symbol(set);
+static void
+msg_eos_cb(UNUSED GstBus *bus,
+ UNUSED GstMessage *msg,
+ gpointer *data)
+{
+ UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
+
+ if (GST_MESSAGE_SRC(msg) == GST_OBJECT(handle->pipeline))
+ _disable_video_processing(handle, TRUE);
+}
+
+static void
+msg_state_changed_cb(UNUSED GstBus *bus,
+ GstMessage *msg,
+ gpointer *data)
+{
+ UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
- if (!symbol)
- goto cleanup_scan;
+ GstState old_state, new_state, pending_state;
+ gst_message_parse_state_changed(msg, &old_state, &new_state, &pending_state);
- uint data_len = 0;
- const char *data = NULL;
+ if ((GST_MESSAGE_SRC(msg) != GST_OBJECT(handle->pipeline)) ||
+ (new_state == old_state) || (!(handle->preview_stack)))
+ return;
- for (; symbol; symbol = zbar_symbol_next(symbol))
+ if (GST_STATE_PLAYING == new_state)
{
- if (zbar_symbol_get_count(symbol))
- continue;
+ gtk_stack_set_visible_child(
+ handle->preview_stack,
+ GTK_WIDGET(handle->id_drawing_area)
+ );
- data_len = zbar_symbol_get_data_length(symbol);
- data = zbar_symbol_get_data(symbol);
+ if (0 == handle->idle_processing)
+ handle->idle_processing = g_idle_add(idle_video_processing, handle);
}
+ else if (GST_STATE_PAUSED == new_state)
+ _disable_video_processing(handle, FALSE);
+}
- if ((data_len > 0) && (data))
- scan_result = g_string_new_len(data, data_len);
+static void
+msg_barcode_cb(UNUSED GstBus *bus,
+ GstMessage *msg,
+ gpointer *data)
+{
+ UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) data;
+ GstMessageType msg_type = GST_MESSAGE_TYPE(msg);
+
+ if ((GST_MESSAGE_SRC(msg) != GST_OBJECT(handle->scanner)) ||
+ (GST_MESSAGE_ELEMENT != msg_type))
+ return;
+
+ const GstStructure *s = gst_message_get_structure(msg);
-cleanup_scan:
- zbar_image_destroy(y8);
+ if (!s)
+ return;
+
+ const gchar *type = gst_structure_get_string(s, "type");
+ const gchar *symbol = gst_structure_get_string(s, "symbol");
+
+ if ((!type) || (!symbol) || (0 != g_strcmp0(type, "QR-Code")))
+ return;
- zbar_image_t *rgb = zbar_image_convert(
- image,
- zbar_fourcc('R', 'G', 'B', '3')
+ if (handle->id_entry)
+ gtk_entry_set_text(handle->id_entry, symbol);
+}
+
+static void
+_setup_gst_pipeline(UI_NEW_CONTACT_Handle *handle)
+{
+ handle->pipeline = gst_parse_launch(
+ "v4l2src name=source ! videoconvert ! zbar name=scanner"
+ " ! videoconvert ! video/x-raw,format=RGB ! videoconvert ! appsink name=sink",
+ NULL
);
- if (!rgb)
- goto cleanup_image;
+ handle->source = gst_bin_get_by_name(
+ GST_BIN(handle->pipeline), "source"
+ );
- zbar_image_set_userdata(rgb, scan_result);
+ handle->scanner = gst_bin_get_by_name(
+ GST_BIN(handle->pipeline), "scanner"
+ );
- if (handle->image)
- zbar_image_destroy(handle->image);
+ handle->sink = gst_bin_get_by_name(
+ GST_BIN(handle->pipeline), "sink"
+ );
- handle->image = rgb;
+ gst_app_sink_set_drop(GST_APP_SINK(handle->sink), TRUE);
- if (handle->id_drawing_area)
- gtk_widget_queue_draw(GTK_WIDGET(handle->id_drawing_area));
+ GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(handle->pipeline));
-cleanup_image:
- zbar_image_destroy(image);
- return TRUE;
+ gst_bus_add_signal_watch(bus);
+
+ g_signal_connect(
+ G_OBJECT(bus),
+ "message::error",
+ (GCallback) msg_error_cb,
+ handle
+ );
+
+ g_signal_connect(
+ G_OBJECT(bus),
+ "message::eos",
+ (GCallback) msg_eos_cb,
+ handle
+ );
+
+ g_signal_connect(
+ G_OBJECT(bus),
+ "message::state-changed",
+ (GCallback) msg_state_changed_cb,
+ handle
+ );
+
+ g_signal_connect(
+ G_OBJECT(bus),
+ "message",
+ (GCallback) msg_barcode_cb,
+ handle
+ );
+
+ gst_object_unref(bus);
}
static void*
@@ -275,31 +379,17 @@ _ui_new_contact_video_thread(void *args)
{
UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) args;
- if (0 != zbar_video_open(handle->video, ""))
- {
- _disable_video_processing(handle);
+ if (!(handle->pipeline))
return NULL;
- }
-
- if (0 != zbar_video_enable(handle->video, 1))
- {
- _disable_video_processing(handle);
- return NULL;
- }
- zbar_image_scanner_set_config(
- handle->scanner,
- ZBAR_QRCODE,
- ZBAR_CFG_ENABLE,
- TRUE
+ GstStateChangeReturn ret = gst_element_set_state(
+ handle->pipeline,
+ GST_STATE_PLAYING
);
- gtk_stack_set_visible_child(
- handle->preview_stack,
- GTK_WIDGET(handle->id_drawing_area)
- );
+ if (GST_STATE_CHANGE_FAILURE == ret)
+ _disable_video_processing(handle, TRUE);
- handle->idle_processing = g_idle_add(idle_video_processing, handle);
return NULL;
}
@@ -307,8 +397,16 @@ void
ui_new_contact_dialog_init(MESSENGER_Application *app,
UI_NEW_CONTACT_Handle *handle)
{
- handle->video = zbar_video_create();
- handle->scanner = zbar_image_scanner_create();
+ _setup_gst_pipeline(handle);
+
+ handle->image = NULL;
+
+ pthread_create(
+ &(handle->video_tid),
+ NULL,
+ _ui_new_contact_video_thread,
+ handle
+ );
handle->builder = gtk_builder_new_from_resource(
application_get_resource_path(app, "ui/new_contact.ui")
@@ -335,13 +433,6 @@ ui_new_contact_dialog_init(MESSENGER_Application *app,
gtk_builder_get_object(handle->builder, "id_drawing_area")
);
- pthread_create(
- &(handle->video_tid),
- NULL,
- _ui_new_contact_video_thread,
- handle
- );
-
handle->id_draw_signal = g_signal_connect(
handle->id_drawing_area,
"draw",
@@ -398,13 +489,16 @@ ui_new_contact_dialog_cleanup(UI_NEW_CONTACT_Handle *handle)
handle->id_draw_signal
);
- g_object_unref(handle->builder);
-
if (handle->image)
- zbar_image_destroy(handle->image);
+ g_object_unref(handle->image);
- zbar_image_scanner_destroy(handle->scanner);
- zbar_video_destroy(handle->video);
+ g_object_unref(handle->builder);
+
+ if (handle->pipeline)
+ {
+ gst_element_set_state(handle->pipeline, GST_STATE_NULL);
+ gst_object_unref(GST_OBJECT(handle->pipeline));
+ }
memset(handle, 0, sizeof(*handle));
}
diff --git a/src/ui/new_contact.h b/src/ui/new_contact.h
index 7a7ff96..dd04cce 100644
--- a/src/ui/new_contact.h
+++ b/src/ui/new_contact.h
@@ -29,14 +29,19 @@
#include <cairo/cairo.h>
#include <gdk/gdkpixbuf.h>
+#include <gstreamer-1.0/gst/gst.h>
#include <pthread.h>
-#include <zbar.h>
typedef struct UI_NEW_CONTACT_Handle
{
- zbar_video_t *video;
- zbar_image_t *image;
- zbar_image_scanner_t *scanner;
+ GstElement *pipeline;
+ GstElement *source;
+ GstElement *scanner;
+ GstElement *sink;
+
+ guint bus_watch;
+
+ GdkPixbuf *image;
GtkBuilder *builder;
GtkDialog *dialog;