This commit is contained in:
gferg 2007-05-04 13:21:30 +00:00
parent 9853b20e0f
commit c77b5d4a84
1 changed files with 304 additions and 22 deletions

View File

@ -8,7 +8,7 @@
<surname>Agarwal</surname>
<affiliation>
<address>
<email><ulink url="mailto:rohdimp_24@rediffmail.com">rohdimp_24@rediffmail.com/</ulink></email>
<email><ulink url="mailto:rohdimp_24@rediffmail.com">rohdimp_24@rediffmail.com</ulink></email>
</address>
</affiliation>
</author>
@ -23,6 +23,12 @@
</author>
<pubdate>2006-01-23</pubdate>
<revhistory>
<revision>
<revnumber>1.2</revnumber>
<date>2007-04-14</date>
<authorinitials>RA</authorinitials>
<revremark>Addition of DMA related section contributed by Ian Peikon <email><ulink url="mailto:idp2@duke.edu">idp2@duke.edu</ulink></email>and Tim Hanson <email><ulink url="mailto:tim@hardcarve.com">tim@hardcarve.com</ulink></email></revremark>
</revision>
<revision>
<revnumber>1.0</revnumber>
<date>2006-01-23</date>
@ -84,7 +90,7 @@
present. Normally it is in <filename
class="directory">/usr/src</filename>. We suggest that you download
a fresh copy of the kernel source code (2.6.10) from <ulink url="http://www.kernel.org/">www.kernel.org</ulink>.</para>
<para>Thus, <command>cd /usr/src/kernel-2.6</command> (<filename>kernel-2.6.10</filename> is the name of the source code directory. It can vary from system to system.)</para>
<para>Thus, <command>cd /usr/src/kernel-2.6.10</command> (<filename>kernel-2.6.10</filename> is the name of the source code directory. It can vary from system to system.)</para>
<orderedlist>
<listitem><para><command>make menuconfig</command></para></listitem>
<listitem><para>The menu will come up. Select <guimenuitem>Device Drivers</guimenuitem></para></listitem>
@ -206,15 +212,15 @@ polling for leftover messages
cameras at <ulink
url="http://www.ptgrey.com/support/kb/data/grabdma.tgz">http://www.ptgrey.com/support/kb/data/grabdma.tgz</ulink>.</para>
<para>Fortunately, we have an open source graphical application
developed for the IEEE1394 cameras, known a<application>ion>Coria</application>io<application>ation>Cor</application>ation> provides a nice Graphical User
developed for the IEEE1394 cameras, known as <application><command>Coriander</command></application> that provides a nice Graphical User
Interface for libdc1394 to help the user work with the camera more
efficiently. Later we will di<application>applicati</application>application> helped us for debugging. Next,
efficiently. Later we will discuss how <application>Coriander</application> helped us in debugging. Next,
we briefly explain how to install <application>Coriander</application>.</para>
<orderedlist>
<title>Installation of <application>Coriander</application></title>
<listitem><para>Make sure that you have libdc1394 and the Gnome
libraries (<application>Coriander</application> uses
<filename>gnome.h</filename>ilename>) installed on your Linux
<filename>gnome.h</filename>) installed on your Linux
machine. For more details regarding the requirements, look into the user
manual provided by <application>Coriander</application>: <ulink
url="http://damien.douxchamps.net/ieee1394/coriander/manual.php">http://damien.douxchamps.net/ieee1394/coriander/manual.php</ulink>.</para></listitem>
@ -265,7 +271,7 @@ cd coriander-1.0.1/coriander-1.0.1/src
</orderedlist>
It may be possible that a camera does not support some modes, so we need to be careful during the setup. You use setup to set various parameters like data speed, image mode, framerate that are necessary to make the camera ready to grab the image. We will shortly discuss setup functions.</para></listitem>
<listitem><para>In order to set or get the values of the parameters/features of the camera, the library functions will modify or read the register values.</para></listitem>
<listitem><para>The camera can work with or without DMA. Unfortunately, our camera does not support DMA and hence we could not really exploit the functionality of DMA related functions. We limit our discussion to non-DMA functions.</para></listitem>
<listitem><para>The camera can work with or without DMA. We are greatful to Ian Peikon and Tim Hanson for contributing a section on IEEE1394 camera using DMA support </para></listitem>
</orderedlist>
<para>With the above background, we begin our discussion about the
various functions, data structures and other miscellaneous features
@ -445,11 +451,11 @@ gamma)
camera, some parameters must be passed to the function. The
number and the type of parameters are specific to the setup
function, but essentially three parameters must be passed in
all the setup functions: <parameter>w1394handle_t</parameter>,
all the setup functions: <parameter>raw1394handle_t</parameter>,
<parameter>nodeid_t</parameter> and the pointer to the dc1394_cameracapture structure (this is to provide the buffer for grabbed images and keep attributes, like height and width of frame).</para>
<para>As mentioned previously, <parameter>raw1394handle_t</parameter> and <parameter>nodeid_t</parameter> uniquely define the camera, while the pointer to dc1394_cameracapture provides the buffer for the image frame to be grabbed. It also stores information about the width and height of the frame which is useful at the time of image processing.</para>
<para>Other parameters that are passed are data speed, frame rate, image format, image mode and ISO channel number. </para>
<para>In case the camera uses DMA, the number of DMA buffers and drop frames is to be provided. As we have already mentioned, we will not be discussing the role of the DMA in this text.</para>
<para>In case the camera uses DMA, the number of <varname>DMA buffers</varname> and <varname>drop frames</varname> is to be provided. In most applications you will want to set the number of DMA buffers relatively low(i.e. 1) this ensures that you are viewing frames in near real time. Drop frames is also important for real time as it causes the capture function to throw away the frames buffered in the DMA ring buffer except fot the last. We will discuss about DMA functions in the later part of this HowTo</para>
<para>The various setup functions are:</para>
<orderedlist>
<listitem><para><function>dc1394_dma_setup_capture</function></para></listitem>
@ -474,16 +480,14 @@ gamma)
</imageobject>
</mediaobject>
</figure>
<para>As shown in Figure 3, the Setup function in turn calls various set functions to set the parameter values to the camera registers. In the case of DMA setup, after the set functions have been called the ioctl system call is called to set the DMA buffers.</para>
<para>The ioctl system calls will fail if the DMA is not supported by the camera and in such a case you will get the error message:</para>
<para><computeroutput>IDEO1394_IOC_LISTEN_CHANNEL ioctl failed </computeroutput></para>
<para>As shown in Figure 3, the Setup function in turn calls various set functions to set the parameter values to the camera registers. In the case of DMA setup, after the set functions have been called the ioctl system call is called to allocate memory for the DMA buffers and returns a pointer <parameter>capture_buffer</parameter> in user space.</para>
<para>The ioctl system calls will fail if the DMA is not setup correctly</para>
<para>The setup functions also allocate memory for the camera _capture buffer:</para>
<para>
<screen>camera-&gt;capture_buffer=(int*)malloc(camera-&gt;quadlets_per_frame*4);
</screen></para>
</sect3>
<sect3 id="format7_functions">
<sect3 id="format7_functions">
<title>Format7 Functions</title>
<para>These functions are used only if the camera is set for Format7. This format is preferred since this allows the user to define the size of the image to be captured according to his need. By default the size is 1024x768; you can set it to different dimensions, say 960x720.</para>
<para>All Format7 functions have <varname>format7</varname> in
@ -831,7 +835,7 @@ dc1394_single_capture(handle,&amp;camera)
<callout arearefs="stop_d"><para>After the image has been grabbed, stop the data transmission by calling the following function:</para>
<para><function>dc1394_stop_iso_transmission(handle,camera.node)</function></para>
</callout>
<callout arearefs="pgm_header"><anchor id="pgm_header_anchor" ></anchor><para>Add a PGM file header to the captured buffer to see the image using gimp.</para>
<callout arearefs="pgm_header"><anchor id="pgm_header_anchor" ></anchor><para>Add a PGM file header to the captured buffer to see the image using <application>gimp</application>.</para>
</callout>
<callout arearefs="fwrite"><para>Use <command>fwrite</command>
to save the captured image, by writing the buffer
@ -878,6 +882,280 @@ where the values of the parameters for channel, speed, bytes_per_packet, speed,
<listitem><para>The value of the width and height depends on the size of frame the user wants, for example, if one wants 960x720 then pass 960 as width and 720 as height.</para></listitem>
</orderedlist>
</sect2>
<sect2 id="dma example">
<title>Example: How to grab image from the IEEE1394 camera using DMA</title>
<para>This section has been contributed by Ian Peikon <email><ulink url="mailto:idp2@duke.edu">idp2@duke.edu</ulink></email>and Tim Hanson <email><ulink url="mailto:tim@hardcarve.com">tim@hardcarve.com</ulink></email>
We will now present an example of how to grab a frame by the camera using DMA calls. The example is simple to understand as the logic remains the same as the previous example. We will later compare the function calls used in the previous example (without dma) and this example (with dma) for better understanding.
</para>
<screen>
#include &lt;stdio.h&gt;
#include &lt;libraw1394/raw1394.h&gt;
#include &lt;libdc1394/dc1394_control.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;iostream&gt;
#define IMAGE_FILE_NAME "Image.pgm"
using namespace std;
int main(int arc, char *argv[]){
FILE * imagefile;
dc1394_cameracapture camera;
int numNodes;
int numCameras;
raw1394handle_t handle;
nodeid_t * camera_nodes;
unsigned int channel, speed, format, framerate, mode;
/*Step 1: Open ohci and assign a handle to it.*/
/*=======================================================*/
handle = dc1394_create_handle(0);
if(handle==NULL){
fprintf(stderr, "Unable to acquire a handle. \n\n");
}
else{
cout &lt;&lt;"dma1394: Handle aquired successfully-" &lt;&lt;handle&lt;&lt;"\n";
}
/*Step 2: Get the camera nodes and describe them as we find them.*/
/*=========================================================================*/
numNodes = raw1394_get_nodecount(handle);
camera_nodes = dc1394_get_camera_nodes(handle, &amp;numCameras, 1);
fflush(stdout);
if (numCameras&lt;1){
fprintf(stderr, "No cameras found :( \n");
dc1394_destroy_handle(handle);
return -1;
}
else{
cout&lt;&lt;"dma1394:"&lt;&lt; numCameras&lt;&lt;" cameras found. \n";
}
printf("dma1394: Working with the first camera on the bus.\n");
if(camera_nodes[0] == numNodes-1){
fprintf(stderr, "\n" "dma1394: Sorry, your camera is the highest numbered node.\n");
dc1394_destroy_handle(handle);
dc1394_free_camera_nodes(camera_nodes);
return -1;
}
/*Step 3: Setup Capture*/
/*=====================================================================*/
/*Using camera functions to get the params by querying them*/
cout&lt;&lt;"INFO FOR DEBUG: \n"
"num_dma_buffers: "&lt;&lt; camera.num_dma_buffers&lt;&lt;"\n";
dc1394_get_iso_channel_and_speed(handle, camera_nodes[0], &amp;channel, &amp;speed); /*get channel and speed*/
dc1394_get_video_format(handle, camera_nodes[0], &amp;format); /*get format*/
dc1394_get_video_framerate(handle, camera_nodes[0], &amp;framerate); /*get framerate*/
dc1394_get_video_mode(handle, camera_nodes[0], &amp;mode); /*get mode*/
cout&lt;&lt;"dc1394: Got parameters from the camera.\n"
"=======================================\n"
"Channel: "&lt;&lt; channel&lt;&lt; " \n"
"Speed: " &lt;&lt;speed &lt;&lt;" \n"
"Format: "&lt;&lt; format &lt;&lt;" \n"
"Framerate: " &lt;&lt;framerate&lt;&lt; "\n"
"Mode: "&lt;&lt; mode &lt;&lt;"\n";
camera.num_dma_buffers = 8; /* set the dma buffers */
camera.drop_frames = 1; /* set the number of drop frames */
camera.dma_device_file = NULL;
if(dc1394_dma_setup_capture(handle, camera_nodes[0], channel, format, mode, speed, framerate, camera.num_dma_buffers, camera.drop_frames, camera.dma_device_file, &amp;camera) !=DC1394_SUCCESS){
fprintf(stderr, "dma1394: Unable to setup camera.\n"
"Check line %d of %s to ensure that the options set are supported by your camera.\n", __LINE__, __FILE__);
dc1394_destroy_handle(handle);
dc1394_free_camera_nodes(camera_nodes);
return -1;
}
else{
printf("dma1394: Capture has been setup.\n");
}
dc1394_free_camera_nodes(camera_nodes);
//Set Trigger Mode -- Generally not required thus I will comment it out.
/*if(dc1394_set_trigger_mode(handle, camera.node, TRIGGER_MODE_0) != DC1394_SUCCESS){
fprintf(stderr, "dma1394: Unable to set the camera trigger mode. Refer to line %d in %s.\n", __LINE__, __FILE__);
dc1394_release_camera(handle, &amp;camera);
dc1394_destroy_handle(handle);
}
else{
printf("dma1394: Successfully set trigger mode.\n");
}*/
/*Step 4: Start sending data */
/*=======================================================*/
if(dc1394_start_iso_transmission(handle, camera.node) != DC1394_SUCCESS){
fprintf(stderr, "dma1394: Unable to start the data transmission.\n");
dc1394_dma_done_with_buffer(&amp;camera);
dc1394_dma_release_camera(handle, &amp;camera);
dc1394_destroy_handle(handle);
return -1;
}
else{
printf("dma1394: Success. Data Transmission started.\n");
}
/*Step 5: Capture Something...Anything...PLEASE*/
/*===============================================================*/
if(dc1394_dma_single_capture(&amp;camera) != DC1394_SUCCESS){
fprintf(stderr, "dma1394; DAIM, can't capture a single frame.\n");
dc1394_dma_done_with_buffer(&amp;camera); /*important step */
dc1394_dma_release_camera(handle, &amp;camera);
dc1394_destroy_handle(handle);
return -1;
}
else{
printf("dma1394: GREAT SUCCESS! Captured a single frame.\n");
}
/*Step 6: Stop sending data*/
/*==================================================*/
if(dc1394_dma_unlisten(handle, &amp;camera) != DC1394_SUCCESS){
fprintf(stderr, "Can't unlisten iso channel! \n");
}
else{
printf("dma1394: DMA unlistened. \n");
}
if(dc1394_stop_iso_transmission(handle, camera.node) != DC1394_SUCCESS){
fprintf(stderr, " Can't stop the camera!! \n");
}
else{
printf("dma1394: Data transmission terminated. \n");
}
/*Step 7: Save our image*/
/*===============================================================*/
imagefile=fopen(IMAGE_FILE_NAME, "w");
if(imagefile==NULL){
perror("dma1394: Can't create' "IMAGE_FILE_NAME" ' ");
dc1394_dma_done_with_buffer(&amp;camera);
dc1394_dma_release_camera(handle, &amp;camera);
dc1394_destroy_handle(handle);
return -1;
}
else{
cout&lt;&lt;"dma1394: Saved image in "&lt;&lt;IMAGE_FILE_NAME&lt;&lt;".\n";
}
/*Add pgm file header*/
fprintf(imagefile, "P5\n%u %u 255\n", camera.frame_width, camera.frame_height);
/*write to file*/
fwrite((const char *)camera.capture_buffer, 1, camera.frame_height*camera.frame_width, imagefile);
fclose(imagefile);
printf("dma1394: wrote: " IMAGE_FILE_NAME "\n");
/*Step 8: Close camera*/
/*=============================================================*/
dc1394_dma_done_with_buffer(&amp;camera);
dc1394_dma_release_camera(handle, &amp;camera);
dc1394_destroy_handle(handle);
printf("dma1394: Camera released. Exiting. \n");
//Step END
return 0;
}
</screen>
<para>
Just like the previous example (<xref linkend="example"/>) the program includes the necessary header files(<filename>libraw1394/raw1394.h</filename> and <filename>libdc1394/dc1394_control.h</filename>) and then declare the three variables of the following data type
<itemizedlist>
<listitem><para><varname>dc1394_cameracapture</varname></para></listitem>
<listitem><para><varname>raw1394handle_t</varname></para></listitem>
<listitem><para><varname>nodeid_t *</varname></para></listitem>
</itemizedlist>
After this the following steps are followed which are very similar to the previous example (<xref linkend="example"/>)
<orderedlist>
<listitem> Open ohci and assign handle to it using the function <function>dc1394_create_handle(0)</function></listitem>
<listitem>Get the camera nodes using the function <function>dc1394_get_camera_nodes</function></listitem>
<listitem>Find out various parameters need to be passed during the camera setup. This is done by querying the camera using the following functions
<itemizedlist>
<listitem><function>dc1394_get_iso_channel_and_speed()</function>: To get the channel and speed information</listitem>
<listitem><function>dc1394_get_video_format()</function>: To get the camera format</listitem>
<listitem><function>dc1394_get_video_framerate()</function>: To get the framerate information</listitem>
<listitem><function>dc1394_get_video_mode()</function>: To get the camera mode</listitem>
</itemizedlist>
Also we are required to set the <varname>dma buffers</varname> to 8 and <varname>number of drop frames</varname> to 1.
<para>
Once the values of the parameter have been obtained (framerate,format,mode,channel,speed etc), they are passed in <function>dc1394_dma_setup_capture</function> which then sets up the camera and enables it for capturing video. For DMA you must pass the number of dma buffers and drop frames parameter.</para>
</listitem>
<listitem>After the camera is set, <function>dc1394_start_iso_transmission()</function> is called. This function starts data transactions from the camera to the bus.</listitem>
<listitem>Now capture one frame using <function>dc1394_dma_single_capture()</function>. This function will capture a frame into the dma buffer<para>
After the frame has been grabbed release the dma buffer using <function>dc1394_dma_done_with_buffer()</function>. This is required so that the memory can be reused. It is imperative that <function>dc1394_dma_done_with_buffer()</function> always follows a <function>dma_capture</function> function call</para>
So in order to capture more than one frame the code will be
<screen>
for( i=0;i&lt;100 ;i++)/* to capture 100 images*/
{
dc1394_dma_single_capture(&amp;camera);
dc1394_dma_done_with_buffer(&amp;camera);
}
</screen>
</listitem>
<listitem>Stop listening to the iso channel by calling <function>dc1394_dma_unlisten()</function><para>
Terminate the data transmission by calling <function>dc1394_stop_iso_transmission()</function></para></listitem>
<listitem>Save the image in a file and add a PGM header for viewing using <application>gimp</application>.</listitem>
<listitem>Finally call <function>dc1394_release_camera</function> to release the camera</listitem>
</orderedlist>
</para>
<para>
If DMA is not setup correctly you will get the following error message:
</para>
<para><computeroutput>VIDEO1394_IOC_LISTEN_CHANNEL ioctl failed </computeroutput></para>
<para>
There are various reasons for this error which will be further explained in the Problems section (<xref linkend="common_problems"/>)
</para>
<para>
Thus we can see that the image capture using DMA is not much different from non DMA method. We have compared the functions used in two approaches in the following table.
</para>
<informaltable frame="all">
<tgroup cols="3"><tbody>
<row>
<entry><para>Non DMA steps</para></entry>
<entry><para>DMA steps</para></entry>
<entry><para>Comments</para></entry>
</row>
<row>
<entry><para><function>dc1394_create_handle</function></para></entry>
<entry><para><function>dc1394_create_handle</function></para></entry>
<entry><para>Create handle</para></entry>
</row>
<row>
<entry><para><function>dc1394_get_camera_nodes</function></para></entry>
<entry><para><function>dc1394_get_camera_nodes</function></para></entry>
<entry><para>Get camera nodes</para></entry>
</row>
<row>
<entry><para><function>dc1394_setup_capture</function></para></entry>
<entry><para><function>dc1394_dma_setup_capture</function></para></entry>
<entry><para>Call setup functions to set various parameters of camera</para></entry>
</row>
<row>
<entry><para><function>dc1394_start_iso_transmission</function></para></entry>
<entry><para><function>dc1394_start_iso_transmission</function></para></entry>
<entry><para>Start sending the data from camera to the bus</para></entry>
</row>
<row>
<entry><para><function>dc1394_single_capture</function></para></entry>
<entry><para><function>dc1394_dma_single_capture</function>, <function>dc1394_dma_done_with_buffer</function></para></entry>
<entry><para>Capture one frame</para></entry>
</row>
<row>
<entry><para><function>dc1394_stop_iso_transmission</function></para></entry>
<entry><para><function>dc1394_dma_unlisten</function>, <function>dc1394_stop_iso_transmission</function></para></entry>
<entry><para>Stop sending the data from camera to the bus</para></entry>
</row>
<row>
<entry><para><function>dc1394_release_camera</function>, <function>dc1394_destroy_handle</function></para></entry>
<entry><para><function>dc1394_dma_done_with_buffer</function>, <function>dc1394_dma_release_camera</function>, <function>dc1394_destroy_handle</function></para></entry>
<entry><para>Close the camera</para></entry>
</row>
</tbody></tgroup>
</informaltable>
</sect2>
<sect2 id="get_color">
<title>How to get color images: Bayer Pattern Concepts</title>
@ -927,7 +1205,7 @@ where the values of the parameters for channel, speed, bytes_per_packet, speed,
adding a header (look at the explanation in <xref
linkend="example"/>).</para>
<para>In order to get a colored image, the Bayer Pattern image is
converted to a <emphasis>RGB</emphasis> image. A RGB image is an enhanced version of the Bayer Pattern image; we try to find the value of the two missing colors at each pixel (remember that each pixel of the sensor is covered by Bayer Pattern filter so we get a single color at any pixel by default). This is done by using different algorithms like Nearest Neighbor, Edge Sense, and so on:
converted to a <emphasis>RGB</emphasis> image. A RGB image is an enhanced version of the Bayer Pattern image; we try to find the value of the two missing colors at each pixel (remember that each pixel of the sensor is covered by Bayer Pattern filter so we get a single color at any pixel by default). This is done by using different algorithms like <emphasis>Nearest Neighbor</emphasis>,<emphasis> Edge Sense</emphasis>, and so on:
<figure><title>RAW to RGB</title>
<mediaobject>
<imageobject>
@ -1234,7 +1512,7 @@ quadlet_t qValue;
(<parameter>rgbbuffer</parameter>) will be passed as the destination buffer (the second parameter in <function>BayerNearestNeighbor</function>).</para>
<para>After the buffer has been filled with the RGB values we
write it in the file <filename>image.rgb</filename>.</para>
<para>In order to view this image using <application>Gimp</application>, we need to append a bitmap header. The method we employed was as follows: </para>
<para>In order to view this image using <application>gimp</application>, we need to append a bitmap header. The method we employed was as follows: </para>
<orderedlist>
<listitem><para>Save the RGB image buffer in a file, say, <filename>image.rgb</filename>.</para></listitem>
<listitem><para>Make a bitmap header and save it in a separate
@ -1242,7 +1520,7 @@ quadlet_t qValue;
url="http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html">http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html</ulink> for header details.</para></listitem>
<listitem><para><command>cat bmpheader image.rgb
&gt; bmpfile</command></para></listitem>
<listitem><para>Open <filename>bmpfile</filename> using <application>Gimp</application>.</para></listitem>
<listitem><para>Open <filename>bmpfile</filename> using <application>gimp</application>.</para></listitem>
</orderedlist>
<para>In order to run the program, use the following steps:</para>
<para>
@ -1328,11 +1606,15 @@ be set accordingly.</emphasis></para>
failed</computeroutput> error message being displayed.</para>
</formalpara>
<formalpara>
<title>Solution:</title><para><emphasis>This means that the DMA
support is missing. The error message is a good way to find out
if the DMA support is available or not. This can be done by using the
setup functions that are meant for DMA support (this is how we
found out).</emphasis></para>
<title>Solution: (contributed by Ian and Tim)</title><para><emphasis>There are various reasons for this error message. Type <command>dmesg</command> in the command prompt to gain a better understanding of the problem. Here is a list of problem we ran into
<itemizedlist>
<listitem>Channel 0 is not being used- This means you are listening on the iso channel and then calling a capture function again. Make sure not to call <function>dma_unlisten</function> until you are ready to stop iso transmission.
</listitem>
<listitem>Channel 0 is already being used- This means you have set two camera nodes to the same Channel. Fix your <function>dma_setup_capture()</function>. This could also mean that you have tried to call the setup function more than once without releasing the camera between the calls. This error is more likely to occur when you are working with more than one camera.</listitem>
<listitem>Buffer 0 is already being used- This means that you have not freed the DMA buffer before trying to write to it again. Make sure to alternate <function>dma_done_with_buffer calls with dma_capture_calls</function></listitem>
</itemizedlist>
</emphasis></para>
</formalpara>
</listitem>
<listitem>