Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

V4LCapture.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 /* ---------------------------------------------------------------------- */
00027 /* plugins/camera/v4l/V4LCapture.cpp
00028  *      Improved upon previous V4LCapture class that was in camera/v4l/V4LCapture.cpp
00029  * 
00030  *      V4LCapture object now allows more control by the user in terms of
00031  *      when to start capturing and what to do with the data.
00032  *
00033  *      The data can be passed or taken by any object that knows
00034  *      how to work with the phImage class. (It doesn't take 
00035  *      a rocket scientist to figure it out.)
00036  *
00037  *      When a capture is started, a thread is spawned to handle transfers
00038  *      of the image from the mmapped hw_buffer to the phImage
00039  *      buffer. There is always a full fresh image waiting to be accessed
00040  *      while capturing is being done.
00041  *
00042  *      When the capture is stopped, the phImage buffer retains it's 
00043  *      last frame until the V4LCapture object is destroyed or a new capture 
00044  *      session is started.
00045  * 
00046  * ---------------------------------------------------------------------- *
00047  * TODO:
00048  *  - use capabilities structure to limit image settings.
00049  *  - allow picture format setting while capture is in progress ?
00050  *  
00051  *
00052  *
00053  * ---------------------------------------------------------------------- */
00054 /* ---------------------------------------------------------------------- *
00055  * possible events which each class method/function must check if the 
00056  * event is relevant to the function's proper execution.
00057  * 
00058  *      (1)device open/(2)closed. 
00059  *      (3)capture running/(4)stopped
00060  *      (5)hw buffers mapped/(6)unmapped 
00061  *       
00062  *------------------------------------------------------------------------*/
00063 #ifdef HAVE_CONFIG_H
00064     #include <phissionconfig.h>
00065 #endif
00066 
00067 /* ---------------------------------------------------------------------- */
00068 #if defined(HAVE_STDIO_H)
00069     #include <stdio.h>
00070 #endif
00071 #if defined(HAVE_STDLIB_H)
00072     #include <stdlib.h>
00073 #endif
00074 #if defined(HAVE_STRING_H)
00075     #include <string.h>
00076 #endif
00077 #if defined(HAVE_UNISTD_H)
00078     #include <unistd.h>
00079 #endif
00080 #if defined(HAVE_SYS_FCNTL_H)
00081     #include <sys/fcntl.h>
00082 #endif
00083 #if defined(HAVE_SYS_MMAN_H)
00084     #include <sys/mman.h>
00085 #endif
00086 #if defined(HAVE_SYS_IOCTL_H)
00087     #include <sys/ioctl.h>
00088 #endif
00089 #if defined(HAVE_ERRNO_H)
00090     #include <errno.h>
00091 #endif
00092 #if defined(HAVE_LINUX_VIDEODEV_H)
00093     #include <linux/videodev.h>
00094 #endif
00095 
00096 #define V4L_MAX_HWBUFFERS 32
00097 
00098 /* ---------------------------------------------------------------------- */
00099 #include <phStandard.h>
00100 #include <ImageConversions.h>
00101 #include <V4LCapture.h>
00102 
00103 #define TIMESTUFF() 0
00104 #if TIMESTUFF()
00105     #include <phTime.h>
00106 #endif
00107 
00108 #include <phError.h>
00109 #include <phMemory.h>
00110 #include <phPrint.h>
00111 
00112 #ifdef __cplusplus
00113 extern "C" {
00114 #endif
00115            
00116 /* ---------------------------------------------------------------------- */
00117 void v4l_print_video_capability( struct video_capability caps )
00118 {   
00119     phPRINT("struct video_capability\n[\n");
00120     phPRINT("\tname         : %s\n",    caps.name );
00121     phPRINT("\ttype         : 0x%08x\n",    caps.type );
00122     phPRINT("\t(type) ");
00123     if (caps.type & VID_TYPE_CAPTURE)       phPRINT("CAPTURE ");
00124     if (caps.type & VID_TYPE_TUNER)         phPRINT("TUNER ");
00125     if (caps.type & VID_TYPE_TELETEXT)      phPRINT("TELETEXT ");
00126     if (caps.type & VID_TYPE_OVERLAY)       phPRINT("OVERLAY ");
00127     if (caps.type & VID_TYPE_CHROMAKEY)     phPRINT("CHROMAKEY ");
00128     if (caps.type & VID_TYPE_CLIPPING)      phPRINT("CLIPPING ");
00129     if (caps.type & VID_TYPE_FRAMERAM)      phPRINT("FRAMERAM ");
00130     if (caps.type & VID_TYPE_SCALES )       phPRINT("SCALES  ");
00131     if (caps.type & VID_TYPE_MONOCHROME)    phPRINT("MONOCHROME ");
00132     if (caps.type & VID_TYPE_SUBCAPTURE )   phPRINT("SUBCAPTURE  ");
00133     if (caps.type & VID_TYPE_MPEG_DECODER)  phPRINT("MPEG_DECODER ");
00134     if (caps.type & VID_TYPE_MPEG_ENCODER)  phPRINT("MPEG_ENCODER ");
00135     if (caps.type & VID_TYPE_MJPEG_DECODER) phPRINT("MJPEG_DECODER ");
00136     if (caps.type & VID_TYPE_MJPEG_ENCODER) phPRINT("MJPEG_ENCODER ");
00137     phPRINT("\n");
00138     phPRINT("\tchannels     : %d\n",    caps.channels );
00139     phPRINT("\taudios       : %d\n",    caps.audios );
00140     phPRINT("\tmax width    : %d\n",    caps.maxwidth );
00141     phPRINT("\tmax height   : %d\n",    caps.maxheight );
00142     phPRINT("\tmin width    : %d\n",    caps.minwidth );
00143     phPRINT("\tmin height   : %d\n",    caps.minheight );
00144     phPRINT("]\n");
00145 }
00146 
00147 /* ---------------------------------------------------------------------- */
00148 void v4l_print_video_channel( struct video_channel chan )
00149 {   
00150     phPRINT("struct video_channel\n[\n");
00151     phPRINT("\tchannel  : %d\n",chan.channel);
00152     phPRINT("\tname     : %s\n",chan.name);
00153     phPRINT("\ttuners   : %d\n",chan.tuners);
00154     phPRINT("\tflags    : 0x%08x\n",chan.flags);
00155     phPRINT("\t  tuner  : %d\n",chan.flags & VIDEO_VC_TUNER ? 1 : 0);
00156     phPRINT("\t  audio  : %d\n",chan.flags & VIDEO_VC_AUDIO ? 1 : 0);
00157     phPRINT("\ttype     : %hu\n",chan.type);
00158     phPRINT("\t  tv     : %d\n",chan.type & VIDEO_TYPE_TV ? 1 : 0);
00159     phPRINT("\t  camera : %d\n",chan.type & VIDEO_TYPE_CAMERA ? 1 : 0);
00160     phPRINT("\tnorm     : %hu\n",chan.norm);
00161     phPRINT("\t(norm) ");
00162     if (chan.norm == VIDEO_MODE_PAL) phPRINT("PAL ");
00163     if (chan.norm == VIDEO_MODE_NTSC) phPRINT("NTSC ");
00164     if (chan.norm == VIDEO_MODE_SECAM) phPRINT("SECAM ");
00165     if (chan.norm == VIDEO_MODE_AUTO) phPRINT("AUTO ");
00166     phPRINT("\n]\n");
00167 }
00168     
00169 /* ---------------------------------------------------------------------- */
00170 void v4l_print_video_picture( struct video_picture pict )
00171 {   
00172     char *palette_name = NULL;
00173     char *palette_type = NULL;
00174     const char *palette_names[] = {
00175                 "unknown",
00176                 "VIDEO_PALETTE_GREY",
00177                 "VIDEO_PALETTE_HI240",
00178                 "VIDEO_PALETTE_RGB565",
00179                 "VIDEO_PALETTE_RGB24",
00180                 "VIDEO_PALETTE_RGB32",
00181                 "VIDEO_PALETTE_RGB555",
00182                 "VIDEO_PALETTE_YUV422",
00183                 "VIDEO_PALETTE_YUYV",
00184                 "VIDEO_PALETTE_UYVY",
00185                 "VIDEO_PALETTE_YUV420",
00186                 "VIDEO_PALETTE_YUV411",
00187                 "VIDEO_PALETTE_RAW",
00188                 "VIDEO_PALETTE_YUV422P",
00189                 "VIDEO_PALETTE_YUV411P",
00190                 "VIDEO_PALETTE_YUV420P",
00191                 "VIDEO_PALETTE_YUV410P" };
00192 
00193 
00194     phPRINT("struct video_picture\n[\n");
00195     phPRINT("\tbrightness   : %hu %f%%\n",
00196             pict.brightness,
00197             (pict.brightness / 65535.0) * 100
00198             );
00199     phPRINT("\thue          : %hu %f%%\n",
00200             pict.hue,
00201             (pict.hue / 65535.0) * 100
00202             );
00203     phPRINT("\tcolor        : %hu %f%%\n",
00204             pict.colour,
00205             (pict.colour / 65535.0) * 100
00206             );
00207     phPRINT("\tcontrast     : %hu %f%%\n",
00208             pict.contrast,
00209             (pict.contrast / 65535.0) * 100
00210             );
00211     phPRINT("\twhiteness    : %hu %f%%\n",
00212             pict.whiteness,
00213             (pict.whiteness / 65535.0) * 100
00214             );
00215     phPRINT("\tdepth        : %hu bits\n",
00216             pict.depth
00217             );
00218     if (pict.palette >= VIDEO_PALETTE_PLANAR)
00219         palette_type = "PLANAR";
00220     else if (pict.palette >= VIDEO_PALETTE_COMPONENT)
00221         palette_type = "COMPONENT";
00222     else
00223         palette_type = "PACKED";
00224     if (pict.palette <= VIDEO_PALETTE_YUV410P)
00225         palette_name = (char *)palette_names[pict.palette];
00226     else
00227         palette_name = "unknown";
00228     phPRINT("\tpalette      : %hu %s %s\n",
00229             pict.palette,
00230             palette_name, palette_type
00231             );
00232     phPRINT("]\n");
00233 }
00234     
00235 /* ---------------------------------------------------------------------- */
00236 void v4l_print_video_mmap( struct video_mmap mmap )
00237 {   
00238     phPRINT("struct video_mmap\n[\n");
00239     phPRINT("\tframe    : %d\n",   mmap.frame   );
00240     phPRINT("\theight   : %d\n",   mmap.height  );
00241     phPRINT("\twidth    : %d\n",   mmap.width   );
00242     phPRINT("\tformat   : %u\n",   mmap.format  );
00243     phPRINT("]\n");
00244 }
00245 
00246 /* ---------------------------------------------------------------------- */
00247 void v4l_print_video_mbuf( struct video_mbuf mbuf )
00248 {   
00249     int i = 0;
00250     phPRINT("struct video_mbuf\n[\n");
00251     phPRINT("\tsize     : %d\n", mbuf.size );
00252     phPRINT("\tframes   : %d\n", mbuf.frames );
00253     for (i = 0; i < VIDEO_MAX_FRAME; i++ )
00254     {
00255         phPRINT("\t%d:{ %12d }",i,mbuf.offsets[i]);
00256         if (((i + 1) % 3) == 0) phPRINT("\n");
00257     }
00258     phPRINT("\n]\n");
00259 }
00260 
00261 /* ---------------------------------------------------------------------- */
00262 void v4l_print_video_window( struct video_window win )
00263 {   
00264     int i = 0;
00265     struct video_clip       *clip = NULL;
00266     
00267     phPRINT("struct video_window\n[\n");
00268     phPRINT("\tx        : %u\n",win.x);
00269     phPRINT("\ty        : %u\n",win.y);
00270     phPRINT("\twidth    : %u\n",win.width);
00271     phPRINT("\theight   : %u\n",win.height);
00272     phPRINT("\tchromakey: %u\n",win.chromakey);
00273     phPRINT("\tflags    : %u\n",win.flags);
00274     phPRINT("\tclipcount: %d\n",win.clipcount);
00275     phPRINT("\tclips    : %p\n",win.clips);
00276     
00277     clip = win.clips;
00278     for (i = 0; (i < win.clipcount) && (clip != NULL); i++ )
00279     {
00280         phPRINT("\t------------------------------\n");
00281         phPRINT("\t  i        : %d\n",i);
00282         phPRINT("\t  x        : %d\n",clip->x);
00283         phPRINT("\t  y        : %d\n",clip->y);
00284         phPRINT("\t  width    : %d\n",clip->width);
00285         phPRINT("\t  height   : %d\n",clip->height);
00286         clip = clip->next;
00287     }
00288 
00289     phPRINT("\n]\n");
00290 }
00291     
00292 /* ---------------------------------------------------------------------- */
00293 void v4l_print_video_tuner( struct video_tuner tuner )
00294 {   
00295     phPRINT("struct video_tuner\n[\n");
00296     phPRINT("\ttuner    :%d\n",tuner.tuner);
00297     phPRINT("\tname     :%s\n",tuner.name);
00298     phPRINT("\trangelow :%lu\n",tuner.rangelow);
00299     phPRINT("\trangehigh:%lu\n",tuner.rangehigh);
00300     phPRINT("\tflags    :%u\n",tuner.flags);
00301     phPRINT("\t(flags) ");
00302     if (tuner.flags & VIDEO_TUNER_PAL) phPRINT("PAL ");
00303     if (tuner.flags & VIDEO_TUNER_NTSC) phPRINT("NTSC ");
00304     if (tuner.flags & VIDEO_TUNER_SECAM) phPRINT("SECAM ");
00305     if (tuner.flags & VIDEO_TUNER_LOW) phPRINT("LOW ");
00306     if (tuner.flags & VIDEO_TUNER_NORM) phPRINT("NORM ");
00307     if (tuner.flags & VIDEO_TUNER_STEREO_ON) phPRINT("STEREO_ON ");
00308     if (tuner.flags & VIDEO_TUNER_RDS_ON) phPRINT("RDS_ON ");
00309     if (tuner.flags & VIDEO_TUNER_MBS_ON) phPRINT("MBS_ON ");
00310     phPRINT("\n");
00311     phPRINT("\tmode     : %hu\n",tuner.mode); 
00312     phPRINT("\t(mode) ");
00313     if (tuner.flags & VIDEO_MODE_PAL) phPRINT("PAL ");
00314     if (tuner.flags & VIDEO_MODE_NTSC) phPRINT("NTSC ");
00315     if (tuner.flags & VIDEO_MODE_SECAM) phPRINT("SECAM ");
00316     if (tuner.flags & VIDEO_MODE_AUTO) phPRINT("AUTO ");
00317     phPRINT("\n");
00318     phPRINT("\tsignal   : %hu\n",tuner.signal);
00319 
00320     phPRINT("\n]\n");
00321 }
00322 
00323 /* ---------------------------------------------------------------------- */
00324 /* TODO: check object's m_info for != NULL everywhere */
00325 struct phV4LCaptureInfo_t
00326 {
00327     /* this structure will hold the capabilities of the 
00328      * capture device when the device is open */
00329     struct video_capability m_device_caps;
00330     
00331     /* This is used when capturing from the source 
00332      * and specifies: frame, width, height, depth */
00333     struct video_mmap       m_device_mmap;
00334 
00335     /* This holds the features of the channel including,
00336      * the type of signal(NTSC,PAL,etc.) and channel num */
00337     struct video_channel    m_device_chan;
00338 
00339     struct video_picture    m_device_picture;
00340     
00341     struct video_mbuf       m_device_mbuf;
00342 
00343     struct video_window     m_device_win;
00344 
00345     struct video_tuner      m_device_tuner;
00346 };
00347 
00348 #ifdef __cplusplus
00349 }
00350 #endif
00351 
00352 /* ---------------------------------------------------------------------- *
00353  * V4LCapture Constructor - This is called when a new instance of the V4LCapture object
00354  * is created.
00355  * 
00356  * PRE: Who knows
00357  * POST: All variables have been initialized to 0, or NULL.
00358  *       channelSpec.channel = 1, m_device_mmap.width = 160,
00359  *       m_device_mmap.height = 120, device = "/dev/video0", h
00360  *       hw_bufferCount = 2
00361  *
00362  * ---------------------------------------------------------------------- */
00363 V4LCapture::V4LCapture(char *path)
00364 {
00365     phFUNCTION("V4LCapture::V4LCapture")
00366     
00367     rc = this->lock();
00368     phPRINT_RC(rc,NULL,"this->lock()");
00369    
00370     this->setName("V4LCapture");
00371     
00372     this->m_changed_settings = 0;
00373     this->m_changed_channel = 0;
00374 
00375     this->m_info = (struct phV4LCaptureInfo_t *)phCalloc(1,
00376                         sizeof(struct phV4LCaptureInfo_t));
00377     phPRINT_PTR(this->m_info,"phCalloc",
00378               "phCalloc failed to alloc phV4LCaptureInfo");
00379     
00380     phMemset(&this->m_info->m_device_caps,   0,sizeof(struct video_capability));
00381     phMemset(&this->m_info->m_device_mmap,   0,sizeof(struct video_mmap));
00382     phMemset(&this->m_info->m_device_chan,   0,sizeof(struct video_channel));
00383     phMemset(&this->m_info->m_device_picture,0,sizeof(struct video_picture));
00384     phMemset(&this->m_info->m_device_mbuf,   0,sizeof(struct video_mbuf));
00385     phMemset(&this->m_info->m_device_win,    0,sizeof(struct video_window));
00386     phMemset(&this->m_info->m_device_tuner,  0,sizeof(struct video_tuner));
00387 
00388     this->m_deviceOpen = 0;
00389     this->m_device_fd = 0;
00390     
00391     this->m_hw_mmapped = 0;
00392     this->m_hw_buffer = NULL;
00393     this->m_hw_bufferSize = 0;
00394     /* Init the buffer count to 2, not the maximum, because the lag involved
00395      * with > 2 buffers can be annoying */
00396     this->m_hw_bufferCount = 3;
00397     
00398     this->m_image_size = 0;
00399 
00400     if (path != NULL)
00401     {
00402         this->setPath(path);
00403     }
00404     else
00405     {
00406         this->setPath("/dev/video0");
00407     }
00408 
00409     /*
00410     this->m_info->m_device_picture.brightness   = 65536 / 2;
00411     this->m_info->m_device_picture.hue          = 65536 / 2;
00412     this->m_info->m_device_picture.colour       = 65536 / 2;
00413     this->m_info->m_device_picture.contrast     = 65536 / 2;
00414     this->m_info->m_device_picture.whiteness    = 65536 / 2;
00415     this->m_info->m_device_picture.palette      = VIDEO_PALETTE_RGB24;
00416     this->m_info->m_device_picture.depth        = 24;
00417     */    
00418     
00419     /*
00420     this->m_info->m_device_mmap.width = 160;
00421     this->m_info->m_device_mmap.height = 120;
00422     this->m_info->m_device_chan.channel = 1;
00423     */
00424     
00425     /* this->setFormat(phImageRGB24); */
00426     this->m_current_format = this->m_format;
00427 
00428     /* This applies the default (1) picture/image settings[w,h,format,etc.]
00429      * (2) channel settings  */
00430     this->applySettings();
00431     
00432     /* opening the device must be explicitly done */
00433     /* capturing must be explicitly done. */
00434 /*error:*/
00435     rc = this->unlock();
00436     phPRINT_RC(rc,NULL,"this->unlock()");
00437     
00438     return;
00439 }
00440 
00441 /* ---------------------------------------------------------------------- *
00442  * V4LCapture Destructor - Called when the V4LCapture object is freed/destroyed. Yup.
00443  * 
00444  * PRE: Stuff. Like allocations and Stuff.
00445  * 
00446  * POST: All allocations will be freed, the capture stopped, the 
00447  * device closed and mappings unmapped.
00448  * ---------------------------------------------------------------------- */
00449 V4LCapture::~V4LCapture ()
00450 {
00451     phFUNCTION("V4LCapture::~V4LCapture")
00452   
00453     rc = this->lock();
00454     phPRINT_RC(rc,NULL,"this->lock()");
00455 
00456     if (this->isRunning())
00457     {
00458         /* this unmaps the hw_buffer and closes the device */
00459         rc = this->stop();
00460         phPRINT_RC(rc,NULL,"this->stop()");
00461     }
00462    
00463     if (this->isOpen())
00464     {
00465         rc = this->close();
00466         phPRINT_RC(rc,NULL,"this->close()");
00467     }
00468  
00469     phFree(this->m_info);
00470     
00471     rc = this->unlock();
00472     phPRINT_RC(rc,NULL,"this->unlock()");
00473 }
00474     
00475 /* ---------------------------------------------------------------------- */
00476 /* open - This opens the device named in this->m_path as a V4LCapture
00477  *  file descriptor.
00478  *
00479  * This is called from phImageCapture::startCapturing()
00480  * 
00481  * PRE: V4LCapture Object has been created. 
00482  *      m_device_fd = 0 (closed), 
00483  *      m_path is some valid device name (default: /dev/video0)
00484  *      hardware buffer isn't mmapped.
00485  * 
00486  * POST: m_device_fd > 0 (opened)
00487  *      hardware buffers are still not mmapped
00488  *      Object is ready to start capturing with a call to start.
00489  */
00490 /* ---------------------------------------------------------------------- */
00491 /* start - This starts the capture session.
00492  * 
00493  *  [OLD comment that I'll put here for now]
00494  *
00495  * PRE: The device is open. The capture hasn't been started yet.
00496  *  HW Buffers aren't mapped.
00497  *
00498  * POST: The HW Buffers are mapped.
00499  *  A new thread has been spawned to manage the capturing of the data.
00500  *  The sw_buffer is being updated and is ready to have data copied from 
00501  *  it.
00502  */
00503 /* ---------------------------------------------------------------------- */
00504 int V4LCapture::open(char *path)
00505 {
00506     phFUNCTION("V4LCapture::open")
00507 
00508     rc = this->lock();
00509     phPRINT_RC(rc,NULL,"this->lock()");
00510    
00511     /* device is already open, close it */
00512     if (this->isOpen())
00513     {
00514         rc = this->close();
00515         phPRINT_RC(rc,NULL,"this->close()");
00516     }
00517   
00518     if (path != NULL)
00519     {
00520         rc = this->setPath( path );
00521         phPRINT_RC(rc,NULL,"this->setPath( path:%s )",path);
00522     }
00523    
00524     if ((this->m_device_fd <= 0) && (this->getPath() != NULL))
00525     {
00526         /* open the video device */
00527         rc = (this->m_device_fd = ::open((char*)this->getPath(), O_RDWR));
00528         phCHECK_RC(rc,"::open",
00529                 "Error: opening video device (%s)",
00530                 (char*)this->getPath()
00531                 );
00532 
00533         this->ioctl_get_capability();
00534         this->m_info->m_device_chan.norm = VIDEO_MODE_NTSC;
00535         this->ioctl_set_channel();
00536         this->ioctl_set_tuner();
00537         this->ioctl_get_capability();
00538         this->ioctl_set_picture();
00539         this->ioctl_set_window();
00540         
00541         /* Try to apply all the settings to the V4L device */
00542         ph_int32_array_append(this->m_changed_array,phCHANGE_INIT);
00543         this->applySettings();
00544         
00545         this->m_deviceOpen = 1;
00546     }
00547 
00548     rc = this->unlock();
00549     phPRINT_RC(rc,NULL,"this->unlock()");
00550     
00551     return phSUCCESS;
00552 error:
00553     rc = this->unlock();
00554     phPRINT_RC(rc,NULL,"this->unlock()");
00555     
00556     return phFAIL;
00557 }
00558 
00559 /* ---------------------------------------------------------------------- */
00560 int V4LCapture::isOpen() 
00561 { 
00562     return ((this->m_deviceOpen > 0) ? 1 : 0); 
00563 }    
00564 
00565 /* ---------------------------------------------------------------------- */
00566 /* close - closes the video device file descriptor. Also cleans
00567  *  up any other class items like mappings and running threads.
00568  *
00569  * This is called from phImageCapture::stopCapturing()
00570  * 
00571  * PRE: m_device_fd > 0 (device open)
00572  *      m_deviceOpen > 0
00573  * POST: All mappings unmapped. All threads cleaned up. All necessary 
00574  *  variables reinitialized as in Constructor.
00575  */
00576 /* ---------------------------------------------------------------------- */
00577 int V4LCapture::close()
00578 {
00579     phFUNCTION("V4LCapture::close")
00580    
00581     rc = this->lock();
00582     phPRINT_RC(rc,NULL,"this->lock()");
00583     
00584     if (this->m_hw_mmapped == 1)
00585     {
00586         phERR_PRINT("What the hell? hw_mapped == 1\n");
00587     }
00588     
00589     if (this->m_device_fd > 0)
00590     {
00591         /* close the video device */
00592         rc = ::close(this->m_device_fd);
00593         phCHECK_RC(rc, "::close",
00594                 "Error: closing video device (%s)",
00595                 this->getPath()
00596                 );
00597         
00598         memset(&this->m_info->m_device_caps,
00599                0,sizeof(struct video_capability));
00600         
00601         /* These are reset last */
00602         this->m_device_fd = 0;
00603         this->m_deviceOpen = 0;
00604     }
00605     else if (this->m_device_fd < 0)
00606     {
00607         /* These are reset last */
00608         this->m_device_fd = 0;
00609         this->m_deviceOpen = 0;
00610     }
00611    
00612     rc = this->unlock();
00613     phPRINT_RC(rc,NULL,"this->unlock()");
00614     
00615     return phSUCCESS;
00616     
00617 error:
00618     rc = this->unlock();
00619     phPRINT_RC(rc,NULL,"this->unlock()");
00620     
00621     return phFAIL;
00622 }
00623 
00624 /* ---------------------------------------------------------------------- */
00625 /* setBufferCount - sets the number of frame buffers to set at the 
00626  *  hardware/kernel level of aquisition; potentially speeds things up if
00627  *  multiple buffers are supported.
00628  * 
00629  * PRE: device isn't open (m_device_fd = 0)
00630  *      hw buffer isn't mmapped
00631  *      capture is stopped/no captures in progress
00632  *      buffer_count > 0 and <= 32
00633  * POST:
00634  *      buffer_count is stored in hw_bufferCount
00635  */
00636 /* ---------------------------------------------------------------------- */
00637 int V4LCapture::setBufferCount( uint32_t buffer_count )
00638 {
00639     phFUNCTION("V4LCapture::setBufferCount")
00640 
00641     rc = this->lock();
00642     phPRINT_RC(rc,NULL,"this->lock()");
00643    
00644     /* The hw_bufferCount won't be applied until the next time the
00645      * capturing thread is started */
00646     if (buffer_count > V4L_MAX_HWBUFFERS)
00647         buffer_count = V4L_MAX_HWBUFFERS;
00648     
00649     this->m_hw_bufferCount = buffer_count;
00650     
00651     rc = this->unlock();
00652     phPRINT_RC(rc,NULL,"this->unlock()");
00653     
00654     return phSUCCESS;
00655     /*
00656 error:
00657     rc = this->unlock();
00658     phPRINT_RC(rc,NULL,"this->unlock()");
00659     
00660     return phFAIL;
00661     */
00662 }
00663 
00664 /* ---------------------------------------------------------------------- */
00665 uint32_t V4LCapture::getBufferCount() 
00666 { 
00667     return this->m_hw_bufferCount; 
00668 }
00669 
00670 /* ---------------------------------------------------------------------- */
00671 /* getWidth, getHeight, getFormat, getImageSize:
00672  * 
00673  *  if the device is open, then return the value in V4LCapture...
00674  * otherwise we won't have a consistent value with what the h/w/sz/f
00675  * is supposed to be since some of the V4LCapture fields don't get set
00676  * until the device is open but m_height is always set. Then, when
00677  * the device is open, captureSpec reflects the current setting
00678  * since the height can't be changed without closing the device...
00679  * at least not yet */
00680 /* ---------------------------------------------------------------------- */
00681 int V4LCapture::getWidth() 
00682 {
00683     if (this->m_device_fd > 0)
00684     {
00685         return this->m_info->m_device_mmap.width; 
00686     }
00687     else
00688     {
00689         return this->phImageCapture::getWidth();
00690     }
00691 }
00692 /* ---------------------------------------------------------------------- */
00693 int V4LCapture::getHeight() 
00694 {
00695     if (this->m_device_fd > 0)
00696     {
00697         return this->m_info->m_device_mmap.height; 
00698     }
00699     else
00700     {
00701         return this->phImageCapture::getHeight();
00702     }
00703 }
00704 /* ---------------------------------------------------------------------- */
00705 int32_t V4LCapture::getFormat() 
00706 { 
00707     if (this->m_device_fd > 0)
00708     {
00709         return this->m_current_format; 
00710     }
00711     else
00712     {
00713         return this->phImageCapture::getFormat(); 
00714     }
00715 }
00716 /* ---------------------------------------------------------------------- */
00717 uint32_t V4LCapture::getImageSize() 
00718 { 
00719     if (this->m_device_fd > 0)
00720     {
00721         return this->m_image_size; 
00722     }
00723     else
00724     {
00725         return this->phImageCapture::getImageSize();
00726     }
00727 }
00728 
00729 /* ---------------------------------------------------------------------- */
00730 /*  - 
00731  * 
00732  */
00733 /* ---------------------------------------------------------------------- */
00734 int V4LCapture::unmapHWBuffer()
00735 {
00736     phFUNCTION("V4LCapture::unmapHWBuffer")
00737     uint32_t i = 0;
00738 
00739     rc = this->lock();
00740     phPRINT_RC(rc,NULL,"this->lock()");
00741     
00742     /* This is a must. Check all input parameters; raise an error is needed */
00743     if (this->isCapturing())
00744     {
00745         phCHECK_RC(-1,NULL,"Capture still in progress. Stop capturing first.");
00746     }
00747     
00748     if (this->m_hw_mmapped == 0)
00749     {
00750         goto success;
00751     }
00752     
00753     /* TODO: SYNC with all hw buffers */
00754     for (i = 0; i < this->m_hw_bufferCount; i++)
00755     {
00756         m_info->m_device_mmap.frame = i;
00757         /*phPRINT("ioctl:VIDIOCSYNC\n");*/
00758         rc = ioctl(this->m_device_fd, VIDIOCSYNC, 
00759                    &(this->m_info->m_device_mmap));
00760     }    
00761     
00762     /* Reset the frame index because the old frame index is
00763      * likely to be obsolete */
00764     this->m_info->m_device_mmap.frame  = 0;
00765     
00766     if (this->m_hw_mmapped == 1)
00767     {
00768         if ((this->m_hw_buffer != NULL) && (this->m_hw_bufferSize > 0))
00769         {
00770             rc = munmap((void *)this->m_hw_buffer, this->m_hw_bufferSize);
00771             phPRINT_RC(rc,"munmap failed",
00772                      "munmap(%p,%u);",
00773                      this->m_hw_buffer,
00774                      this->m_hw_bufferSize );
00775         }
00776        
00777         this->m_hw_buffer = NULL;
00778         this->m_hw_bufferSize = 0;
00779         this->m_hw_mmapped = 0;
00780     }
00781 
00782 success:
00783     rc = this->unlock();
00784     phPRINT_RC(rc,NULL,"this->unlock()");
00785     
00786     return phSUCCESS;
00787 error:
00788     rc = this->unlock();
00789     phPRINT_RC(rc,NULL,"this->unlock()");
00790     
00791     return phFAIL;
00792 }
00793 
00794 /* ---------------------------------------------------------------------- */
00795 /*  - 
00796  * 
00797  */
00798 /* ---------------------------------------------------------------------- */
00799 int V4LCapture::mapHWBuffer()
00800 {
00801     phFUNCTION("V4LCapture::mapHWBuffer")
00802     intmax_t    map_rc = 0;
00803     void        *vrc = NULL;
00804 
00805     rc = this->lock();
00806     phPRINT_RC(rc,NULL,"this->lock()");
00807     
00808     if (this->m_device_fd <= 0)
00809     {
00810         phERR_PRINT("this->m_device_fd <= 0\n");
00811     }
00812     
00813     if (this->m_image_size <= 0)
00814     {
00815         phERR_PRINT("this->m_image_size <= 0\n");
00816     }
00817 
00818     /* Automatically unmap it */
00819     if (this->m_hw_mmapped == 1)
00820     {
00821         rc = unmapHWBuffer();
00822         phPRINT_RC(rc,NULL,"unmapHWBuffer");
00823     }
00824  
00825     memset( &this->m_info->m_device_win, 0, sizeof( struct video_window ) );
00826     this->m_info->m_device_win.width = this->m_info->m_device_mmap.width;
00827     this->m_info->m_device_win.height = this->m_info->m_device_mmap.height;
00828 
00829     if (this->m_device_fd > 0)
00830     {
00831         rc = this->ioctl_set_window();
00832         phPRINT_RC(rc,NULL,"ioctl_set_window");
00833     }
00834     
00835     /* Set the video buffer data */
00836     rc = this->ioctl_get_mbuf();
00837     phCHECK_RC(rc,NULL,"ioctl_get_mbuf");
00838 
00839     /* Make sure the hardware buffer count isn't greater than 
00840      * what is allowed by the just queried device */
00841     if (this->m_hw_bufferCount > 
00842         (uint32_t)this->m_info->m_device_mbuf.frames)
00843     {
00844         if (!(((uint32_t)this->m_info->m_device_mbuf.frames) > 
00845                                             V4L_MAX_HWBUFFERS))
00846             this->m_hw_bufferCount = this->m_info->m_device_mbuf.frames;
00847     }
00848 
00849     /* map the memory being used to grab the images */
00850     this->m_hw_bufferSize = this->m_info->m_device_mbuf.size;
00851     this->m_hw_buffer = (uint8_t *)(vrc = mmap(NULL,
00852                                             this->m_hw_bufferSize, 
00853                                             PROT_READ | PROT_WRITE, 
00854                                             MAP_SHARED, 
00855                                             this->m_device_fd, 
00856                                             0)); 
00857     /* must cast to intmax_t because of 64bit vs. 32bit processor addrs */
00858     map_rc = (intmax_t)vrc;
00859     if (map_rc == -1)
00860     {
00861         phERROR_PRINT("mmap",
00862                     "*** ERROR (rc:%p)*** Error: mmap\n",
00863                     this->m_hw_buffer);
00864         DEBUG_PRINT("%p\n",this->m_hw_buffer);
00865         
00866         this->m_hw_buffer = NULL;
00867         
00868         goto error;
00869     }
00870     
00871     /* let the destructor know to free using munmap */
00872     this->m_hw_mmapped = 1;
00873 
00874     rc = this->unlock();
00875     phPRINT_RC(rc,NULL,"this->unlock()");
00876     
00877     return phSUCCESS;
00878 error:
00879     rc = this->unlock();
00880     phPRINT_RC(rc,NULL,"this->unlock()");
00881     
00882     return phFAIL;
00883 }
00884 
00885 /* ---------------------------------------------------------------------- */
00886 int V4LCapture::remapHWBuffer()
00887 {
00888     phFUNCTION("V4LCapture::remapHWBuffer")
00889 
00890     rc = this->lock();
00891     phPRINT_RC(rc,NULL,"this->lock()");
00892     
00893     rc = this->unmapHWBuffer();
00894   
00895     rc = this->mapHWBuffer();
00896     phPRINT_RC(rc,NULL,"mapHWBuffer() failed");
00897     
00898     rc = this->unlock();
00899     phPRINT_RC(rc,NULL,"this->unlock()");
00900     
00901     return phSUCCESS;
00902     /*
00903 error:
00904     rc = this->unlock();
00905     phPRINT_RC(rc,NULL,"this->unlock()");
00906     
00907     return phFAIL;
00908     */
00909 }
00910 
00911 
00912 /* ---------------------------------------------------------------------- */
00913 /* m_info->m_device_picture and this are locked upon entry */
00914 /* ---------------------------------------------------------------------- */
00915 int V4LCapture::onApplySettings()
00916 {
00917     phFUNCTION("V4LCapture::onApplySettings")
00918     int retrc = phSUCCESS;
00919 
00920     int ch_init     = 0;
00921     int ch_b        = 0;
00922     int ch_hue      = 0;
00923     int ch_color    = 0;
00924     int ch_con      = 0;
00925     int ch_white    = 0;
00926     int ch_channel  = 0;
00927     int ch_tuner    = 0;
00928     int ch_h        = 0;
00929     int ch_w        = 0;
00930     int ch_f        = 0;
00931     int ch_p        = 0;
00932    
00933     ch_init = ph_int32_array_find(this->m_changed_array, phCHANGE_INIT,NULL);
00934     /* 
00935      * this->m_changed_array contains the list of changes that are to 
00936      *  be applied.
00937      *
00938      * This method will call phImageCapture::onApplySettings which will empty
00939      * the array so that settings are applied only once.
00940      */
00941     
00942     /* Copy the image settings into the V4L structure */
00943     ch_b = ph_int32_array_find(this->m_changed_array,       phCHANGE_BRIGHTNESS,
00944                             NULL);
00945     ch_hue = ph_int32_array_find(this->m_changed_array,     phCHANGE_HUE,
00946                             NULL);
00947     ch_color = ph_int32_array_find(this->m_changed_array,   phCHANGE_COLOR,
00948                             NULL);
00949     ch_con = ph_int32_array_find(this->m_changed_array,     phCHANGE_CONTRAST,
00950                             NULL);
00951     ch_white = ph_int32_array_find(this->m_changed_array,   phCHANGE_WHITENESS,
00952                             NULL);
00953     if (ch_init > 0) ch_b = ch_hue = ch_color = ch_con = ch_white = 1;
00954     if ((ch_b > 0) || (ch_hue > 0) || (ch_color > 0) || 
00955         (ch_con > 0) || (ch_white > 0))
00956     {
00957         this->m_changed_settings = 1;
00958         if (ch_b > 0)
00959             this->m_info->m_device_picture.brightness   = this->m_brightness;
00960         if (ch_hue > 0)
00961             this->m_info->m_device_picture.hue          = this->m_hue;
00962         if (ch_color > 0)
00963             this->m_info->m_device_picture.colour       = this->m_color;
00964         if (ch_con > 0)
00965             this->m_info->m_device_picture.contrast     = this->m_contrast;
00966         if (ch_white > 0)
00967             this->m_info->m_device_picture.whiteness    = this->m_whiteness;
00968     }
00969     
00970     /*--------------------------------------------------------------------*
00971      * From linux/Documentation/video4linux/API.html:
00972      *
00973      * "Each channel can be queries with the VIDIOCGCHAN ioctl call. 
00974      * Before invoking this function the caller must set the channel 
00975      * field to the channel that is being queried. On return the 
00976      * struct video_channel is filled in with information about the 
00977      * nature of the channel itself."
00978      *--------------------------------------------------------------------*/
00979     ch_channel = ph_int32_array_find(this->m_changed_array,phCHANGE_CHANNEL,
00980                                     NULL);
00981     if (((ch_channel > 0) || (ch_init > 0)) && (this->m_channel >= 0))
00982     {
00983         this->m_info->m_device_chan.channel = this->m_channel;
00984         this->m_changed_channel = 1;
00985     }
00986     /* else, the channel is < 0 or the current chn # */
00987     
00988 
00989     /* settings that require the capture to not be in progress for the 
00990      * V4LCapture settings changes to be applied */
00991     ch_h = ph_int32_array_find(this->m_changed_array, phCHANGE_HEIGHT, NULL);
00992     ch_w = ph_int32_array_find(this->m_changed_array, phCHANGE_WIDTH, NULL);
00993     ch_f = ph_int32_array_find(this->m_changed_array, phCHANGE_FORMAT, NULL);
00994 
00995     if (ch_init > 0) ch_h = ch_w = ch_f = 1;
00996 
00997     if ((ch_h > 0) || (ch_w > 0) || (ch_f > 0))
00998     {
00999         /* if the retrc variable isn't set to 1, then copy these 
01000          * into the private values for the V4LCapture class */
01001         /* Settings not applied until restart */
01002         if ((!this->isRunning()) && (this->m_hw_mmapped == 0))
01003         {
01004             int changed_image_dimensions = 0;
01005             
01006             /* width and height will be checked for > 0 and
01007              * whether the value has changed. But check again
01008              * for fun and because the change is being checked
01009              * against a different variable (ie m_device_mmap) 
01010              * because these changes could be defered */
01011             
01012             /* use OR/|| because sometimes the change must be forced
01013              * to actually apply the settings */
01014             if ((ch_w > 0) || 
01015                 (this->m_info->m_device_mmap.width != this->m_width))
01016             {
01017                 this->m_info->m_device_mmap.width = this->m_width;
01018                 changed_image_dimensions = 1;
01019             }
01020             /* use OR/|| because sometimes the change must be forced
01021              * to actually apply the settings */
01022             if ((ch_h > 0) || 
01023                 (this->m_info->m_device_mmap.height != this->m_height))
01024             {
01025                 this->m_info->m_device_mmap.height = this->m_height;
01026                 changed_image_dimensions = 1;
01027             }
01028             /* use OR/|| because sometimes the change must be forced
01029              * to actually apply the settings */
01030             if ((ch_f > 0) || (this->m_current_format != this->m_format))
01031             {
01032                 int32_t f = this->m_format;
01033                 int32_t validFormats = (phImageRGB24 |
01034                                         phImageBGR24 |
01035                                         phImageRGBA32 | 
01036                                         phImageBGRA32 |
01037                                         phImageGREY8);
01038                 changed_image_dimensions = 1;
01039                 
01040                 /* make sure any special flags are removed */
01041                 f &= validFormats;
01042                 
01043                 switch (f)
01044                 {
01045                     /* --------------------------------------------------- */
01046                     case phImageGREY8:
01047                         
01048                         this->m_info->m_device_mmap.format = 
01049                             this->m_info->m_device_picture.palette = 
01050                                                         VIDEO_PALETTE_GREY;
01051                         this->m_info->m_device_picture.depth = 8;    
01052                         
01053                         break;
01054                     /* --------------------------------------------------- */
01055                     case phImageRGBA32:
01056                     case phImageBGRA32:
01057                         
01058                         this->m_info->m_device_mmap.format = 
01059                             this->m_info->m_device_picture.palette = 
01060                                                         VIDEO_PALETTE_RGB32;
01061                         this->m_info->m_device_picture.depth = 32;    
01062                     
01063                         break;
01064                     /* --------------------------------------------------- */
01065                     /* if multiple formats are specified or the format is 
01066                      * invalid, then phImageRGB24 is used */
01067                     case phImageRGB24:
01068                     case phImageBGR24:
01069                     default:
01070                         
01071                         this->m_info->m_device_mmap.format = 
01072                             this->m_info->m_device_picture.palette = 
01073                                                         VIDEO_PALETTE_RGB24;
01074                         this->m_info->m_device_picture.depth = 24;
01075                         
01076                         break;
01077                 }
01078                 
01079                 this->m_current_format = this->m_format = f;
01080             }
01081 
01082             /* if any of the fields changed, then apply the changes
01083              * to the device if it's open and set the new image size */
01084             if (changed_image_dimensions == 1)
01085             {
01086                 phIMAGE_SIZE_IN_BYTES(this->m_image_size,
01087                                       this->m_info->m_device_mmap.width,
01088                                       this->m_info->m_device_mmap.height,
01089                                       this->m_current_format );
01090                 this->m_changed_settings = 1;
01091             }
01092         }
01093         else
01094         {
01095             retrc = 1;
01096         }
01097     }
01098 
01099     ch_tuner = ph_int32_array_find(this->m_changed_array, phCHANGE_TUNER, NULL);
01100     if ((ch_tuner > 0) || (ch_init > 0))
01101     {
01102         if (this->m_device_fd > 0)
01103         {
01104             rc = this->ioctl_get_tuner();
01105             phCHECK_RC(rc,NULL,"this->ioctl_get_tuner");
01106 
01107             if (this->m_info->m_device_tuner.mode != VIDEO_MODE_NTSC)
01108             {
01109                 this->m_info->m_device_tuner.mode = VIDEO_MODE_NTSC;
01110 
01111                 rc = this->ioctl_set_tuner();
01112                 phCHECK_RC(rc,NULL,"ioctl_set_tuner");
01113                 
01114                 this->m_changed_channel = 1;
01115             }
01116         }
01117     }
01118     
01119     ch_p = ph_int32_array_find(this->m_changed_array, phCHANGE_PATH, NULL);
01120     if ((ch_p > 0) || (ch_init > 0))
01121     {
01122         /* this->m_path is used in 'open', no special V4LCapture
01123          * settings have to be applied here */
01124         retrc = 1;
01125     }
01126 
01127     /* if the device is open, apply the settings... */
01128     /* can really only apply the settings if the device is open */
01129     /* until the device is open we're merely saving the values */
01130     if (this->m_device_fd > 0)
01131     {
01132         /* TODO: if reopening and stopping of the thread is necessary
01133          * then this is likely the place to do it */
01134 
01135         /* The value m_changed_channel is persistent across calls to 
01136          * applySettings in the case the settings aren't applied 
01137          * in one call of applySettings */
01138         if (this->m_changed_channel == 1)
01139         {
01140             /* get channel: fills the structure's fields with default values*/
01141             if (this->m_info->m_device_chan.channel < 0)
01142                 this->m_info->m_device_chan.channel = 0;
01143                        
01144             /* set channel */
01145             rc = this->ioctl_set_channel();
01146             phPRINT_RC(rc,NULL,"ioctl_set_channel()");
01147 
01148             this->m_changed_channel = 0;
01149         }   
01150 
01151         /* The value m_changed_settings is persistent across calls to 
01152          * applySettings in the case the settings aren't applied 
01153          * in one call of applySettings */
01154         if (this->m_changed_settings == 1)
01155         {
01156             rc = this->ioctl_set_picture();
01157             phPRINT_RC(rc,NULL,"ioctl_set_picture()");
01158 
01159             /* Apply the picture  settings */
01160             this->m_changed_settings = 0;
01161         }
01162  
01163 
01164     }
01165 
01166     rc = this->phImageCapture::onApplySettings();
01167     phCHECK_RC(rc,NULL,"this->phImageCapture::onApplySettings() failed.");
01168  
01169     return retrc;
01170 error:
01171 
01172     return phFAIL;
01173 }
01174 
01175 /* ---------------------------------------------------------------------- */
01176 /* cleanup - This unmaps the hardware buffer after the thread has stopped
01177  * 
01178  */
01179 /* ---------------------------------------------------------------------- */
01180 int V4LCapture::cleanup()
01181 {
01182     phFUNCTION("V4LCapture::cleanup()")
01183    
01184     rc = this->lock();
01185     phPRINT_RC(rc,NULL,"this->lock()");
01186     
01187     rc = this->unmapHWBuffer();
01188     phPRINT_RC(rc,NULL,"this->unmapHWBUffer()");
01189 
01190     rc = this->phImageCapture::cleanup();
01191     phPRINT_RC(rc,NULL,"this->phImageCapture::cleanup()");
01192     
01193     rc = this->unlock();
01194     phPRINT_RC(rc,NULL,"this->unlock()");
01195     
01196     return phSUCCESS;
01197 }
01198 
01199 /* ---------------------------------------------------------------------- */
01200 #define CAPTURE_BEGIN(fd,array,frm) \
01201 {\
01202     /*phDEBUG_PRINT("ioctl(%d,VIDIOCMCAPTURE,%p):%d\n",\
01203             fd, &spec, frm ); */\
01204     /*phPRINT("ioctl:VIDIOCMCAPTURE\n");*/ \
01205     rc = ioctl(fd, VIDIOCMCAPTURE, &array[frm] ); \
01206     if (errno == EINTR) rc = 0; \
01207     phPRINT_RC( rc, \
01208                 "ioctl(VIDIOCMCAPTURE)",\
01209                 "ioctl(%d,VIDIOCMCAPTURE,%p):frm%d:w%d:h%d failed",\
01210                 fd, \
01211                 &array[frm],\
01212                 frm,\
01213                 array[frm].width,\
01214                 array[frm].height ); \
01215 }
01216 /* ---------------------------------------------------------------------- */
01217 #define CAPTURE_SYNC(fd,frm) \
01218 {\
01219     /*phDEBUG_PRINT( "ioctl(%d,VIDIOCSYNC,%p):%d\n", \
01220              fd, &frm, frm ); */\
01221     /*phPRINT("ioctl:VIDIOCSYNC\n");*/ \
01222     rc = ioctl(fd, VIDIOCSYNC, &frm); \
01223     if (errno == EINTR) rc = 0; \
01224     phPRINT_RC( rc, \
01225                 "ioctl(VIDIOCSYNC)", \
01226                 "ioctl(%d,VIDIOCSYNC,%p) frame:%d failed", \
01227                 fd, \
01228                 &frm, \
01229                 frm ); \
01230 }
01231 
01232 /* ---------------------------------------------------------------------- */
01233 void V4LCapture::print( int copy )
01234 {   
01235     phFUNCTION("V4LCapture::print()")
01236     int locked = 0;
01237 
01238     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01239 
01240     phTHIS_LOOSE_LOCK(locked);
01241     phPRINT("--------------------------------------------------------------------------\n");
01242     print_caps      (copy);
01243     print_channel   (copy);
01244     print_picture   (copy);
01245     print_mmap      (copy);
01246     print_mbuf      (copy);
01247     print_window    (copy);
01248     print_tuner     (copy);
01249     phPRINT("--------------------------------------------------------------------------\n");
01250     phTHIS_LOOSE_UNLOCK(locked);
01251 
01252     return;
01253 }
01254 
01255 /* ---------------------------------------------------------------------- */
01256 void V4LCapture::print_caps( int copy )
01257 {   
01258     phFUNCTION("V4LCapture::print_caps()")
01259     int locked = 0;
01260     
01261     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01262 
01263     phTHIS_LOOSE_LOCK(locked);
01264 
01265     struct video_capability caps;
01266     /* print the capabilities */
01267     if (copy == 1)
01268         phMemcpy(&caps,&this->m_info->m_device_caps,sizeof(struct video_capability));
01269     else
01270         ioctl(this->m_device_fd,VIDIOCGCAP,&caps);
01271    
01272     v4l_print_video_capability(caps);
01273     
01274     phTHIS_LOOSE_UNLOCK(locked);
01275 
01276     return;
01277 }
01278 
01279 /* ---------------------------------------------------------------------- */
01280 void V4LCapture::print_channel( int copy )
01281 {   
01282     phFUNCTION("V4LCapture::print_channel()")
01283     int locked = 0;
01284 
01285     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01286 
01287     phTHIS_LOOSE_LOCK(locked);
01288 
01289     /* Print the video channel stuff */
01290     struct video_channel    chan;
01291     if (copy == 1)
01292         phMemcpy(&chan,&this->m_info->m_device_chan,sizeof(struct video_channel));
01293     else
01294         ioctl(this->m_device_fd,VIDIOCGCHAN,&chan);
01295     
01296     v4l_print_video_channel(chan);
01297 
01298     phTHIS_LOOSE_UNLOCK(locked);
01299 
01300     return;
01301 }
01302     
01303 /* ---------------------------------------------------------------------- */
01304 void V4LCapture::print_picture( int copy )
01305 {   
01306     phFUNCTION("V4LCapture::print_picture()")
01307     int locked = 0;
01308 
01309     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01310 
01311     phTHIS_LOOSE_LOCK(locked);
01312 
01313     /* Print the video_picture */
01314     struct video_picture    pict;
01315     if (copy == 1)
01316         phMemcpy(&pict,&this->m_info->m_device_picture,sizeof(struct video_picture));
01317     else
01318         ioctl(this->m_device_fd,VIDIOCGPICT,&pict);
01319    
01320     v4l_print_video_picture(pict);
01321     
01322     phTHIS_LOOSE_UNLOCK(locked);
01323 
01324     return;
01325 }
01326     
01327 /* ---------------------------------------------------------------------- */
01328 void V4LCapture::print_mmap( int copy )
01329 {   
01330     phFUNCTION("V4LCapture::print_mmap()")
01331     int locked = 0;
01332 
01333     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01334 
01335     phTHIS_LOOSE_LOCK(locked);
01336 
01337     /* Print the video_mmap */
01338     struct video_mmap       mmap;
01339     phMemcpy(&mmap,&this->m_info->m_device_mmap,sizeof(struct video_mmap));
01340    
01341     v4l_print_video_mmap(mmap);
01342     
01343     phTHIS_LOOSE_UNLOCK(locked);
01344 
01345     return;
01346 }
01347 
01348 /* ---------------------------------------------------------------------- */
01349 void V4LCapture::print_mbuf( int copy )
01350 {   
01351     phFUNCTION("V4LCapture::print_mbuf()")
01352     int locked = 0;
01353 
01354     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01355 
01356     phTHIS_LOOSE_LOCK(locked);
01357 
01358     /* Print the mbuf info */
01359     struct video_mbuf       mbuf;
01360     if (copy == 1)
01361         phMemcpy(&mbuf,&this->m_info->m_device_mbuf,sizeof(struct video_mbuf));
01362     else
01363         ioctl(this->m_device_fd,VIDIOCGMBUF,&mbuf);
01364    
01365     v4l_print_video_mbuf(mbuf);
01366     
01367     phTHIS_LOOSE_UNLOCK(locked);
01368 
01369     return;
01370 }
01371 
01372 /* ---------------------------------------------------------------------- */
01373 void V4LCapture::print_window( int copy )
01374 {   
01375     phFUNCTION("V4LCapture::print_window()")
01376     int locked = 0;
01377     struct video_window     win;
01378 
01379     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01380 
01381     phTHIS_LOOSE_LOCK(locked);
01382 
01383     /* Print the window stuff */
01384     if (copy == 1)
01385         phMemcpy(&win,&this->m_info->m_device_win,sizeof(struct video_window));
01386     else
01387         ioctl(this->m_device_fd,VIDIOCGWIN,&win);
01388    
01389     v4l_print_video_window(win);
01390     
01391     phTHIS_LOOSE_UNLOCK(locked);
01392 
01393     return;
01394 }
01395     
01396 /* ---------------------------------------------------------------------- */
01397 void V4LCapture::print_tuner( int copy )
01398 {   
01399     phFUNCTION("V4LCapture::print_tuner()")
01400     int locked = 0;
01401     struct video_tuner      tuner;
01402 
01403     if ((this->m_info == NULL) || (this->m_device_fd <= 0)) return;
01404 
01405     phTHIS_LOOSE_LOCK(locked);
01406 
01407     /* Print the tuner stuff */
01408     if (copy == 1)
01409         phMemcpy(&tuner,&this->m_info->m_device_tuner,sizeof(struct video_tuner));
01410     else
01411         ioctl(this->m_device_fd,VIDIOCGTUNER,&tuner);
01412 
01413     v4l_print_video_tuner(tuner);
01414 
01415     phTHIS_LOOSE_UNLOCK(locked);
01416 
01417     return;
01418 }
01419 
01420 /* ---------------------------------------------------------------------- */
01421 int V4LCapture::ioctl_get_capability()
01422 {
01423     phFUNCTION("V4LCapture::ioctl_get_capability")
01424     
01425     if (this->m_device_fd <= 0) return phFAIL;
01426  
01427     /* Get the Capability settings from the device */
01428     /*phPRINT("ioctl:VIDIOCGCAP\n");*/
01429     rc = ioctl( this->m_device_fd, 
01430                 VIDIOCGCAP,
01431                 &this->m_info->m_device_caps);
01432     phPRINT_RC( rc, 
01433                 "ioctl(VIDIOCGCAP)", 
01434                 "ioctl(%d,VIDIOCGCAP,%p) failed",
01435                 this->m_device_fd,
01436                 &(this->m_info->m_device_caps));
01437     
01438     return rc;
01439 } 
01440 
01441 /* ---------------------------------------------------------------------- */
01442 int V4LCapture::ioctl_get_mbuf()
01443 {
01444     phFUNCTION("V4LCapture::ioctl_get_mbuf")
01445     
01446     if (this->m_device_fd <= 0) return phFAIL;
01447  
01448     /*phPRINT("ioctl:VIDIOCGMBUF\n");*/
01449     rc = ioctl(this->m_device_fd, 
01450                VIDIOCGMBUF, 
01451                &this->m_info->m_device_mbuf);
01452     phPRINT_RC( rc,
01453                 "ioctl(VIDIOCGMBUF)",
01454                 "ioctl(%d,VIDIOCGMBUF,%p) failed.",
01455                 this->m_device_fd,
01456                 &this->m_info->m_device_mbuf);
01457 
01458     return rc;
01459 }
01460 /* ---------------------------------------------------------------------- */
01461 int V4LCapture::ioctl_get_tuner()
01462 {
01463     phFUNCTION("V4LCapture::ioctl_get_tuner")
01464     
01465     if (this->m_device_fd <= 0) return phFAIL;
01466  
01467     /*phPRINT("ioctl:VIDIOCGTUNER\n");*/
01468     rc = ioctl( this->m_device_fd, 
01469                 VIDIOCGTUNER,
01470                 &(this->m_info->m_device_tuner) );
01471     phPRINT_RC( rc, 
01472                 "ioctl(VIDIOCGTUNER)", 
01473                 "ioctl(%d,VIDIOCGTUNER,%p)",
01474                 this->m_device_fd,
01475                 &this->m_info->m_device_tuner);
01476     return rc;
01477 }
01478 
01479 /* ---------------------------------------------------------------------- */
01480 int V4LCapture::ioctl_set_channel()
01481 {
01482     phFUNCTION("V4LCapture::ioctl_set_channel")
01483     int     channel = 0;
01484     short   norm    = VIDEO_MODE_NTSC;
01485     
01486     if (this->m_device_fd <= 0) return phFAIL;
01487     
01488     norm    = this->m_info->m_device_chan.norm;
01489     channel = this->m_info->m_device_chan.channel;
01490 
01491     /*phPRINT("ioctl:VIDIOCGCHAN:%d\n",channel);*/
01492     rc = ioctl( this->m_device_fd, 
01493                 VIDIOCGCHAN,
01494                 &this->m_info->m_device_chan);
01495     phPRINT_RC( rc,
01496                 "ioctl(VIDIOCGCHAN)", 
01497                 "ioctl(%d,VIDIOCGCHAN,%p)-channel:%d",
01498                 this->m_device_fd,
01499                 &this->m_info->m_device_chan,
01500                 this->m_info->m_device_chan.channel);
01501         
01502     /* set image source and TV norm */
01503     this->m_info->m_device_chan.norm    = norm;
01504     this->m_info->m_device_chan.channel = channel;
01505  
01506     /*phPRINT("ioctl:VIDIOCSCHAN:%d\n",channel);*/
01507     rc = ioctl( this->m_device_fd, 
01508                 VIDIOCSCHAN,
01509                 &this->m_info->m_device_chan);
01510     phPRINT_RC( rc,
01511                 "ioctl(VIDIOCSCHAN)", 
01512                 "ioctl(%d,VIDIOCSCHAN,%p)-channel:%d",
01513                 this->m_device_fd,
01514                 &this->m_info->m_device_chan,
01515                 this->m_info->m_device_chan.channel);
01516     
01517     return rc;
01518 }
01519 
01520 /* ---------------------------------------------------------------------- */
01521 int V4LCapture::ioctl_set_picture()
01522 {
01523     phFUNCTION("V4LCapture::ioctl_set_picture")
01524 
01525     if (this->m_device_fd <= 0) return phFAIL;
01526     
01527     /*phPRINT("ioctl:VIDIOCSPICT\n");*/
01528     rc = ioctl( this->m_device_fd,
01529                 VIDIOCSPICT,
01530                 &this->m_info->m_device_picture);
01531     phPRINT_RC( rc,
01532                 "ioctl(VIDIOCSPICT)", 
01533                 "ioctl(%d,VIDIOCSPICT,%p) failed",
01534                 this->m_device_fd,
01535                 &this->m_info->m_device_picture);
01536     
01537     return rc;
01538 }
01539 
01540 /* ---------------------------------------------------------------------- */
01541 int V4LCapture::ioctl_set_window()
01542 {
01543     phFUNCTION("V4LCapture::ioctl_set_window")
01544 
01545     if (this->m_device_fd <= 0) return phFAIL;
01546 
01547     this->m_info->m_device_win.clips = NULL;
01548     
01549     /*phPRINT("ioctl:VIDIOCSWIN\n");*/
01550     rc = ioctl( this->m_device_fd, 
01551                 VIDIOCSWIN, 
01552                 &(this->m_info->m_device_win) );
01553     phPRINT_RC(rc,
01554                "ioctl(VIDIOCSWIN)", 
01555                "ioctl(%d,VIDIOCSWIN,%p) failed",
01556                this->m_device_fd,
01557                &this->m_info->m_device_win);
01558     return rc;
01559 }
01560 
01561 /* ---------------------------------------------------------------------- */
01562 int V4LCapture::ioctl_set_tuner()
01563 {
01564     phFUNCTION("V4LCapture::ioctl_set_tuner")
01565     int tuner = 0;
01566 
01567     if (this->m_device_fd <= 0) return phFAIL;
01568 
01569     tuner = this->m_info->m_device_tuner.tuner;
01570 
01571     /*phPRINT("ioctl:VIDIOCSTUNER:%d\n",tuner);*/
01572     rc = ioctl( this->m_device_fd, 
01573                 VIDIOCSTUNER,
01574                 &(this->m_info->m_device_tuner) );
01575     phPRINT_RC( rc, 
01576                 "ioctl(VIDIOCSTUNER)", 
01577                 "ioctl(%d,VIDIOCSTUNER,%p)",
01578                 this->m_device_fd,
01579                 &this->m_info->m_device_tuner);
01580 
01581     rc = this->ioctl_set_channel();
01582     phPRINT_RC(rc,NULL,"ioctl_set_channel");
01583     
01584     return rc;
01585 }
01586 
01587 /* ---------------------------------------------------------------------- */
01588 int V4LCapture::run()
01589 {
01590     phFUNCTION("V4LCapture::run")
01591     
01592     rc = this->mapHWBuffer();
01593     phPRINT_RC(rc,NULL,"this->mapHWBuffer()");
01594 
01595     /* About using the disabled swap: */
01596     /* There has to be at least 2 V4L buffers for which one of the two
01597      * are being captured to while the other buffer is accessible to
01598      * listening objects/threads. 2 buffers will likely give jerky 
01599      * results in the frame rate than 3 buffers; which provide a smoother
01600      * frame rate */
01601     /* After starting all the capturing to the buffers, we first have 
01602      * to SYNC with the capture for a buffer before we can send it off
01603      * on another capture session. When we've sync'd with the buffer(#0) 
01604      * we can then take the pointer and place it into the phImage until the 
01605      * next buffer(#1) has been sync'd with. We can only begin a capture on 
01606      * the first buffer(#0) after we've taken the pointer out of the phImage
01607      * object. At this point we can restart the capture for the buffer #0. */
01608     /* buffer_ready lets the code know when the capture can be 
01609      * started again. This is mostly for starting and shutting down of
01610      * this capture thread. In the case of two buffers, we can't capture
01611      * to buffer #1 until the previous capture has been stopped/sync'd.
01612      * When starting we would be swapping #0's pointers into the phImage
01613      * buffer. We would then be assuming that the pointers and info we get
01614      * out of the phImage during this swap are #1. However, this is untrue 
01615      * and we need to prevent trying to start a capture on #1 until it's
01616      * buffer is ready. */
01617     int         use_disabled_swap = this->m_hw_bufferCount >= 2 ? 1 : 0;
01618     int        *buffer_ready      = new int[this->m_hw_bufferCount];
01619     int         temp_frame_index  = 0;
01620     
01621     phImage     *output_buffer  = this->getImage();
01622     int         output_locked   = 0;
01623     uint8_t     *temp           = NULL;
01624     
01625     uint32_t i = 0;
01626     uint32_t cur_frame = 0;
01627 #if TIMESTUFF()
01628     struct timeval tv_start;
01629     struct timeval tv_stop;
01630     float tdiff;
01631     int32_t frames;
01632 #endif
01633 
01634 #if TIMESTUFF()
01635     tv_start.tv_sec = 0;
01636     tv_start.tv_usec= 0;
01637     tv_stop.tv_sec = 0;
01638     tv_stop.tv_usec= 0;
01639     tdiff = 0.0;
01640     frames = 0;
01641 #endif
01642 
01643     /* local copies of V4LCapture object's member vars */
01644     int                     cur_fd              = 0;
01645     uint8_t                 *cur_imgptr         = NULL;
01646     int32_t                 cur_format          = 0;
01647     uint32_t                cur_image_size      = 0;
01648     uint32_t                cur_buffer_count    = 0;
01649     struct video_mbuf       cur_capture_buffer_info;
01650     struct video_mmap       cur_capture_spec;
01651     struct video_picture    cur_settings;
01652     struct video_mmap       *mmap_array         = NULL;
01653     
01654     uint32_t loop_width     = 0;
01655     uint32_t loop_height    = 0;
01656     uint32_t loop_format    = phImageNOFORMAT;
01657     uint32_t loop_size      = 0;
01658     uint8_t *loop_ptr       = NULL;
01659     
01660     /* Setup */
01661     cur_imgptr      = this->m_hw_buffer;
01662     cur_format      = this->m_current_format;
01663     cur_image_size  = this->m_image_size;
01664     cur_buffer_count= this->m_hw_bufferCount;
01665     cur_fd          = this->m_device_fd;
01666     
01667     phMemcpy(&cur_capture_buffer_info,
01668              (void *)&(this->m_info->m_device_mbuf),
01669              sizeof(struct video_mbuf));
01670     phMemcpy(&cur_capture_spec,
01671              (void *)&(this->m_info->m_device_mmap),
01672              sizeof(struct video_mmap));
01673     phMemcpy(&cur_settings,
01674              (void *)&(this->m_info->m_device_picture),
01675              sizeof(struct video_picture));
01676 
01677     phMemset(buffer_ready,0,sizeof(int) * this->m_hw_bufferCount);
01678     
01679     mmap_array = (struct video_mmap *)phCalloc(cur_buffer_count,
01680                                                sizeof(struct video_mmap));
01681     phCHECK_PTR(mmap_array,"phCalloc","phCalloc failed.");
01682     for (i = 0; i < this->m_hw_bufferCount; i++ )
01683     {
01684         mmap_array[i].frame = i;
01685         mmap_array[i].width = cur_capture_spec.width;
01686         mmap_array[i].height = cur_capture_spec.height;
01687         mmap_array[i].format = cur_settings.palette;
01688     }
01689 
01690     if (!use_disabled_swap)
01691     {
01692         if (temp == NULL)
01693         {
01694             temp = (uint8_t*)phMalloc(cur_image_size);
01695             phCHECK_NULLPTR(temp,"phMalloc","phMalloc failed");
01696 
01697             phMemset(temp,0,cur_image_size);
01698         }
01699         else
01700         {
01701             temp = (uint8_t *)phRealloc(temp,cur_image_size);
01702             phCHECK_NULLPTR(temp,"phRealloc","phRealloc failed");
01703         }
01704     
01705         /* If there is no data in the buffer or the buffer is of a different size,
01706          * then [re]allocate the data and set it back in so the data can be
01707          * swapped out and match the temp buffer */
01708         if (output_buffer->isNull())
01709         {
01710             /* Prepare the output_buffer */
01711             output_buffer->disableNotify();
01712             
01713             loop_width  = cur_capture_spec.width;
01714             loop_height = cur_capture_spec.height;
01715             loop_format = cur_format;
01716             loop_size   = 0; /* size: let the method figure it out */
01717             loop_ptr    = (uint8_t*)temp;
01718             
01719             rc = output_buffer->setImage(loop_width,
01720                                          loop_height,
01721                                          loop_format,
01722                                          loop_size,
01723                                          loop_ptr);
01724             phPRINT_RC(rc,NULL,"setImage");
01725             
01726             loop_size = output_buffer->getSize();
01727             
01728             output_buffer->enableNotify();
01729         }
01730     }
01731     else
01732     {
01733         /* disable swapping on the buffer now; just for fun */
01734         output_buffer->disableSwap();
01735     }
01736 
01737     /* start the first capture */
01738     for (i = 0; i < cur_buffer_count; i++)
01739     {
01740         CAPTURE_BEGIN( cur_fd, mmap_array, i );
01741     }
01742 
01743     /* Release the thread that spawned this one */
01744     /* Everything has been copied and everything is ready to start */
01745     rc = this->signal_running();
01746     phPRINT_RC(rc,NULL,"this->signal_running");
01747     
01748     DEBUG_PRINT("Thread Started\n");
01749     DEBUG_PRINT("output_buffer: %p\n",output_buffer);
01750     
01751     while (this->isRunning())
01752     {
01753         CAPTURE_SYNC( cur_fd, cur_frame );
01754 
01755         buffer_ready[cur_frame] = 1;
01756 
01757         if (!use_disabled_swap)
01758         {
01759             memcpy(temp,
01760                    (uint8_t*)(cur_imgptr + 
01761                               cur_capture_buffer_info.offsets[cur_frame]),
01762                    cur_image_size);
01763         
01764             CAPTURE_BEGIN( cur_fd, mmap_array, cur_frame );
01765             cur_frame = (cur_frame + 1) % cur_buffer_count;
01766         }
01767         else
01768         {
01769             temp = (uint8_t*)(cur_imgptr + 
01770                               cur_capture_buffer_info.offsets[cur_frame]);
01771         } 
01772         
01773         /* convert to RGB format, it's the specified format for image 
01774          * data from a capture class */
01775         /* V4L Format is BGR, BGRA */
01776         if ((cur_format == phImageRGB24) &&
01777             (cur_settings.palette == VIDEO_PALETTE_RGB24))
01778         {
01779             phBGR24_x_RGB24(cur_image_size,temp);
01780         }
01781         if ((cur_format == phImageRGBA32) &&
01782             (cur_settings.palette == VIDEO_PALETTE_RGB32))
01783         {
01784             phBGRA32_x_RGBA32(cur_image_size,temp);
01785         }
01786         
01787         /* if (output_buffer->tryWritelock() == 0) */
01788         DEBUG_PRINT("output_buffer->tryWriteLock()\n");
01789         if (output_buffer->writeLock() == 0)
01790         {
01791             ++output_locked;
01792 
01793             /* enable the swapping after we have the write lock so we
01794              * can swap our mmapped pointer into the object */
01795             if (use_disabled_swap)
01796                 output_buffer->enableSwap();
01797 
01798             DEBUG_PRINT("== 0\n");
01799             /* This will lock(again) and unlock the image.
01800              * While in possession of the lock the image
01801              * is copied */
01802             loop_width  = cur_capture_spec.width;
01803             loop_height = cur_capture_spec.height;
01804             loop_format = cur_format;
01805             loop_size   = cur_image_size; /* size: let the method figure it out */
01806             loop_ptr    = temp;
01807             
01808             rc = output_buffer->swapData(   &loop_width,
01809                                             &loop_height,
01810                                             &loop_format,
01811                                             &loop_ptr,
01812                                             &loop_size
01813                                         );
01814             phPRINT_RC(rc,NULL,"output_buffer->swapData");
01815             
01816             if (use_disabled_swap)
01817             {
01818                 /* make sure the swap is disabled before we unlock the
01819                  * image so no one else can take the pointer from the
01820                  * object and do bad things with it */
01821                 output_buffer->disableSwap();
01822             
01823                 temp_frame_index = cur_frame - 1;
01824                 if (temp_frame_index < 0) 
01825                     temp_frame_index = cur_buffer_count - 1;
01826 
01827                 if (buffer_ready[temp_frame_index])
01828                 {
01829                     CAPTURE_BEGIN( cur_fd, mmap_array, temp_frame_index );
01830                     buffer_ready[temp_frame_index] = 0;
01831                 }
01832                 cur_frame = (cur_frame + 1) % cur_buffer_count;
01833             }
01834             /*
01835             phPRINT("loop w:%u h:%u f:0x%08x s:%u p:%p\n",
01836                   loop_width,loop_height,loop_format,loop_size,loop_ptr);
01837             */
01838             /* This is the only data that needs to be copied back from the swap 
01839              * operation. It's the old pointer to the data in the output_buffer.
01840              * All the other sizes should be the same values as the ones seen
01841              * locally to this function */
01842             temp = loop_ptr;
01843 
01844             output_buffer->rwUnlock();
01845             output_locked--;
01846         }
01847 
01848         /* make sure the size of the pointer we got from the phImage is
01849          * the correct size for the current format/image size being
01850          * captured */
01851         if (use_disabled_swap)
01852         {
01853             temp = NULL;
01854         }
01855         else if ((loop_size != cur_image_size) && (temp != NULL))
01856         {
01857             temp = (uint8_t *)phRealloc(temp,cur_image_size);
01858             phCHECK_NULLPTR(temp,"phRealloc","phRealloc failed");
01859         }
01860 
01861 #if TIMESTUFF()
01862         /* Compare the current time to the start time to figure 
01863          * out how fast things are being displayed */
01864         
01865         if (frames > 30)
01866         {
01867             TIMEEND(frames);
01868             frames = 0;
01869             /* This sets the start time. We'll use the start
01870              * * time and compare it to the end time(at the begining
01871              * * of this function) to find out how many frames per second
01872              * * are being blitted.                     */
01873             TIMESTART();
01874         }
01875         frames++;
01876 #endif
01877 
01878         phYield();
01879     }
01880         
01881     /* sync with the last frame, just because */
01882     for (i = 0; i < cur_buffer_count; i++ )
01883     {
01884         if (!buffer_ready[i]) /* not (buffer ready) = capture in progress */
01885                               /* (buffer ready) = capture not progress */
01886         {
01887             CAPTURE_SYNC( cur_fd, i );
01888         }
01889     }
01890 
01891     /* if we disabled the swapping capability, we're using a
01892      * piece of memory that can't be freed by the phImage object.
01893      * We need to reset it so it won't segfault. */
01894     if (use_disabled_swap)
01895     {
01896         loop_width  = 0;
01897         loop_height = 0;
01898         /* loop_format = phImageNOFORMAT; - not valid, can't use this */
01899         loop_ptr    = NULL;
01900         loop_size   = 0;
01901 
01902         phWRITELOCK_LOOSE((*output_buffer),output_locked);
01903 
01904         /* enable the swap so we can put NULL into the object so
01905          * the object won't try to free our mmapped pointer */
01906         output_buffer->enableSwap();
01907         
01908         rc = output_buffer->swapData(&loop_width,
01909                                      &loop_height,
01910                                      &loop_format,
01911                                      &loop_ptr,
01912                                      &loop_size
01913                                      );
01914         phPRINT_RC(rc,NULL,"output_buffer->swapData");
01915        
01916         /* disable swap because it should be, yea */
01917         output_buffer->disableSwap();
01918 
01919         phRWUNLOCK_LOOSE((*output_buffer),output_locked);
01920     }
01921 
01922     DEBUG_PRINT("Thread returning cleanly\n");
01923    
01924     phDeleteArray(buffer_ready);
01925     phFree(temp);
01926     phFree(mmap_array);
01927 
01928     return phSUCCESS;
01929     
01930 error:
01931     phPROGRESS("Thread returning with error\n");
01932     
01933     phRWUNLOCK_ERROR((*output_buffer),output_locked); /* 1337 */
01934     phDeleteArray(buffer_ready);
01935     phFree(temp);
01936     phFree(mmap_array);
01937     
01938     rc = this->signal_error();
01939     phPRINT_RC(rc,NULL,"this->signal_error");
01940     
01941     return phFAIL;
01942 }
01943 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4