GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Oct 31, 2014 4:31 pm

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Pixbuf memory issues
PostPosted: Fri Apr 26, 2013 4:56 pm 
Offline

Joined: Tue Apr 23, 2013 10:44 pm
Posts: 4
Hello Forum members, I am new (to both this BB and GTK) thank you for accepting me into your online community.

I apologize if the following problem has been discussed previously - I'm on week two trying to resolve an issue in the (should be trivial) application I am building, but have been unable to figure out what it is I am doing (or not doing) incorrectly.

Let me briefly explain my application and it's purpose: Basically the 'client side' of the application receives JPEG image data via a buffer over a UDP socket from the 'server side'. My 'client side' application makes use of ghbcompositor from the handbrake project in order to layer widgets (this all works great). The socket communications operate within their own thread, I intend to eventually have it chunk the image data (split it into smaller pieces and re-assemble) and incorporate a basic protocol for ACK'ing packets, but for now my receive simply (attempts to) take the image data, the length of data, and it's 'image number', and gives that to pixbuf_loader. The resulting pixbuf is then displayed in a GtkImage which is in the bottom layer of my composited layering of widgets. This all works. The image is displayed, it updates, until the application gets KILLED because it has eaten all the memory in the system (this happens fairly quickly). In addition I have an event handler that resizes the displayed image when the user resizes the window by it's handles, or by maximizing the window. This is done via 'scale_simple' and also works (but also causes a memory leak and eventually my app is killed).

I've read several posts regarding references to pixbuf's and have tried gdk_pixbuf_unref, and g_object_unref at various points in my application code, seemingly with no effect. I guess I'm a bit foggy on how resources are retained and cleared with regard to pixbuf loader and scale_simple operations.

I will post my code when I arrive at work and maybe someone who has more experience with regard to the matter can shed some light on what I am doing incorrectly.


Top
 Profile  
 
 Post subject: Re: Pixbuf memory issues
PostPosted: Fri Apr 26, 2013 5:06 pm 
Offline

Joined: Tue Apr 23, 2013 10:44 pm
Posts: 4
Code:
/*
* GUI TEST
* This version attempts to receive an image over UDP from rccar_com
* in a seperate thread and shows it in the GTK image 'cam_widget'
*
* compile command:
*
* gcc gui_test.c -o gui_test `pkg-config --libs --cflags gtk+-3.0`
*
*/

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf-loader.h>
#include <vlc/vlc.h>
#include <gdk/gdkx.h>
#include <stdbool.h>
#include <pthread.h>
#include "ghbcompositor.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "../common.h"
#include "../lib.h"
#define BUFFER_LENGTH    32000
#define FALSE              0
#define SERVER_NAME     "127.0.0.1"

bool winismaximized = false;
bool hudisvisible= true;
bool up_on=false;
bool left_on=false;
bool right_on=false;
bool down_on=false;
bool DIREC_changed=false;
gboolean
print_DIREC(int);
int    sd, rc;
char   server[256];
unsigned char   buffer[BUFFER_LENGTH];
unsigned char   *udp_cam_img;
struct hostent *hostp;
struct sockaddr_in serveraddr;
struct GError *ger;
struct GError *ger2;
struct GError *ger3;
FILE *outfile;
int    serveraddrlen = sizeof(serveraddr);


pthread_t udp_camimg;

gboolean on_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
gboolean on_key_release (GtkWidget *widget, GdkEventKey *event, gpointer user_data);
gboolean on_double_click(GtkWidget *widget, GdkEventButton *gdk_event, GtkWidget *widget2);
unsigned int DIREC = 0;
void* get_cam_stream(void*);
gboolean resize_cam_image(GtkWidget *widget, GdkEvent *event,GtkWidget *window);
gboolean set_cam_image(GtkWidget *window, GtkWidget *widget,GdkPixbuf *pixbuf);
gboolean draw_img(GtkWidget *window, GdkEvent *event,GtkWidget *cam_widget);
gboolean zerosize_cam_image(GtkWidget *widget);
/* -----  */
GtkWidget *window;
GtkWidget *event_box;
GtkWidget *cam_widget;
GtkWidget *blender;

    GtkWidget *eb_bottom;
    GtkWidget *eb_top1;
    GtkWidget *eb_top2;
    GtkWidget *eb_top3;
    GtkWidget *top1;
    GtkWidget *top2;
    GtkWidget *top3;
    GtkWidget *table;
    GtkWidget *m_batt;
    GtkWidget *m_batt_align;
GtkAllocation alloc;
GtkWidget   *s_window;
GdkPixbufLoader *loader;


GtkWidget *cam_holder;
void destroy (GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
exit(1);
}
int main (int argc, char *argv[])
{
g_thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
GdkColor color_black;
gdk_color_parse("black", &color_black);
gtk_init (&argc, &argv);
s_window = gtk_scrolled_window_new(0,0);
gtk_scrolled_window_set_policy(s_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(s_window,GTK_SHADOW_NONE);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
event_box=gtk_event_box_new();
cam_widget=gtk_image_new_from_file("./img/colorbars.png");
eb_bottom = gtk_event_box_new();
eb_top1 = gtk_event_box_new();
eb_top2 = gtk_event_box_new();
eb_top3 = gtk_event_box_new();
blender = ghb_compositor_new();
cam_holder=gtk_viewport_new(0,0);
gtk_window_set_default_size(GTK_WINDOW(window), 640, 360);
gtk_window_set_title(GTK_WINDOW(window), "RCCAR GUI");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);
g_signal_connect (G_OBJECT (window), "key_press_event", G_CALLBACK (on_key_press), NULL);
g_signal_connect (G_OBJECT (window), "key_release_event", G_CALLBACK (on_key_release), NULL);
g_signal_connect (G_OBJECT (eb_bottom), "button_press_event", G_CALLBACK(on_double_click), G_OBJECT(window));
g_signal_connect (G_OBJECT (window), "size-allocate", G_CALLBACK(resize_cam_image),(gpointer)cam_widget);
/* Create an EventBox and add it to our toplevel window */

gtk_container_add (GTK_CONTAINER(eb_bottom),s_window);
//gtk_scrolled_window_add_with_viewport(GTK_CONTAINER(s_window),cam_widget);
gtk_container_add (GTK_CONTAINER(s_window),cam_widget);
//gtk_container_add (GTK_CONTAINER(cam_holder),cam_widget);
m_batt=gtk_image_new_from_file("./img/m_batt_4bar.png");
m_batt_align=gtk_alignment_new(1,0,0,0);
gtk_event_box_set_visible_window(eb_top1,false);
top2 = gtk_button_new_with_label("Top 2");
top3 = gtk_button_new_with_label("Top 3");

    // The buttons must be placed inside an event box since
    // buttons do not have their own window.
gtk_container_add(GTK_CONTAINER(m_batt_align),m_batt);
gtk_container_add(GTK_CONTAINER(eb_top1), m_batt_align);
//gtk_container_add(GTK_CONTAINER(eb_top2), top2);
//gtk_container_add(GTK_CONTAINER(eb_top3), top3);

    // Create the table that will be the top layer
    // Using a layout widget gives flexibility in the layout of the layer
table = gtk_table_new(6, 3, TRUE);
gtk_table_set_row_spacing (GTK_TABLE(table), 0, 0);
gtk_table_set_col_spacing(GTK_TABLE(table),0,0);
/*  guint left_attach,guint right_attach,guint top_attach,guint bottom_attach,GtkAttachOptions xoptions,  GtkAttach, Options yoptions, guint xpadding,guint ypadding); */
gtk_table_attach(GTK_TABLE(table), eb_top1, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
//    gtk_table_attach(GTK_TABLE(table), eb_top2, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
//    gtk_table_attach(GTK_TABLE(table), eb_top3, 2, 3, 2, 3, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
gtk_container_add(GTK_CONTAINER(window), blender);
ghb_compositor_zlist_insert(GHB_COMPOSITOR(blender), eb_bottom, 1, 1);
ghb_compositor_zlist_insert(GHB_COMPOSITOR(blender), table, 2, 0.4);

gtk_widget_modify_fg(window, GTK_STATE_NORMAL, &color_black);
gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color_black);
gtk_widget_modify_fg(s_window, GTK_STATE_NORMAL, &color_black);
gtk_widget_modify_bg(s_window, GTK_STATE_NORMAL, &color_black);
gtk_widget_show (event_box);
gtk_widget_show_all (window);
printf("THREAD:UDP Creating UDP SOCKET thread for cam img 1\n");
  if (pthread_create(&udp_camimg, NULL, get_cam_stream,NULL)!=0){
        perror("pthread_error");
    }
gtk_main ();
gdk_threads_leave ();
int ret3=pthread_join(udp_camimg, NULL);
return 0;
}
gboolean resize_cam_image(GtkWidget *window,GdkEvent *event, GtkWidget *cam_widget){
GdkPixbuf *pixbuf;
//printf("WIN ALLOC:");
gtk_widget_get_allocation(window, &alloc);
//printf("RESIZE IMG: %i %i\n",alloc.width, alloc.height);
pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(cam_widget));
//if(pixbuf==NULL){g_printerr("Failed to resize image\n");return 1;}
pixbuf=gdk_pixbuf_scale_simple(pixbuf,alloc.width,alloc.height,GDK_INTERP_NEAREST); /*GDK_INTERP_BILINEAR GDK_INTERP_NEAREST */
gtk_image_set_from_pixbuf(cam_widget,pixbuf);
gtk_widget_queue_draw(cam_widget);
pixbuf=NULL;
free(pixbuf);
return FALSE;
}
void* get_cam_stream(void* arg){
GdkPixbuf *pixbuf_in;
do
   {printf("in get cam stream\n");
sd = socket(AF_INET, SOCK_DGRAM, 0);if (sd < 0){perror("socket() failed");break;}
      strcpy(server, SERVER_NAME);
      memset(&serveraddr, 0, sizeof(serveraddr));
         serveraddr.sin_family      = AF_INET;
         serveraddr.sin_port        = htons(RCCAR_UDP_INET_PORT);
         serveraddr.sin_addr.s_addr = inet_addr(server);
         if (serveraddr.sin_addr.s_addr == (unsigned long)INADDR_NONE)
      {
         hostp = gethostbyname(server);
         if (hostp == (struct hostent *)NULL)
         {
            printf("Host not found --> ");
            printf("h_errno = %d\n", h_errno);
            break;
         }

         memcpy(&serveraddr.sin_addr,
                hostp->h_addr,
                sizeof(serveraddr.sin_addr));
      }

memset(buffer, 0, sizeof(buffer));
buffer[0]=229;buffer[1]=129;
rc = sendto(sd, buffer, sizeof(buffer), 0,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
      if (rc < 0){perror("sendto() failed");break;}
int outlen;
int img_num;
int img_complete;
rc = recvfrom(sd, buffer, sizeof(buffer), 0,(struct sockaddr *)&serveraddr,&serveraddrlen);
      if (rc < 0){perror("recvfrom() failed");break;}
      printf("client received the following: <%s>\n", buffer);
      printf("from port %d, from address %s\n",ntohs(serveraddr.sin_port),inet_ntoa(serveraddr.sin_addr));
for (;;){
loader=gdk_pixbuf_loader_new_with_type("jpeg",NULL);
outlen=0;
img_num=0;
img_complete=0;
rc = recvfrom(sd, buffer, sizeof(buffer), 0,(struct sockaddr *)&serveraddr,&serveraddrlen);
//printf("client received the following: <%s>  LEN:%i\n", buffer,sizeof(buffer));
//printf("from port %d, from address %s\n",ntohs(serveraddr.sin_port),inet_ntoa(serveraddr.sin_addr));
outlen=(buffer[3]*256) + buffer[2];
img_num=(buffer[1]*256)+buffer[0];
img_complete=buffer[4];
//printf("img_num:%i outlen:%i complete:%i\n",img_num,outlen,img_complete);
//printf("raw:  %i %i %i %i %i\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
gdk_threads_enter();
if ((gdk_pixbuf_loader_write(loader,buffer+5,outlen,NULL))==TRUE){
gdk_pixbuf_loader_close(loader,NULL);
pixbuf_in = gdk_pixbuf_loader_get_pixbuf(loader);
gtk_image_set_from_pixbuf(cam_widget,pixbuf_in);
gtk_widget_queue_draw(cam_widget);
//free(pixbuf_in);
g_object_unref(pixbuf_in);
loader=NULL;
gdk_threads_leave();
}else{printf("GDK_LOADER:encountered a problem\n");}
}
      /********************************************************************/
      /* Program complete                        gtkimage from file descritor                         */
      /********************************************************************/

   } while (FALSE);

   /***********************************************************************/
   /* Close down any open socket descriptors                              */
   /***********************************************************************/
   if (sd != -1)
      close(sd);
}
gboolean on_double_click(GtkWidget *widget, GdkEventButton *gdk_event, GtkWidget *widget2)
{
  if((gdk_event->type== GDK_2BUTTON_PRESS || gdk_event->type== GDK_2BUTTON_PRESS)) {
if(winismaximized==false){
gtk_window_set_decorated(GTK_WINDOW(widget2),FALSE);gtk_window_maximize(GTK_WINDOW(widget2));winismaximized=true;
}else{
gtk_window_set_decorated(GTK_WINDOW(widget2),TRUE);gtk_window_unmaximize(GTK_WINDOW(widget2));winismaximized=false;}   
  }
  return FALSE;
}
gboolean on_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
//printf("KeyVal:%i\n",event->keyval);
switch (event->keyval){
case 100:
if(hudisvisible==false){hudisvisible=true;gtk_widget_show (eb_top1);}else{hudisvisible=false;gtk_widget_hide (eb_top1);}
break;
case 102:
if(winismaximized==false){
gtk_window_set_decorated(GTK_WINDOW(widget),FALSE);gtk_window_maximize(GTK_WINDOW(widget));winismaximized=true;
}else{
gtk_window_set_decorated(GTK_WINDOW(widget),TRUE);gtk_window_unmaximize(GTK_WINDOW(widget));winismaximized=false;}
break;
case 65362:
/* up arrow */
if (up_on!=true){up_on=true;DIREC=(DIREC+1);DIREC_changed=true;}
break;
case 65361:
/* left arrow */
if (left_on!=true){left_on=true;DIREC=(DIREC+2);DIREC_changed=true;}
break;
case 65363:
/* right arrow */
if (right_on!=true){right_on=true;DIREC=(DIREC+4);DIREC_changed=true;}
break;
case 65364:
/* down arrow */
if (down_on!=true){down_on=true;DIREC=(DIREC+8);DIREC_changed=true;}
break;
case 32:
/* space bar */
break;
default:
break;
}
if(DIREC_changed==true){/* put transmit direction here */ print_DIREC(DIREC);DIREC_changed=false;}
return FALSE;
}
gboolean on_key_release (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
//printf("KeyVal Release:%i\n",event->keyval);
switch (event->keyval){
case 65362:
/* up arrow */
if (up_on!=false){up_on=false;DIREC=(DIREC-1);DIREC_changed=true;}
break;
case 65361:
/* left arrow */
if (left_on!=false){left_on=false;DIREC=(DIREC-2);DIREC_changed=true;}
break;
case 65363:
/* right arrow */
if (right_on!=false){right_on=false;DIREC=(DIREC-4);DIREC_changed=true;}
break;
case 65364:
/* down arrow */
if (down_on!=false){down_on=false;DIREC=(DIREC-8);DIREC_changed=true;}
break;
default:
break;
}
if(DIREC_changed==true){/* put transmit direction here */ print_DIREC(DIREC);DIREC_changed=false;}
  return FALSE;
}
int print_DIREC(DIREC_val){
switch(DIREC_val){
case 0:
system("clear");printf("Stopped\n");
break;
case 1:
system("clear");printf("Forward\n");
break;
case 2:
system("clear");printf("Left\n");
break;
case 4:
system("clear");printf("Right\n");
break;
case 3:
system("clear");printf("Forward-Left\n");
break;
case 5:
system("clear");printf("Forward-Right\n");
break;
case 8:
system("clear");printf("Reverse\n");
break;
case 10:
system("clear");printf("Reverse-Left\n");
break;
case 12:
system("clear");printf("Reverse-Right\n");
break;
default:
system("clear");printf("Invalid Direction\n");
break;
}
return 0;
}


Top
 Profile  
 
 Post subject: Re: Pixbuf memory issues
PostPosted: Fri Apr 26, 2013 5:10 pm 
Offline

Joined: Tue Apr 23, 2013 10:44 pm
Posts: 4
the attachment files


Attachments:
File comment: all the files related to the client side
gui.tar.bz2 [13.98 KiB]
Downloaded 43 times
Top
 Profile  
 
 Post subject: Re: Pixbuf memory issues
PostPosted: Fri Apr 26, 2013 9:10 pm 
Offline

Joined: Tue Apr 23, 2013 10:44 pm
Posts: 4
So as it turns out in reading my own post calling for help I was able to identify the problem, it seems to be fixed now my app doesn't die as usual because of out of memory problems.

The line:
g_object_unref(pixbuf);

Should have been:

g_object_unref(G_OBJECT(pixbuf));

apparently g_object_unref doesn't assume one is talking about a G_OBJECT.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: Tanite and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group