Thread: Multithreading problem

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    3

    Multithreading problem

    Hi, im just learning about multithreading for a program i am writing that ne
    eds to read from multiple camreas attached to the computer at the same time.

    I know how to create threads and pass around info, and i know a bit about mu
    texes but this is not where the problem resides.
    Every time the thread goes to open the device at /dev/video* the thread just
    stops running as far as i can see.
    i put printf's all over the place and it prints right before the open call o
    n the camera, then the next thread kicks in and does the same thing.
    I know the camreas work cuse when i go back to the non-multithreaded code, e
    verything works just fine.
    Also if i try the open call outside the thread, then pass the camrea into th
    e thread, they open fine but when the read() call comes, then the thread die
    s in the same way.
    Does anyone have any ideas whats going on?
    Thanks in advance for the help
    Here is the code for the program.

    Code:
    #include "ifqcam.h"
    #include "error.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <linux/videodev.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 see
    int 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);
      data->device = 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,
    			  &image, 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[i], "-npng" ))
    	nopng = 1;
          if( !strcmp( argv[i], "-name" ))
    	strcpy( name, argv[++i] );
          if( !strcmp( argv[i], "-exp" ))
    	experiment = 1;
          if( !strcmp( argv[i], "-cams" ))
    	numDirs = argv[++i];
          if( !strcmp( argv[i], "-u" ))
    	up_down = 1;
          if( !strcmp( argv[i], "-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[i] );
    	  fprintf( stdout, "cam %d Y pos: ", i+1 );
    	  fscanf( stdin, "%d", &gzpy[i] );
    	  fprintf( stdout, "cam %d Z pos: ", i+1 );
    	  fscanf( stdin, "%d", &gzpz[i] );
    	  
    	  fprintf( stdout, "cam %d Yaw: ", i+1 );
    	  fscanf( stdin, "%lf", &yaw[i] );
    	  fprintf( stdout, "cam %d Pitch: ", i+1 );
    	  fscanf( stdin, "%lf", &pitch[i] );
    	  fprintf( stdout, "cam %d Roll: ", i+1 );
    	  fscanf( stdin, "%lf", &roll[i] );
    	  
    	  fprintf( stdout, "If the camera is upside down enter 1, otherwise enter 0. " );
    	  fscanf( stdin, "%d", &isbottom[i] ); 
    	  
    	  // 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[i]      = 0;
    	  gzpy[i]      = 0;
    	  gzpz[i]      = 0;
    	  yaw[i]       = 0;
    	  pitch[i]     = 0;
    	  roll[i]      = 0;
    	  if( up_down == 1 && (ud_cam - 1) == i )
    	    isbottom[i]  = 1;
    	  else
    	    isbottom[i] = 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] = ( i % 3 ) * 320;
    	  yOffSet[i] = ( i / 2 ) * 240;
    	}
          if( i >= 2 )
    	{
    	  xOffSet[i] = (( i + 1 ) % 3 ) *  320;
    	  yOffSet[i] = (( 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[i], gzpy[i], gzpz[i],
    		   yaw[i], pitch[i], roll[i] );
    	  fclose( fp );
    	}
        }
       
      
      // Make all the threads
      for( i = 0; i < numDirs; i++ )
        {
          info[i] = ( struct thread_data* )malloc( sizeof( struct thread_data ));
          sprintf( info[i]->deviceName, "/dev/video%d", i );
          strcpy( info[i]->name, name );
          info[i]->maxFrames   = maxFrames;
          info[i]->xOffset     = xOffSet[i];
          info[i]->yOffset     = yOffSet[i];
          info[i]->nopng       = nopng;
          info[i]->experiment  = experiment;
          info[i]->cam         = i;
          info[i]->isbottom    = isbottom[i];
          //info[i]->the_mutex   = a_mutex;
    
          pthread_create( &threads[i], 0,
    		      cam_read,
    		      (void *)info[i]);
        }
        
    /*   for( i = 0; i < numDirs; i++ ) */
    /*     { */
    /*       pthread_join(info[i], 0); */
    /*     } */
      
      
    }

  2. #2
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192
    Maybe the non-standard function open_camera() is causing the problem and getting into blocked state. Are you sure the problem is not there?

    -Harsha
    Help everyone you can

  3. #3
    Registered User
    Join Date
    Aug 2004
    Posts
    3
    All the camera open function does is call:
    open( device, 0_RDWR );
    and then return the device that was opened.

    the thread is hanging at the open() call.

  4. #4
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192

    Lightbulb Might not be a problem...

    Quote Originally Posted by Bacardi34
    All the camera open function does is call:
    open( device, 0_RDWR );
    and then return the device that was opened.

    the thread is hanging at the open() call.

    Hi,
    this might not be a problem, but a non-follow of specification.

    PTHREAD_MUTEX_INITIALIZER can only be used on Static mutex. Check This out... Info On Mutex Initializer
    I cannot try it out as I dont have the additional libraries and h/w that you are using.

    I believe the line data->devicename is being printed and then your program is stalling. So, definately there is a problem at open_camera unless you see the next line "Hi <devicename>". And if "open" is the only function being called by open_camera, then I dont see any other problem but the one with mutex. Check that out as another trial..!
    Help everyone you can

  5. #5
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192

    Lightbulb

    Also, why are you not locking the mutex before calling open?





    -Harsha
    This might be of much interest to you
    Last edited by vsriharsha; 08-28-2004 at 01:09 AM. Reason: more info
    Help everyone you can

  6. #6
    Registered User
    Join Date
    Aug 2004
    Posts
    3
    Quote Originally Posted by vsriharsha
    Hi,
    this might not be a problem, but a non-follow of specification.

    PTHREAD_MUTEX_INITIALIZER can only be used on Static mutex. Check This out... Info On Mutex Initializer
    I cannot try it out as I dont have the additional libraries and h/w that you are using.

    I believe the line data->devicename is being printed and then your program is stalling. So, definately there is a problem at open_camera unless you see the next line "Hi <devicename>". And if "open" is the only function being called by open_camera, then I dont see any other problem but the one with mutex. Check that out as another trial..!
    ok, i updated the code. i removed the call to open_camera() in the thread loop and just made the open() call right in the loop, and i changed the mutex to static mutex.
    here is the new relevant code:
    Code:
    static 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 for open\n" );
        }
      else
        {
          printf( "Cant lock mutex for open\n" );
        }
      data->device = open( data->deviceName, O_RDWR);
      //data->device = open_camera( data->deviceName, a_mutex );  
      if( !rc )
        {
          printf( "Mutex unlocked for 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,
    			  &image, 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);
    }
    The output from this is now:
    "/dev/video0"
    "mutex locked for open"
    "/dev/video1"

    Then it stops.
    Thx for the help

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  2. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  3. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  4. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  5. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM