|
楼主 |
发表于 2009-3-11 23:41:36
|
显示全部楼层
//draw.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <semaphore.h>
#include "draw.h"
#include <linux/videodev2.h>
#define TIMEOUT_UNSET 0
#define DATA_BUFFERS 8
#define NUM_BUFFERS 2
struct backend_data
{
GtkWidget *widget;
guchar *image_data[ NUM_BUFFERS ];
struct timeval fill_times[ NUM_BUFFERS ];
gint current_buffer;
tcpcam_format_t format;
GdkPixbuf *pixbuf;
gint crop_x;
gint crop_y;
gint crop_w;
gint crop_h;
Display *display;
GdkWindow *overlay_window;
GdkGC *overlay_gc;
guint exposure_timer;
gboolean scale_to_fit;
gint output_width;
gint output_height;
gboolean pause_state;
sem_t sema;
};
enum {
UNICAPGTK_VIDEO_DISPLAY_PREDISPLAY_SIGNAL,
LAST_SIGNAL
};
enum
{
PROP_0 = 0,
PROP_SCALE_TO_FIT,
PROP_BACKEND,
PROP_FOURCC,
};
struct _TcpcamGtkDisplay
{
GtkWidget widget;
GtkWidget *drawing_area;
GdkGC *gc;
GdkPixbuf *still_image_pixbuf;
gint display_timeout_tag;
gboolean scale_to_fit;
gboolean capture_running;
volatile gboolean pause;
tcpcam_format_t format;
tcpcam_data_buffer_t data_buffer[DATA_BUFFERS];
tcpcam_data_buffer_t still_image_buffer;
tcpcam_data_buffer_t pause_buffer;
volatile gboolean new_frame;
tcpcam_new_frame_callback_t new_frame_callback;
void * new_frame_callback_data;
unsigned int new_frame_callback_flags;
struct timeval disp_time;
tcpcam_gtk_color_conversion_callback_t color_conversion_cb;
void *color_conversion_data;
unsigned int backend_fourcc;
int crop_x;
int crop_y;
int crop_width;
int crop_height;
int display_width;
int display_height;
void (*backend_update_image)(gpointer data,
tcpcam_data_buffer_t *data_buffer, GError **err );
void (*backend_destroy) ( gpointer _data );
void (*backend_gtk_expose)( gpointer _data, GtkWidget *da, GdkEventExpose *event );
void (*backend_expose)( gpointer _data, GtkWidget *da, GdkEventExpose *event );
void (*backend_get_image_data)( gpointer _data, tcpcam_data_buffer_t *data_buffer, int b );
void (*backend_lock)( gpointer _data );
void (*backend_unlock)( gpointer _data );
void (*backend_set_scale_to_fit)( gpointer _data, gboolean scale );
void (*backend_display_image) ( gpointer _data );
void (*backend_redraw) ( gpointer _data );
void (*backend_size_allocate)(gpointer _data, GtkWidget *widget, GtkAllocation *allocation );
void (*backend_set_pause_state)( gpointer _data, gboolean state );
guint (*backend_get_flags)( gpointer _data );
void (*backend_color_conversion_callback)( void *_backend_data,
tcpcam_gtk_color_conversion_callback_t cb,
void *data );
gpointer backend_data;
};
static void gtk_video_display_class_init ( TcpcamGtkDisplayClass *klass);
static void gtk_video_display_init ( TcpcamGtkDisplay *display);
static void gtk_video_display_set_property ( GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec );
static void gtk_video_display_get_property ( GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec );
static void gtk_video_display_destroy ( GtkObject *object );
static gboolean tlwindow_configure_event( GtkWidget *window, GdkEventConfigure *event, TcpcamGtkDisplay *display );
static void da_hierarchy_changed_cb( GtkWidget *da, GtkWidget *widget2, TcpcamGtkDisplay *display );
static void da_configure_cb ( GtkWidget *da, GdkEventConfigure *event, TcpcamGtkDisplay *display );
static GtkWidgetClass *parent_class = NULL;
static guint tcpcam_gtk_video_display_signals[LAST_SIGNAL] = { 0 };
static void gtk_video_display_realize (GtkWidget *widget);
static void gtk_video_display_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static void gtk_display_drawing_area_attach (TcpcamGtkDisplay *display);
static gint gtk_video_display_expose (GtkWidget *widget, GdkEventExpose *event);
static void gtk_video_display_send_configure (TcpcamGtkDisplay *display);
static void gtk_video_display_update (TcpcamGtkDisplay *display);
GType
tcpcam_gtk_display_get_type (void)
{
static GType display_type = 0;
if( !display_type )
{
static const GTypeInfo display_info =
{
sizeof( TcpcamGtkDisplayClass ),
NULL, /* base_init */
NULL, /* base_finalize */
( GClassInitFunc ) gtk_video_display_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof( TcpcamGtkDisplay ),
0,
( GInstanceInitFunc ) gtk_video_display_init,
};
display_type = g_type_register_static( GTK_TYPE_ASPECT_FRAME, "TcpcamGtkDisplay",
&display_info, 0 );
}
return display_type;
}
static void gtk_video_display_class_init( TcpcamGtkDisplayClass *class )
{
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS(class );
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);;
GObjectClass *object_class = G_OBJECT_CLASS( class );
puts ("before class init");
widget_class->realize = gtk_video_display_realize;
widget_class->size_allocate = gtk_video_display_size_allocate;
widget_class->expose_event = gtk_video_display_expose;
parent_class = gtk_type_class (gtk_widget_get_type ());
object_class = G_OBJECT_CLASS (class);
object_class->set_property = gtk_video_display_set_property;
object_class->get_property = gtk_video_display_get_property;
gtk_object_class->destroy = gtk_video_display_destroy;
/*
widget_class->size_request = gtk_dial_size_request;
widget_class->size_allocate = gtk_dial_size_allocate;
*/
tcpcam_gtk_video_display_signals[UNICAPGTK_VIDEO_DISPLAY_PREDISPLAY_SIGNAL] =
g_signal_new( "tcpcam_gtk_video_display_predisplay",
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET(TcpcamGtkDisplayClass, gtk_display),
NULL,
NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER );
g_object_class_install_property (object_class,
PROP_FOURCC,
g_param_spec_uint ("backend_fourcc",
NULL, NULL,
0, 0xffffffff, 0,
G_PARAM_READWRITE ) );
puts ("after class init");
}
static void gtk_video_display_set_property( GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec )
{
// TcpcamGtkDisplay *display = TCPCAM_GTK_DISPLAY( object );
#if 0
switch( property_id )
{
case PROP_FOURCC:
{
display->backend_fourcc = g_value_get_uint( value );
set_backend( display );
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
break;
}
#endif
}
static void gtk_video_display_get_property( GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec )
{
// TcpcamGtkDisplay *display = TCPCAM_GTK_DISPLAY( object );
#if 0
switch( property_id )
{
case PROP_FOURCC:
g_value_set_uint( value, display->backend_fourcc );
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
break;
}
#endif
}
static void gtk_video_display_destroy( GtkObject *object )
{
TcpcamGtkDisplay *display = TCPCAM_GTK_DISPLAY( object );
if( display->capture_running )
{
tcpcam_gtk_display_stop( display );
}
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static
void da_size_allocate( GtkWidget *da, GtkAllocation *allocation, TcpcamGtkDisplay * display )
{
}
static
void gtk_video_display_init( TcpcamGtkDisplay *display )
{
display->backend_fourcc = 0;
display->new_frame_callback = NULL;
gtk_aspect_frame_set( GTK_ASPECT_FRAME( display ), 0.5, 0.5, 1.0, TRUE );
gtk_frame_set_shadow_type( GTK_FRAME( display ), GTK_SHADOW_NONE );
display->drawing_area = gtk_drawing_area_new();
drawing_area = display->drawing_area;
gtk_widget_add_events( display->drawing_area,
GDK_ALL_EVENTS_MASK );
gtk_container_add(GTK_CONTAINER( display ), display->drawing_area );
gtk_widget_show( display->drawing_area );
g_signal_connect( display->drawing_area, "hierarchy-changed",
G_CALLBACK( da_hierarchy_changed_cb ), display );
g_signal_connect( display->drawing_area, "configure-event",
G_CALLBACK( da_configure_cb ),
display );
g_signal_connect( display->drawing_area, "unmap",
G_CALLBACK(gtk_widget_destroyed),
&display->gc );
g_signal_connect( display->drawing_area, "expose-event",
G_CALLBACK( gtk_video_display_expose),
display );
g_signal_connect( display->drawing_area, "size-allocate",
G_CALLBACK( da_size_allocate ),
display );
display->display_timeout_tag = TIMEOUT_UNSET;
g_printf("\ngtk_video_display_init end\n");
}
/**
* tcpcam_gtk_display_new:
*
* Creates a new GtkVideoDisplay
*
* Returns: a new #GtkVideoDisplay
*/
GtkWidget* tcpcam_gtk_display_new( void )
{
return GTK_WIDGET(g_object_new(TCPCAM_GTK_DISPLAY_TYPE, NULL ));
}
static void da_hierarchy_changed_cb( GtkWidget *da, GtkWidget *widget2, TcpcamGtkDisplay *display )
{
GtkWidget *window;
window = gtk_widget_get_toplevel( da );
if( window )
{
g_signal_connect( G_OBJECT( window ), "configure-event", G_CALLBACK( tlwindow_configure_event ), display );
}
}
static gboolean tlwindow_configure_event( GtkWidget *window, GdkEventConfigure *event, TcpcamGtkDisplay *display )
{
gtk_widget_queue_draw( GTK_WIDGET(display) );
return FALSE;
}
static void da_configure_cb ( GtkWidget *da, GdkEventConfigure *event, TcpcamGtkDisplay *display )
{
}
static void gtk_video_display_realize (GtkWidget *widget)
{
TcpcamGtkDisplay *display;
GdkWindowAttr attributes;
gint attributes_mask;
puts ("before sdl realize");
g_return_if_fail (widget != NULL);
g_return_if_fail (TCPCAM_IS_GTK_DISPLAY (widget));
display = TCPCAM_GTK_DISPLAY(widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
gdk_window_set_user_data (widget->window, display);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
gtk_video_display_send_configure (TCPCAM_GTK_DISPLAY(widget));
puts ("after sdl realize");
}
static void gtk_video_display_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
puts ("before sdl size allocate");
g_return_if_fail (widget != NULL);
g_return_if_fail (TCPCAM_IS_GTK_DISPLAY (widget));
g_return_if_fail (allocation != NULL);
widget->allocation = *allocation;
/* FIXME, TODO-1.3: back out the MAX() statements */
widget->allocation.width = MAX (1, widget->allocation.width);
widget->allocation.height = MAX (1, widget->allocation.height);
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
gtk_video_display_send_configure (TCPCAM_GTK_DISPLAY (widget));
}
puts ("after sdl size allocate");
}
static void gtk_video_display_send_configure (TcpcamGtkDisplay *display)
{
GtkWidget *widget;
GdkEventConfigure event;
puts ("before sdl send configure");
widget = GTK_WIDGET (display);
event.type = GDK_CONFIGURE;
event.window = widget->window;
event.send_event = TRUE;
event.x = widget->allocation.x;
event.y = widget->allocation.y;
event.width = widget->allocation.width;
event.height = widget->allocation.height;
gtk_widget_event (widget, (GdkEvent*) &event);
puts ("after sdl send configure");
}
static void gtk_display_drawing_area_attach (TcpcamGtkDisplay *display)
{
puts ("before sdl surface attach");
/* Attach the SDL_Surface */
puts ("attaching the surface");
puts ("after sdl surface attach");
}
static gint gtk_video_display_expose (GtkWidget *widget, GdkEventExpose *event)
{
TcpcamGtkDisplay *display;
puts ("before sdl expose");
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (TCPCAM_IS_GTK_DISPLAY(widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (event->count > 0) return FALSE;
display = (TcpcamGtkDisplay *)widget;
if (!display->drawing_area)
{
gtk_display_drawing_area_attach (TCPCAM_GTK_DISPLAY(widget));
}
gtk_video_display_update ( TCPCAM_GTK_DISPLAY(widget) );
puts ("after sdl expose");
printf ("display is : %p\n", display->drawing_area);
return FALSE;
}
static void gtk_video_display_update (TcpcamGtkDisplay *display)
{
puts ("before sdl display update");
g_return_if_fail (display != NULL);
g_return_if_fail (TCPCAM_IS_GTK_DISPLAY(display));
g_return_if_fail (display->drawing_area);
GdkGC *gc = display->drawing_area->style->fg_gc[GTK_WIDGET_STATE(display->drawing_area)];
GdkDrawable *drawable = display->drawing_area->window;
GdkColor color;
color.green = 0;
color.blue = 65535;
gdk_gc_set_rgb_fg_color(gc, &color);
gdk_draw_rectangle(drawable, gc, TRUE, 10, 80, 100, 50);
puts ("after display update");
}
/**
* tcpcam_gtk_video_display_start:
* @display: an #TcpcamGtkDisplay
*
* Calls #tcpcam_start_capture on the device and starts displaying the
* live video stream.
*
* Returns: TRUE when the live display could be successfully started.
*/
gboolean tcpcam_gtk_display_start( TcpcamGtkDisplay *display )
{
tcpcam_format_t tmp_format;
printf("%s start\n", __FUNCTION__);
if( display->capture_running )
{
/* g_warning( "video_display_start: Display already started!\n" ); */
return TRUE;
}
if( display->display_timeout_tag != TIMEOUT_UNSET )
{
g_source_remove( display->display_timeout_tag );
display->display_timeout_tag = TIMEOUT_UNSET;
}
if( display->still_image_buffer.data ) //
{
free( display->still_image_buffer.data );
display->still_image_buffer.data = NULL;
}
if( !strcmp( display->format.identifier, "" ) )
{
/* g_warning( "Video format not set" ); */
return FALSE;
}
display->capture_running = TRUE;
tmp_format.buffer_type = TCPCAM_BUFFER_TYPE_SYSTEM;
display->disp_time.tv_sec = 0;
display->disp_time.tv_usec = 0;
display->display_timeout_tag = g_timeout_add( 30, (GtkFunction)gtk_video_display_update, display );
display->pause = FALSE;
printf("%s end\n", __FUNCTION__);
return TRUE;
}
/**
* tcpcam_gtk_display_stop:
* @display: an #TcpcamGtkDisplay
*
* Calls #tcpcam_stop_capture on the device and stops displaying the
* live video image.
*/
void tcpcam_gtk_display_stop( TcpcamGtkDisplay *display )
{
return;
}
/**
* tcpcam_gtk_display_set_format:
* @display: an #TcpcamGtkDisplay
* @format_spec: a #tcpcam_format_t
*
* Returns: TRUE when the format change was successfull.
*/
gboolean tcpcam_gtk_display_set_format( TcpcamGtkDisplay *display,
tcpcam_format_t *format_spec)
{
printf("%s start\n", __FUNCTION__);
tcpcam_format_t format;
gboolean old_capture_state;
gboolean status = TRUE;
format.size.x = format_spec->size.x;
format.size.y = format_spec->size.y;
format.size.width = format_spec->size.width;
format.size.height = format_spec->size.height;
display->format.size.x = format.size.x;
display->format.size.y = format.size.y;
display->format.size.width = format.size.width;
display->format.size.height = format.size.height;
printf("%s end\n", __FUNCTION__);
return status;
}
/**
* tcpcam_gtk_video_display_set_size:
* @display: an #TcpcamGtkDisplay
* @width: new width
* @height: new height
*
* Sets the output size of the display. Video data that is to be
* displayed will be scaled to this size.
*/
void tcpcam_gtk_display_set_size(TcpcamGtkDisplay *display,
gint width, gint height )
{
display->display_width = width;
display->display_height = height;
} |
|