Allow the device, image scaling and flipping to be configured
This commit is contained in:
parent
3c6a1f86f9
commit
968a9353be
@ -1,5 +1,5 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/* Copyright (c) 2012-2013 Pierre Pronchery <khorben@defora.org> */
|
/* Copyright (c) 2012-2014 Pierre Pronchery <khorben@defora.org> */
|
||||||
/* This file is part of DeforaOS Desktop Phone */
|
/* This file is part of DeforaOS Desktop Phone */
|
||||||
/* This program is free software: you can redistribute it and/or modify
|
/* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -43,6 +43,10 @@ typedef struct _PhonePlugin
|
|||||||
PhonePluginHelper * helper;
|
PhonePluginHelper * helper;
|
||||||
|
|
||||||
String * device;
|
String * device;
|
||||||
|
gboolean hflip;
|
||||||
|
gboolean vflip;
|
||||||
|
gboolean ratio;
|
||||||
|
GdkInterpType interp;
|
||||||
|
|
||||||
guint source;
|
guint source;
|
||||||
int fd;
|
int fd;
|
||||||
@ -114,14 +118,25 @@ static int _open_setup(VideoPhonePlugin * video);
|
|||||||
static VideoPhonePlugin * _video_init(PhonePluginHelper * helper)
|
static VideoPhonePlugin * _video_init(PhonePluginHelper * helper)
|
||||||
{
|
{
|
||||||
VideoPhonePlugin * video;
|
VideoPhonePlugin * video;
|
||||||
char const * device = NULL;
|
char const * device;
|
||||||
|
char const * p;
|
||||||
|
|
||||||
if((video = object_new(sizeof(*video))) == NULL)
|
if((video = object_new(sizeof(*video))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
video->helper = helper;
|
video->helper = helper;
|
||||||
/* FIXME let this be configurable */
|
if((device = helper->config_get(helper->phone, "video", "device"))
|
||||||
if(device == NULL)
|
== NULL)
|
||||||
device = "/dev/video0";
|
device = "/dev/video0";
|
||||||
|
p = helper->config_get(helper->phone, "video", "hflip");
|
||||||
|
video->hflip = (p != NULL && p[0] != '\0' && strtol(p, NULL, 10) > 0)
|
||||||
|
? TRUE : FALSE;
|
||||||
|
p = helper->config_get(helper->phone, "video", "vflip");
|
||||||
|
video->vflip = (p != NULL && p[0] != '\0' && strtol(p, NULL, 10) > 0)
|
||||||
|
? TRUE : FALSE;
|
||||||
|
p = helper->config_get(helper->phone, "video", "ratio");
|
||||||
|
video->ratio = (p == NULL || p[0] == '\0' || strtol(p, NULL, 10) != 0)
|
||||||
|
? TRUE : FALSE;
|
||||||
|
video->interp = GDK_INTERP_BILINEAR;
|
||||||
video->source = 0;
|
video->source = 0;
|
||||||
video->fd = -1;
|
video->fd = -1;
|
||||||
memset(&video->cap, 0, sizeof(video->cap));
|
memset(&video->cap, 0, sizeof(video->cap));
|
||||||
@ -378,6 +393,9 @@ static gboolean _video_on_drawing_area_expose(GtkWidget * widget,
|
|||||||
static void _refresh_convert(VideoPhonePlugin * video);
|
static void _refresh_convert(VideoPhonePlugin * video);
|
||||||
static void _refresh_convert_yuv(int amp, uint8_t y, uint8_t u, uint8_t v,
|
static void _refresh_convert_yuv(int amp, uint8_t y, uint8_t u, uint8_t v,
|
||||||
uint8_t * r, uint8_t * g, uint8_t * b);
|
uint8_t * r, uint8_t * g, uint8_t * b);
|
||||||
|
static void _refresh_hflip(VideoPhonePlugin * video, GdkPixbuf ** pixbuf);
|
||||||
|
static void _refresh_scale(VideoPhonePlugin * video, GdkPixbuf ** pixbuf);
|
||||||
|
static void _refresh_vflip(VideoPhonePlugin * video, GdkPixbuf ** pixbuf);
|
||||||
|
|
||||||
static gboolean _video_on_refresh(gpointer data)
|
static gboolean _video_on_refresh(gpointer data)
|
||||||
{
|
{
|
||||||
@ -386,14 +404,16 @@ static gboolean _video_on_refresh(gpointer data)
|
|||||||
int width = video->format.fmt.pix.width;
|
int width = video->format.fmt.pix.width;
|
||||||
int height = video->format.fmt.pix.height;
|
int height = video->format.fmt.pix.height;
|
||||||
GdkPixbuf * pixbuf;
|
GdkPixbuf * pixbuf;
|
||||||
GdkPixbuf * pixbuf2;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s() 0x%x\n", __func__,
|
fprintf(stderr, "DEBUG: %s() 0x%x\n", __func__,
|
||||||
video->format.fmt.pix.pixelformat);
|
video->format.fmt.pix.pixelformat);
|
||||||
#endif
|
#endif
|
||||||
_refresh_convert(video);
|
_refresh_convert(video);
|
||||||
if(width == allocation->width && height == allocation->height)
|
if(video->hflip == FALSE
|
||||||
|
&& video->vflip == FALSE
|
||||||
|
&& width == allocation->width
|
||||||
|
&& height == allocation->height)
|
||||||
/* render directly */
|
/* render directly */
|
||||||
gdk_draw_rgb_image(video->pixmap, video->gc, 0, 0,
|
gdk_draw_rgb_image(video->pixmap, video->gc, 0, 0,
|
||||||
width, height, GDK_RGB_DITHER_NORMAL,
|
width, height, GDK_RGB_DITHER_NORMAL,
|
||||||
@ -404,12 +424,12 @@ static gboolean _video_on_refresh(gpointer data)
|
|||||||
pixbuf = gdk_pixbuf_new_from_data(video->rgb_buffer,
|
pixbuf = gdk_pixbuf_new_from_data(video->rgb_buffer,
|
||||||
GDK_COLORSPACE_RGB, FALSE, 8, width, height,
|
GDK_COLORSPACE_RGB, FALSE, 8, width, height,
|
||||||
width * 3, NULL, NULL);
|
width * 3, NULL, NULL);
|
||||||
pixbuf2 = gdk_pixbuf_scale_simple(pixbuf, allocation->width,
|
_refresh_hflip(video, &pixbuf);
|
||||||
allocation->height, GDK_INTERP_BILINEAR);
|
_refresh_vflip(video, &pixbuf);
|
||||||
gdk_pixbuf_render_to_drawable(pixbuf2, video->pixmap,
|
_refresh_scale(video, &pixbuf);
|
||||||
|
gdk_pixbuf_render_to_drawable(pixbuf, video->pixmap,
|
||||||
video->gc, 0, 0, 0, 0, -1, -1,
|
video->gc, 0, 0, 0, 0, -1, -1,
|
||||||
GDK_RGB_DITHER_NORMAL, 0, 0);
|
GDK_RGB_DITHER_NORMAL, 0, 0);
|
||||||
g_object_unref(pixbuf2);
|
|
||||||
g_object_unref(pixbuf);
|
g_object_unref(pixbuf);
|
||||||
}
|
}
|
||||||
/* force a refresh */
|
/* force a refresh */
|
||||||
@ -473,3 +493,65 @@ static void _refresh_convert_yuv(int amp, uint8_t y, uint8_t u, uint8_t v,
|
|||||||
*g = (dg < 0) ? 0 : ((dg > 255) ? 255 : dg);
|
*g = (dg < 0) ? 0 : ((dg > 255) ? 255 : dg);
|
||||||
*b = (db < 0) ? 0 : ((db > 255) ? 255 : db);
|
*b = (db < 0) ? 0 : ((db > 255) ? 255 : db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _refresh_hflip(VideoPhonePlugin * video, GdkPixbuf ** pixbuf)
|
||||||
|
{
|
||||||
|
GdkPixbuf * pixbuf2;
|
||||||
|
|
||||||
|
if(video->hflip == FALSE)
|
||||||
|
return;
|
||||||
|
/* XXX could probably be more efficient */
|
||||||
|
pixbuf2 = gdk_pixbuf_flip(*pixbuf, TRUE);
|
||||||
|
g_object_unref(*pixbuf);
|
||||||
|
*pixbuf = pixbuf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _refresh_scale(VideoPhonePlugin * video, GdkPixbuf ** pixbuf)
|
||||||
|
{
|
||||||
|
GtkAllocation * allocation = &video->area_allocation;
|
||||||
|
GdkPixbuf * pixbuf2;
|
||||||
|
gdouble scale;
|
||||||
|
gint width;
|
||||||
|
gint height;
|
||||||
|
gint x;
|
||||||
|
gint y;
|
||||||
|
|
||||||
|
if(video->ratio == FALSE)
|
||||||
|
pixbuf2 = gdk_pixbuf_scale_simple(*pixbuf, allocation->width,
|
||||||
|
allocation->height, video->interp);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((pixbuf2 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
|
||||||
|
allocation->width,
|
||||||
|
allocation->height)) == NULL)
|
||||||
|
return;
|
||||||
|
/* XXX could be more efficient */
|
||||||
|
gdk_pixbuf_fill(pixbuf2, 0);
|
||||||
|
scale = (gdouble)allocation->width
|
||||||
|
/ video->format.fmt.pix.width;
|
||||||
|
scale = MIN(scale, (gdouble)allocation->height
|
||||||
|
/ video->format.fmt.pix.height);
|
||||||
|
width = (gdouble)video->format.fmt.pix.width * scale;
|
||||||
|
width = MIN(width, allocation->width);
|
||||||
|
height = (gdouble)video->format.fmt.pix.height * scale;
|
||||||
|
height = MIN(height, allocation->height);
|
||||||
|
x = (allocation->width - width) / 2;
|
||||||
|
y = (allocation->height - height) / 2;
|
||||||
|
gdk_pixbuf_scale(*pixbuf, pixbuf2, x, y, width, height,
|
||||||
|
0.0, 0.0, scale, scale, video->interp);
|
||||||
|
}
|
||||||
|
g_object_unref(*pixbuf);
|
||||||
|
*pixbuf = pixbuf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _refresh_vflip(VideoPhonePlugin * video, GdkPixbuf ** pixbuf)
|
||||||
|
{
|
||||||
|
GdkPixbuf * pixbuf2;
|
||||||
|
|
||||||
|
if(video->vflip == FALSE)
|
||||||
|
return;
|
||||||
|
/* XXX could probably be more efficient */
|
||||||
|
pixbuf2 = gdk_pixbuf_flip(*pixbuf, FALSE);
|
||||||
|
g_object_unref(*pixbuf);
|
||||||
|
*pixbuf = pixbuf2;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user