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 |