Skip to main content
GameDev.net gamedev.net
🔒 Locked

Multithreading and devices...

Started by Bacardi34 Aug 23, 2004 at 6:00 PM 4 replies 1.4k views
Original Post
Bacardi34
Bacardi34
Hi, im trying to get my program to read from multiple cameras that are hooked up to the machine. Before i was not using threading and i was reading each frame from the cameras at a time and the processing them. This was too slow and inefficent as the cameras would not be synced up. So i dove into multithreading and i have a thread all set up but when i try and open a device (camera) the thread stops. so i took the open sequence out of the thread and then when the thread tries to read from the camrea the thread stops. i didnt change the reading code at all, or the open camera code from the other version of the program that did not use threading. All the values of what i pass into the thread function are ok, like the device name, width, height, etc. i have checked them many times over. Here is the thread code.

struct thread_data
{
  char deviceName[40];
  int device;
  char name[200];
  int maxFrames;
  int xOffset;
  int yOffset;
  char experiment;
  char nopng;
  int cam;
  char isbottom;
  pthread_mutex_t the_mutex;
};

void * cam_read( void * theInfo )
{
  int width, height, depth;
  int i, result;
  unsigned char * image;
  struct thread_data *data;
  data = (struct thread_data *)theInfo;

  char prefix[200];

  printf( "%s\n", data->deviceName );
  data->device = open_camera( data->deviceName, data->the_mutex );
  
  printf( "%s %d\n", "hi", data->device );
  

  for( i = 0; i < data->maxFrames; i++ )
    {
      printf( "%s %i\n", "READ FRAME:", i );
      // read the cam image
      result = qcam_read( data->device, &width, &height, &depth,
			  ℑ, data->the_mutex );
      printf( "%d\n", result );
      if( !result )	
	{
	  printf( "%s %i\n", "BLEAH:", i );
	  get_actual_image( image, width, height, depth,
			    data->xOffset, data->yOffset, data->isbottom, 1 );
	}
      
      if( !data->nopng )
	{
	  if( !data->experiment )
	    {
	      sprintf( prefix, "../var/%s_%d/%s_%d %03d.png", data->name, data->cam, data->name, data->cam, i );
	    }
	  else if ( data->experiment )
	    {
	      sprintf( prefix, "../var/experiments/image_sequences/%s/%s_%d/%s_%d %03d.png", data->name, 
		       data->name, data->cam, data->name, 
		       data->cam, i );
	    }
	  // Ends up looknig like "dirname_cam/frame.png"
	  png_write_qcam( prefix, width, height, i, image, data->isbottom );
	  //fprintf( stdout, "%s\n", prefix );
	}
      free( image );
    }
  
  close_camera( data->device );
  pthread_exit(0);
}



This is how im creating all the threads. Is there perhaps some problem with the way i am creating the thread that will not let it access devices attached to the computer?

// Make all the threads
  for( i = 0; i < numDirs; i++ )
    {
      info = ( struct thread_data* )malloc( sizeof( struct thread_data ));
      sprintf( info->deviceName, "/dev/video%d", i );
      strcpy( info->name, name );
      info->maxFrames   = maxFrames;
      info->xOffset     = xOffSet;
      info->yOffset     = yOffSet;
      info->nopng       = nopng;
      info->experiment  = experiment;
      info->cam         = i;
      info->isbottom    = isbottom;
      info->the_mutex   = a_mutex;

      pthread_create( &threads, 0,
		      cam_read,
		      (void *)info);
    }



edit: source tags [Edited by - Bacardi34 on August 24, 2004 11:09:09 AM]
NicoDeLuciferi
NicoDeLuciferi
Well,

I'm not seeing any mutex initiation code, or use for that matter.
So abit more code wouldn't hurt, maybe then I could help you.

/Nico
Bacardi34
Bacardi34
Ok, sorry, here is the qcam_read function.
//int qcam_read(char * filename, int * imgwidth,int * imgheight,int * imgdepth,int qcam_read( int device, int *imgwidth, int * imgheight, int * imgdepth,	       unsigned char ** image, pthread_mutex_t the_mutex) {  int rc;  ioctl(device, VIDIOCGCAP, &vidcap);  ioctl(device, VIDIOCGWIN, &vidwin);  ioctl(device, VIDIOCGPICT, &vidpic);  *imgwidth= vidwin.width;  *imgheight= vidwin.height;  *imgdepth= vidpic.depth/8;  *image = malloc(vidcap.maxwidth * vidcap.maxheight * 3);  rc = pthread_mutex_lock(&the_mutex);  printf( "device %d\twidth %d\theight %d\n", device, vidcap.maxwidth, vidcap.maxheight );  printf( "%x\n", *image );  if( !rc )    {      printf( "Mutex locked in qcam_read\n" );    }    read(device, *image, (vidcap.maxwidth * vidcap.maxheight * 3));  rc = pthread_mutex_unlock(&the_mutex);  if( !rc )    {      printf( "Mutex unlocked in qcam_read\n" );    }    printf( "Qcam_read %d\n",  device );  return 1;}


and here is the code for opening the camera
int open_camera(const char *devicename, pthread_mutex_t mutex){  int rc;  rc = pthread_mutex_lock( &mutex );  if( !rc )    {      printf( "Mutex locked in cam_open\n" );    }    int device = open(devicename, O_RDWR);  pthread_mutex_unlock( &mutex );  if( !rc )    {      printf( "Mutex unlocked in cam_open\n" );    }    if(device <= 0)    {      printf("Device %s couldn't be opened\n", devicename);      return 0;    }  //return 1;  return device;}

it gets as far as saying "mutex locked in cam_open" for both each thread that is started, then just stops.

Thanks for the help in advance
Shannon Barber
Shannon Barber
Do you ever initialize the mutex? You can set it to some special value and POSIX will initialize it for you, but if you do it yourself you can specific a process-local mutex (which is faster).
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Bacardi34
Bacardi34
mutex is initialized like this:
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;
Bacardi34
Bacardi34
ok, i changed the program around a bit. i made the mutex global and moved the camera opening procedure inside the thread function just to make things a bit clearer.
here is the entire program.
when its run, it prints out the device name (/dev/video0)
and then "muted locked in cam_open" and then it exits.
its not a crash or a segfault, it just stops and returns to the prompt.
#include <stdlib.h>#include <stdio.h>#include <pthread.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/Xatom.h>#define SETWIDTH 320#define SETHEIGHT 240#define SETDEPTH 3#define SETFOV 0.1#define SETZDIST 50#define WINDOWWIDTH 980#define WINDOWHEIGHT 480#define MAXVIEWS 15// Globals that all files can seeint imgwidth = SETWIDTH;int imgheight = SETHEIGHT;int imgdepth = SETDEPTH;extern Display *display;extern Window win;typedef unsigned char * charp;pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;struct thread_data{  char deviceName[40];  int device;  char name[200];  int maxFrames;  int xOffset;  int yOffset;  char experiment;  char nopng;  int cam;  char isbottom;  pthread_mutex_t the_mutex;};void * cam_read( void * theInfo ){  int width, height, depth;  int i, result;  unsigned char * image;  struct thread_data *data;  data = (struct thread_data *)theInfo;  char prefix[200];  int rc;  fflush(stdout);  printf( "%s\n", data->deviceName );  rc = pthread_mutex_lock( &a_mutex );  if( !rc )    {      printf( "Mutex locked in cam_open\n" );    }    else    {      printf( "Cant lock mutex in cam_open\n" );    }   data->device =open( data->deviceName, O_RDWR);    //open_camera( data->deviceName, a_mutex );    if( !rc )    {      printf( "Mutex unlocked in cam_open\n" );    }  fflush(stdout);  printf( "%s %d\n", "hi", data->device );    for( i = 0; i < data->maxFrames; i++ )    {      printf( "%s %i\n", "READ FRAME:", i );      // read the cam image      result = qcam_read( data->device, &width, &height, &depth,			  ℑ, a_mutex );      printf( "%d\n", result );      if( !result )		{	  printf( "%s %i\n", "BLEAH:", i );	  get_actual_image( image, width, height, depth,			    data->xOffset, data->yOffset, data->isbottom, 1 );	}            if( !data->nopng )	{	  if( !data->experiment )	    {	      sprintf( prefix, "../var/%s_%d/%s_%d %03d.png", data->name, data->cam, data->name, data->cam, i );	    }	  else if ( data->experiment )	    {	      sprintf( prefix, "../var/experiments/image_sequences/%s/%s_%d/%s_%d %03d.png", data->name, 		       data->name, data->cam, data->name, 		       data->cam, i );	    }	  // Ends up looknig like "dirname_cam/frame.png"	  png_write_qcam( prefix, width, height, i, image, data->isbottom );	  //fprintf( stdout, "%s\n", prefix );	}      free( image );    }    close_camera( data->device );  pthread_exit(0);}int main (int argc, char ** argv) {  charp image[MAXVIEWS];  int width[MAXVIEWS], height[MAXVIEWS], depth[MAXVIEWS];  int xOffSet[MAXVIEWS], yOffSet[MAXVIEWS];  int error;  int i, j;  int gzpx[MAXVIEWS], gzpy[MAXVIEWS], gzpz[MAXVIEWS];  double pitch[MAXVIEWS], roll[MAXVIEWS], yaw[MAXVIEWS];  int isbottom[MAXVIEWS];  int devices[MAXVIEWS]; // Store the camera device(s)  FILE *stereo; // stereo.dat file pointer  FILE *directory[MAXVIEWS]; // File pointer for the flatview info in each dir  int numDirs = 0; // Holds the number of directorys we will be looking at, must be less than MAXVIEWS.  int maxFrames, currentFrame;  int viewNum; // Stores the current view being looked at.  char name[125] = {};// Stores the name of the capture we are working on  char filename[125];  FILE *fp;  char prefix[125];    int nopng = 0; // if 1 no png will be writen.  int up_down = 0;  int ud_cam = 0;  int go = 0;  int experiment = 0; // if 1 this is capturing an experiment and will create the corect directories accordingly.    pthread_t threads[MAXVIEWS] = {};  struct thread_data *info[MAXVIEWS] = {};      // Get the program flags  for( i = 0; i < argc; i++ )    {      if( !strcmp( argv, "-npng" ))	nopng = 1;      if( !strcmp( argv, "-name" ))	strcpy( name, argv[++i] );      if( !strcmp( argv, "-exp" ))	experiment = 1;      if( !strcmp( argv, "-cams" ))	numDirs = argv[++i];      if( !strcmp( argv, "-u" ))	up_down = 1;      if( !strcmp( argv, "-go" ))	go = 1;    }    if( !go )    {      // First get all the info from the user about what we will be caputring      if( !strcmp( name, "" ) && !nopng)	{	  fprintf( stdout, "What will this test be called? " );	  fscanf( stdin, "%s", name );	}            if( numDirs == 0 )	{	  fprintf( stdout, "How many cameras will we be capturing from? " );	  fscanf( stdin, "%d", &numDirs );	}            if( up_down )	{	  fprintf( stdout, "What camera is upside down? " );	  fscanf( stdin, "%d", &ud_cam );	}    }  for( i = 0; i < numDirs; i++ )    {      if( !nopng && !go )	{	  // Get the x, y, z, yaw, pitch, roll for each camera	  fprintf( stdout, "cam %d X pos: ", i+1 );	  fscanf( stdin, "%d", &gzpx );	  fprintf( stdout, "cam %d Y pos: ", i+1 );	  fscanf( stdin, "%d", &gzpy );	  fprintf( stdout, "cam %d Z pos: ", i+1 );	  fscanf( stdin, "%d", &gzpz );	  	  fprintf( stdout, "cam %d Yaw: ", i+1 );	  fscanf( stdin, "%lf", &yaw );	  fprintf( stdout, "cam %d Pitch: ", i+1 );	  fscanf( stdin, "%lf", &pitch );	  fprintf( stdout, "cam %d Roll: ", i+1 );	  fscanf( stdin, "%lf", &roll );	  	  fprintf( stdout, "If the camera is upside down enter 1, otherwise enter 0. " );	  fscanf( stdin, "%d", &isbottom ); 	  	  // Make the directories that the pics will be stored in	  {	    if( !experiment )	      {		sprintf( filename, "mkdir ../var/%s_%d", name, i ); 		//printf( "%s\n", filename );	      }	    else if ( experiment )	      {		sprintf( filename, "mkdir ../var/experiments/image_sequences/%s/%s_%d", name, name, i );	      }	    system( filename );	  }	}      else	{	  gzpx      = 0;	  gzpy      = 0;	  gzpz      = 0;	  yaw       = 0;	  pitch     = 0;	  roll      = 0;	  if( up_down == 1 && (ud_cam - 1) == i )	    isbottom  = 1;	  else	    isbottom = 0;	}    }    if( !nopng )    {      fprintf( stdout, "How many frames will we capture? " );      fscanf( stdin, "%d", &maxFrames );    }  else    {      maxFrames = 5000;    }      // init the display  init_display(argv[0],WINDOWWIDTH,WINDOWHEIGHT);      // Setup the x and y offset for the images   for( i = 0; i < numDirs; i++ )    {      if( i < 2 )	{	  xOffSet = ( i % 3 ) * 320;	  yOffSet = ( i / 2 ) * 240;	}      if( i >= 2 )	{	  xOffSet = (( i + 1 ) % 3 ) *  320;	  yOffSet = (( i + 1 ) / 2 ) + 240;	}    }    // Write the .dat file for each directory  if( !nopng )    {      for( i = 0; i < numDirs; i++ )	{	  if( !experiment )	    {	      sprintf( filename, "../var/%s_%d.dat", name, i );	      sprintf( prefix, "%s_%d/%s_%d", name, i, name, i );	    }	  else if ( experiment )	    {	      sprintf( filename, "../var/experiments/image_sequences/%s/%s_%d.dat", name, name, i );	      sprintf( prefix, "experiments/image_sequences/%s/%s_%d/%s_%d", name, name, i, name, i );	    }	  fp = fopen( filename, "w" );	  fprintf( fp, "%s\n%d\n%d\n%d\n%d %d %d\n%lf %lf %lf\n", prefix, 0,		   currentFrame, 3, gzpx, gzpy, gzpz,		   yaw, pitch, roll );	  fclose( fp );	}    }       // Make all the threads  for( i = 0; i < numDirs; i++ )    {      info = ( struct thread_data* )malloc( sizeof( struct thread_data ));      sprintf( info->deviceName, "/dev/video%d", i );      strcpy( info->name, name );      info->maxFrames   = maxFrames;      info->xOffset     = xOffSet;      info->yOffset     = yOffSet;      info->nopng       = nopng;      info->experiment  = experiment;      info->cam         = i;      info->isbottom    = isbottom;      //info->the_mutex   = a_mutex;      pthread_create( &threads, 0,		      cam_read,		      (void *)info);    }    /*   for( i = 0; i < numDirs; i++ ) *//*     { *//*       pthread_join(info, 0); *//*     } */    } 

thanks for any help!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.