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?
Here is the code for the program.
Thanks in advance
#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); */
/* } */
}