Commit f7c7a5c3 authored by Claes Sjofors's avatar Claes Sjofors

Xtt camera, connection down detection with reconnect added

parent 105bc30d
...@@ -188,11 +188,31 @@ SObject pwrb:Class ...@@ -188,11 +188,31 @@ SObject pwrb:Class
Attr Flags |= PWR_MASK_DEVHIDEVALUE Attr Flags |= PWR_MASK_DEVHIDEVALUE
EndBody EndBody
EndObject EndObject
!/**
! Connection timeout.
!*/
Object ConnectionTimeout $Attribute 17
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
!/**
! Reconnect time.
! If the connection is down, a reconnect will be made
! cyclically with this interval.
!*/
Object ReconnectTime $Attribute 18
Body SysBody
Attr TypeRef = "pwrs:Type-$Float32"
EndBody
EndObject
EndObject EndObject
Object Template XttCamera Object Template XttCamera
Body RtBody Body RtBody
Attr Width = 800 Attr Width = 800
Attr Height = 600 Attr Height = 600
Attr ConnectionTimeout = 10
Attr ReconnectTime = 5
EndBody EndBody
EndObject EndObject
EndObject EndObject
......
...@@ -93,15 +93,43 @@ static GstBusSyncReply bus_sync_handler (GstBus * bus, GstMessage * message, ...@@ -93,15 +93,43 @@ static GstBusSyncReply bus_sync_handler (GstBus * bus, GstMessage * message,
void XttStreamGtk::realize_cb( GtkWidget *widget, void *data) void XttStreamGtk::realize_cb( GtkWidget *widget, void *data)
{ {
XttStreamGtk *strm = (XttStreamGtk *)data; XttStreamGtk *strm = (XttStreamGtk *)data;
GdkWindow *window = gtk_widget_get_window( strm->video_form);
guintptr window_handle; guintptr window_handle;
if (!gdk_window_ensure_native (window)) GstElement *videosink;
g_error ("Couldn't create native window needed for GstXOverlay!"); g_object_get( strm->playbin2, "video-sink", &videosink, NULL);
GdkWindow *window = gtk_widget_get_window( strm->video_form);
// if (!gdk_window_ensure_native (window))
// g_error ("Couldn't create native window needed for GstXOverlay!");
window_handle = GDK_WINDOW_XID( window); window_handle = GDK_WINDOW_XID( window);
gst_x_overlay_set_xwindow_id( GST_X_OVERLAY (strm->playbin2), window_handle); gst_x_overlay_set_xwindow_id( GST_X_OVERLAY (videosink), window_handle);
}
void XttStreamGtk::source_setup_cb( GstElement *playbin2, GstElement *src, gpointer data)
{
XttStreamGtk *strm = (XttStreamGtk *)data;
// Set timeout for connection
GstElement *source;
guint tmo = (int) (strm->connection_timeout + 0.5);
g_object_get( strm->playbin2, "source", &source, NULL);
g_object_set( source, "timeout", tmo, NULL);
// If the connections has been down, overlay has to be set again
GstElement *videosink;
guintptr window_handle;
g_object_get( strm->playbin2, "video-sink", &videosink, NULL);
if ( videosink) {
GdkWindow *window = gtk_widget_get_window( strm->video_form);
window_handle = GDK_WINDOW_XID( window);
gst_x_overlay_set_xwindow_id( GST_X_OVERLAY (videosink), window_handle);
}
} }
/* This function is called when the PLAY button is clicked */ /* This function is called when the PLAY button is clicked */
...@@ -148,18 +176,7 @@ gboolean XttStreamGtk::expose_cb( GtkWidget *widget, GdkEventExpose *event, void ...@@ -148,18 +176,7 @@ gboolean XttStreamGtk::expose_cb( GtkWidget *widget, GdkEventExpose *event, void
XttStreamGtk *strm = (XttStreamGtk *)data; XttStreamGtk *strm = (XttStreamGtk *)data;
if (strm->state < GST_STATE_PAUSED) { if (strm->state < GST_STATE_PAUSED) {
GtkAllocation allocation; strm->erase_window();
GdkWindow *window = gtk_widget_get_window( widget);
cairo_t *cr;
/* Cairo is a 2D graphics library which we use here to clean the video window.
* It is used by GStreamer for other reasons, so it will always be available to us. */
gtk_widget_get_allocation( widget, &allocation);
cr = gdk_cairo_create (window);
cairo_set_source_rgb( cr, 0, 0, 0);
cairo_rectangle( cr, 0, 0, allocation.width, allocation.height);
cairo_fill( cr);
cairo_destroy( cr);
} }
return FALSE; return FALSE;
...@@ -213,6 +230,22 @@ void XttStreamGtk::refresh_ui( XttStreamGtk *strm) ...@@ -213,6 +230,22 @@ void XttStreamGtk::refresh_ui( XttStreamGtk *strm)
} }
void XttStreamGtk::erase_window()
{
GtkAllocation allocation;
GdkWindow *window = gtk_widget_get_window( video_form);
cairo_t *cr;
/* Cairo is a 2D graphics library which we use here to clean the video window.
* It is used by GStreamer for other reasons, so it will always be available to us. */
gtk_widget_get_allocation( video_form, &allocation);
cr = gdk_cairo_create (window);
cairo_set_source_rgb( cr, 0, 0, 0);
cairo_rectangle( cr, 0, 0, allocation.width, allocation.height);
cairo_fill( cr);
cairo_destroy( cr);
}
void XttStreamGtk::refresh( void *data) void XttStreamGtk::refresh( void *data)
{ {
XttStreamGtk *strm = (XttStreamGtk *)data; XttStreamGtk *strm = (XttStreamGtk *)data;
...@@ -222,6 +255,52 @@ void XttStreamGtk::refresh( void *data) ...@@ -222,6 +255,52 @@ void XttStreamGtk::refresh( void *data)
strm->timerid->add( strm->scan_time, strm->refresh, data); strm->timerid->add( strm->scan_time, strm->refresh, data);
} }
void XttStreamGtk::reconnect( void *data)
{
XttStreamGtk *strm = (XttStreamGtk *)data;
GstState state, async;
GstStateChangeReturn ch = gst_element_get_state( strm->playbin2, &state, &async, 0);
printf( "Try to reconnect %d %d %d\n", state, async, ch);
if ( state == GST_STATE_PLAYING)
return;
printf( "Adding reconnect\n");
strm->reconnect_timerid->remove();
strm->reconnect_timerid->add( int( strm->reconnect_time * 1000), reconnect, strm);
if ( strm->no_uri) {
printf( "Reconnect no URI\n");
strm->no_uri = 0;
pwr_tURL luri;
char *s;
if ( strm->options & strm_mOptions_HttpBasicAuthentication) {
if ( strcmp( strm->user, "") != 0 && strcmp( strm->password, "") != 0 && (s = strstr( strm->uri, "://"))) {
unsigned long int offs = s - (char *)strm->uri + 3;
strncpy( luri, strm->uri, offs);
luri[offs] = 0;
strcat( luri, strm->user);
strcat( luri, ":");
strcat( luri, strm->password);
strcat( luri, "@");
strcat( luri, &strm->uri[offs]);
}
else
strcpy( luri, strm->uri);
}
else if ( strm->options & strm_mOptions_CgiParameterAuthentication)
snprintf( luri, sizeof(luri), "%s?user=%s&pwd=%s", strm->uri, strm->user, strm->password);
else
strcpy( luri, strm->uri);
g_object_set( strm->playbin2, "uri", luri, NULL);
}
else
gst_element_set_state( strm->playbin2, GST_STATE_PLAYING);
}
/* This function is called when new metadata is discovered in the stream */ /* This function is called when new metadata is discovered in the stream */
void XttStreamGtk::tags_cb( GstElement *playbin2, gint stream, void *data) void XttStreamGtk::tags_cb( GstElement *playbin2, gint stream, void *data)
{ {
...@@ -244,16 +323,28 @@ void XttStreamGtk::error_cb( GstBus *bus, GstMessage *msg, void *data) ...@@ -244,16 +323,28 @@ void XttStreamGtk::error_cb( GstBus *bus, GstMessage *msg, void *data)
GError *err; GError *err;
gchar *debug_info; gchar *debug_info;
printf( "Message %d\n", GST_MESSAGE_TYPE(data)); printf( "Message %d\n", GST_MESSAGE_TYPE(msg));
/* Print error details on the screen */ /* Print error details on the screen */
gst_message_parse_error( msg, &err, &debug_info); gst_message_parse_error( msg, &err, &debug_info);
printf( "Error received from element %s: %s\n", GST_OBJECT_NAME( msg->src), err->message); printf( "Error received from element %s: %s\n", GST_OBJECT_NAME( msg->src), err->message);
printf( "Debugging information: %s\n", debug_info ? debug_info : "none"); printf( "Debugging information: %s\n", debug_info ? debug_info : "none");
if ( strcmp( err->message, "No URI set") == 0)
strm->no_uri = 1;
g_clear_error( &err); g_clear_error( &err);
g_free( debug_info); g_free( debug_info);
/* Set the pipeline to READY (which stops playback) */ /* Set the pipeline to READY (which stops playback) */
gst_element_set_state( strm->playbin2, GST_STATE_READY); gst_element_set_state( strm->playbin2, GST_STATE_READY);
// Erase window
strm->erase_window();
// Try to reconnect
strm->reconnect_timerid->remove();
strm->reconnect_timerid->add( int(strm->reconnect_time * 1000), reconnect, strm);
break; break;
} }
case GST_MESSAGE_BUFFERING: { case GST_MESSAGE_BUFFERING: {
...@@ -597,7 +688,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -597,7 +688,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
int width, int height, int x, int y, double scan_time, int width, int height, int x, int y, double scan_time,
unsigned int st_options, int st_embedded, pwr_tAttrRef *st_arp, pwr_tStatus *sts) : unsigned int st_options, int st_embedded, pwr_tAttrRef *st_arp, pwr_tStatus *sts) :
XttStream( st_parent_ctx, name, st_uri, width, height, x, y, scan_time, st_options, st_embedded, st_arp), XttStream( st_parent_ctx, name, st_uri, width, height, x, y, scan_time, st_options, st_embedded, st_arp),
scroll_cnt(0), ptz_box_displayed(0), is_live(0), buftime(pwr_cNTime), parent_wid(st_parent_wid), ptz_box(0) scroll_cnt(0), ptz_box_displayed(0), is_live(0), buftime(pwr_cNTime), parent_wid(st_parent_wid), ptz_box(0), reconnect_timerid(0), no_uri(0)
{ {
GstStateChangeReturn ret; GstStateChangeReturn ret;
GstBus *bus; GstBus *bus;
...@@ -657,6 +748,8 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -657,6 +748,8 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
g_signal_connect( G_OBJECT( playbin2), "audio-tags-changed",( GCallback) tags_cb, this); g_signal_connect( G_OBJECT( playbin2), "audio-tags-changed",( GCallback) tags_cb, this);
g_signal_connect( G_OBJECT( playbin2), "text-tags-changed",( GCallback) tags_cb, this); g_signal_connect( G_OBJECT( playbin2), "text-tags-changed",( GCallback) tags_cb, this);
g_signal_connect( G_OBJECT( playbin2), "source-setup",( GCallback) source_setup_cb, this);
if ( !embedded) { if ( !embedded) {
toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL); toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect( G_OBJECT(toplevel), "delete-event", G_CALLBACK(delete_event_cb), this); g_signal_connect( G_OBJECT(toplevel), "delete-event", G_CALLBACK(delete_event_cb), this);
...@@ -670,6 +763,9 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -670,6 +763,9 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
else else
toplevel = parent_wid; toplevel = parent_wid;
GstElement *x_overlay = gst_element_factory_make( "xvimagesink", "videosink");
g_object_set( G_OBJECT(playbin2), "video-sink", x_overlay, NULL);
video_form = gtk_drawing_area_new(); video_form = gtk_drawing_area_new();
gtk_widget_set_double_buffered( video_form, FALSE); gtk_widget_set_double_buffered( video_form, FALSE);
g_signal_connect( video_form, "realize", G_CALLBACK( realize_cb), this); g_signal_connect( video_form, "realize", G_CALLBACK( realize_cb), this);
...@@ -682,6 +778,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -682,6 +778,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
gtk_widget_add_events( video_form, GDK_BUTTON_PRESS_MASK | gtk_widget_add_events( video_form, GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK); GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK);
// GtkWidget *controls; // GtkWidget *controls;
GtkWidget *hbox = gtk_hbox_new( FALSE, 0); GtkWidget *hbox = gtk_hbox_new( FALSE, 0);
if ( options & strm_mOptions_VideoControlPanel) { if ( options & strm_mOptions_VideoControlPanel) {
...@@ -1000,8 +1097,8 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -1000,8 +1097,8 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
gtk_container_add( GTK_CONTAINER( toplevel), main_box); gtk_container_add( GTK_CONTAINER( toplevel), main_box);
gtk_window_set_default_size( GTK_WINDOW( toplevel), width, height); gtk_window_set_default_size( GTK_WINDOW( toplevel), width, height);
gtk_widget_show_all( toplevel); gtk_widget_show_all( toplevel);
if ( ptz_box) if ( ptz_box)
g_object_set( ptz_box, "visible", FALSE, NULL); g_object_set( ptz_box, "visible", FALSE, NULL);
if ( !(options & strm_mOptions_CameraControlPanel)) if ( !(options & strm_mOptions_CameraControlPanel))
...@@ -1050,6 +1147,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -1050,6 +1147,7 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
wow = new CoWowGtk( toplevel); wow = new CoWowGtk( toplevel);
timerid = wow->timer_new(); timerid = wow->timer_new();
scroll_timerid = wow->timer_new(); scroll_timerid = wow->timer_new();
reconnect_timerid = wow->timer_new();
timerid->add( scan_time, refresh, this); timerid->add( scan_time, refresh, this);
*sts = XNAV__SUCCESS; *sts = XNAV__SUCCESS;
...@@ -1057,8 +1155,12 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const ...@@ -1057,8 +1155,12 @@ XttStreamGtk::XttStreamGtk( GtkWidget *st_parent_wid, void *st_parent_ctx, const
XttStreamGtk::~XttStreamGtk() XttStreamGtk::~XttStreamGtk()
{ {
timerid->remove(); if ( timerid)
scroll_timerid->remove(); timerid->remove();
if ( scroll_timerid)
scroll_timerid->remove();
if ( reconnect_timerid)
reconnect_timerid->remove();
gst_element_set_state( playbin2, GST_STATE_NULL); gst_element_set_state( playbin2, GST_STATE_NULL);
gst_object_unref( playbin2); gst_object_unref( playbin2);
......
...@@ -81,6 +81,8 @@ class XttStreamGtk : public XttStream { ...@@ -81,6 +81,8 @@ class XttStreamGtk : public XttStream {
GtkWidget *tools; GtkWidget *tools;
void *overlay; void *overlay;
CoWowTimer *reconnect_timerid;
int no_uri;
static int gst_initialized; static int gst_initialized;
...@@ -94,6 +96,7 @@ class XttStreamGtk : public XttStream { ...@@ -94,6 +96,7 @@ class XttStreamGtk : public XttStream {
void setup(); void setup();
void *get_widget() { return main_box;} void *get_widget() { return main_box;}
void create_popup_menu( int x, int y); void create_popup_menu( int x, int y);
void erase_window();
static void scroll_cb( void *data); static void scroll_cb( void *data);
static void refresh( void *data); static void refresh( void *data);
...@@ -114,7 +117,9 @@ class XttStreamGtk : public XttStream { ...@@ -114,7 +117,9 @@ class XttStreamGtk : public XttStream {
static void state_changed_cb( GstBus *bus, GstMessage *msg, void *data); static void state_changed_cb( GstBus *bus, GstMessage *msg, void *data);
static void application_cb( GstBus *bus, GstMessage *msg, void *data); static void application_cb( GstBus *bus, GstMessage *msg, void *data);
static void resize_cb( GtkWidget *w, GtkAllocation *allocation, gpointer data); static void resize_cb( GtkWidget *w, GtkAllocation *allocation, gpointer data);
static void source_setup_cb( GstElement *playbin2, GstElement *src, gpointer data);
static gboolean mousebutton_cb( GtkWidget *widget, GdkEvent *event, void *data); static gboolean mousebutton_cb( GtkWidget *widget, GdkEvent *event, void *data);
static void reconnect( void *data);
static void menu_position_func( GtkMenu *menu, gint *x, gint *y, gboolean *push_in, static void menu_position_func( GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
gpointer data); gpointer data);
static void activate_zoomreset( GtkWidget *w, gpointer data); static void activate_zoomreset( GtkWidget *w, gpointer data);
......
...@@ -117,6 +117,30 @@ XttStream::XttStream( void *st_parent_ctx, const char *name, const char *st_uri, ...@@ -117,6 +117,30 @@ XttStream::XttStream( void *st_parent_ctx, const char *name, const char *st_uri,
if ( EVEN(sts)) if ( EVEN(sts))
strcpy( user, ""); strcpy( user, "");
pwr_tFloat32 tmo;
sts = gdh_ArefANameToAref( &aref, "ConnectionTimeout", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &tmo, sizeof(tmo));
if ( ODD(sts)) {
connection_timeout = tmo;
if ( connection_timeout < 1)
connection_timeout = 10;
}
else
connection_timeout = 10;
pwr_tFloat32 time;
sts = gdh_ArefANameToAref( &aref, "ReconnectTime", &aaref);
if ( ODD(sts))
sts = gdh_GetObjectInfoAttrref( &aaref, &time, sizeof(time));
if ( ODD(sts)) {
reconnect_time = time;
if ( connection_timeout < 1)
reconnect_time = 5;
}
else
reconnect_time = 5;
if ( strcmp( user, "") != 0 && strcmp( password, "") != 0) { if ( strcmp( user, "") != 0 && strcmp( password, "") != 0) {
// sprintf( &uri[strlen(uri)], "?user=%s&pwd=%s", user, password); // sprintf( &uri[strlen(uri)], "?user=%s&pwd=%s", user, password);
} }
......
...@@ -118,6 +118,8 @@ class XttStream { ...@@ -118,6 +118,8 @@ class XttStream {
XttCameraControl *camera_control; XttCameraControl *camera_control;
pwr_tEnum control_protocol; pwr_tEnum control_protocol;
pwr_tAttrRef aref; pwr_tAttrRef aref;
float connection_timeout;
float reconnect_time;
XttStream( void *st_parent_ctx, const char *name, const char *st_uri, XttStream( void *st_parent_ctx, const char *name, const char *st_uri,
int st_width, int st_height, int x, int y, int st_width, int st_height, int x, int y,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment