[prev in list] [next in list] [prev in thread] [next in thread]
List: linux1394-user
Subject: Re: Camera Capture Flakiness
From: Johann Schoonees <j.schoonees () irl ! cri ! nz>
Date: 2003-12-07 21:30:39
[Download RAW message or body]
Travis Sparks wrote:
> Date: Sat, 06 Dec 2003 10:00:30 -0500
> From: Travis Sparks <sparkst@cs.unc.edu>
> Reply-To: sparkst@cs.unc.edu
> Organization: UNC - Chapel Hill Computer Science
> To: linux1394-user@lists.sourceforge.net
> Subject: Camera Capture Flakiness
>
> Our research group at UNC-CH has been fighting firewire camera
> "flakiness" issues off and on for over a year now with no
resolution. I
> think that our issues are more related to libdc1394, but I cannot rule
> out libraw. At this point we would love a solution but are open to
> ideas on how to better test our setup to ensure things are correct.
Hi Travis
I can unfortunately only give some general pointers. Someone else may
be able to pinpoint your problem.
In general, I had to read a lot of source code (libdc1394 and
video1394) before I got the hang of it.
Be aware that calls to dc1394_dma_multi_capture() block in the
video1394 driver until a frame is received. No frame, no return.
There is a bug in the Linux 1394 system (well not so much a bug as an
incomplete implementation) which causes the camera sometimes to be
made the cycle master despite its protestations during bus resets that
it is not cycle master capable. Nothing you can do about it except
check that it has happened and trying another reset. I use code like
this (hasty cut & paste, not complete but could give you an idea):
typedef struct camera_bus_handle *Cam_handle;
/* This is the camera handle type. */
typedef raw1394handle_t Port_handle;
typedef nodeid_t Node_handle;
typedef struct camera_user_data *User_handle;
typedef struct camera_bus_handle
{
Port_handle port;
Node_handle node;
User_handle userdata;
}
camera_bus_handle_struct;
int num_cams = 0;
Cam_handle *handle_array = NULL;
int main(const int argc, const char *argv[])
{
Cam_handle *handle_array = NULL;
int retry;
int bad_bus;
int num_cameras;
/* Initialize the camera bus:*/
handle_array = cambus_create(&num_cameras);
if (num_cameras < 0 || handle_array == NULL)
{ /* Could be the known kernel 1394 cycle master bug. */
printf("Error initializing the bus: trying reset");
retry = 3;
bad_bus = 1;
while (retry > 0 && bad_bus)
{
printf(" %d", retry);
fflush(stdout);
cambus_reset();
sleep(1);
handle_array = cambus_create(&num_cameras);
if (num_cameras >= 0 && handle_array != NULL) bad_bus = 0;
retry--;
}
if (bad_bus)
{
errorexit(NULL, -1, "Could not initialize the camera bus.");
}
else
{
printf("\n\n");
fflush(stdout);
}
}
if (num_cameras == 0)
{
errorexit(NULL, -1, "Could not find a camera.");
}
if (num_cameras == 1) printf("Found one camera.\n");
else printf("Found %d cameras.\n\n", num_cameras);
fflush(stdout);
... rest of code in main() ...
}
Cam_handle * cambus_create(int *num_handles)
/* Returns a pointer to an array of all available camera handles. The
cameras are not initialized. The number of handles is returned in
num_handles. If no cameras are found, returns a null pointer and 0
for num_handles. On error, returns a null pointer and -1 for
num_handles. The function cambus_destroy() must be called when done
to free the allocated memory. If cambus_create() is called more
times than cambus_destroy(), then it returns the previous array of
camera handles and previous number of handles without doing anything
else. */
{
int p, n;
int camcount, num_ports, num_nodes;
int cycle_master;
raw1394handle_t p_handle = NULL;
nodeid_t *nodelist = NULL;
/* Check whether the bus has not already been created: */
if (handle_array != NULL && num_cams >= 0)
{
*num_handles = num_cams;
return(handle_array);
}
/* Set default (error) values: */
*num_handles = -1;
num_cams = 0;
/* Count the number of visible cameras and IEEE 1394 ports (cards or
chips): */
num_ports = count_the_ports();
if (num_ports < 0) return(NULL); /* Error accessing a port.*/
camcount = count_the_cameras(num_ports);
if (camcount < 0) return(NULL); /* Error accessing a port.*/
if (num_ports == 0) return(NULL); /* Found no ports.*/
if (camcount == 0) /* Nothing wrong, just found no cameras.*/
{
*num_handles = 0;
return(NULL);
}
/* Allocate memory for camera handles: */
handle_array = (Cam_handle *) calloc((size_t) camcount,
sizeof(Cam_handle));
if (handle_array == NULL) return(NULL); /* Allocation failure.*/
/* Fill in the camera addressing map: */
for (p = 0; p < num_ports; p++)
{
p_handle = dc1394_create_handle(p);
/*
if (p_handle == NULL)
// Internal error: should have been caught in
// count_the_cameras() above.
{
cambus_destroy();
return(NULL);
}
*/
/* Find out who the cycle master is:*/
cycle_master = raw1394_get_nodecount(p_handle) - 1;
nodelist = dc1394_get_camera_nodes(p_handle, &num_nodes, 0);
/*
if ((num_nodes < 0) || ((num_nodes > 0) && (nodelist == NULL)))
// Internal error: should have been caught in
// count_the_cameras() above.
{
dc1394_destroy_handle(p_handle);
cambus_destroy();
return(NULL);
}
*/
for (n = 0; n < num_nodes; n++)
{
if (nodelist[n] == cycle_master)
{ /* Cameras are not cycle master capable. */
if (n == 0) dc1394_destroy_handle(p_handle);
cambus_destroy();
return(NULL);
}
handle_array[num_cams] =
(Cam_handle) malloc(sizeof(struct camera_bus_handle));
if (handle_array[num_cams] == NULL)
{ /* Allocation failure.*/
if (n == 0) dc1394_destroy_handle(p_handle);
cambus_destroy();
return(NULL);
}
handle_array[num_cams]->port = p_handle;
handle_array[num_cams]->node = nodelist[n];
num_cams++;
}
free(nodelist); /* Because libdc1394 doesn't.*/
}
/* Sanity check: */
/*
if (num_cams != camcount) // Internal error.
{
cambus_destroy();
return(NULL);
}
*/
/* Returns: */
*num_handles = num_cams;
return(handle_array);
}
void cambus_reset(void)
/* Requests a reset of each bus which has cameras attached. All camera
handles are invalidated. Any existing handles should first be
destroyed with cambus_destroy() and re-assigned with cambus_create()
after the bus reset. The time needed for a bus reset is
hardware-dependent and the calling program may have to wait a while
before trying to access the bus again. */
{
int num_ports, num_nodes;
int p, h;
raw1394handle_t p_handle, last_port = NULL;
if (handle_array == NULL && num_cams == 0)
{ /* No existing bus. */
num_ports = count_the_ports();
for (p = 0; p < num_ports; p++)
{
p_handle = dc1394_create_handle(p);
if (p_handle)
{
num_nodes = count_the_nodes(p_handle);
if (num_nodes > 0) raw1394_reset_bus(p_handle);
dc1394_destroy_handle(p_handle);
}
}
}
else if (handle_array)
{ /* A bus exists. */
for (h = 0; h < num_cams; h++)
{
if ((h == 0) || (handle_array[h]->port != last_port))
{
p_handle = handle_array[h]->port;
if (p_handle)
{
num_nodes = count_the_nodes(p_handle);
if (num_nodes > 0) raw1394_reset_bus(p_handle);
dc1394_destroy_handle(p_handle);
}
last_port = p_handle;
}
free(handle_array[h]);
}
free(handle_array);
handle_array = NULL;
}
num_cams = 0;
}
And X should not come into it at all. I have many times successfully
run our camera with no X in sight.
Not being able to run again without rebooting is also something I have
come across. You will need to tell the video1394 driver to stop
listening to the channel. The following code got rid of the need to
reboot for me:
/*
Tells the video1394 driver to stop listening to the given channel.
Compile this file with something like
gcc -Wall -I../libdc1394-0.9.1/libdc1394 unlisten.c -o unlisten
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "kernel-video1394.h"
#define VIDEO1394_DEVICE_NAME "/dev/video1394/0"
int main(const int argc, const char *argv[])
{
char *device;
int fd, channel, retval;
if (argc < 2)
{
fprintf(stderr, "Usage: %s channel_number\n", argv[0]);
return(EXIT_FAILURE);
}
device = VIDEO1394_DEVICE_NAME;
fd = open(device, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Could not open video1394 device %s\n", device);
return(EXIT_FAILURE);
}
channel = atoi(argv[1]);
retval = ioctl(fd, VIDEO1394_UNLISTEN_CHANNEL, &channel);
close(fd);
return(retval);
}
Do you know about the libdc1394-devel mailing list (also on
sourceforge) and its archive? It may be more specific to the kinds of
problems you decribe.
Regards,
Johann
--
^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^
Johann Schoonees Imaging & Sensing Team
Industrial Research Limited, PO Box 2225, Auckland, New Zealand
Phone +64 9 9203679 Fax +64 9 3028106 http://www.is.irl.cri.nz/
-------------------------------------------------------
This SF.net email is sponsored by: IBM Linux Tutorials.
Become an expert in LINUX or just sharpen your skills. Sign up for IBM's
Free Linux Tutorials. Learn everything from the bash shell to sys admin.
Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click
_______________________________________________
mailing list Linux1394-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux1394-user
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic