/* * README for IEEE 1394 digital camera support routine in PWLib * ------------------------------------------------------------ * * PWLib now contains preliminary support for the IEEE 1394 digital * cameras under Linux. * * * Supported cameras: * * There are two kind of the specifications of IEEE 1394 digital video * cameras, one is called "digital camera" and another is "AV/C camera". * A digital camera sends uncompressed video data while an AV/C camera * sends compressed data. Currently PWLib only supports digital * cameras. We can find a list of supported digital cameras by the Linux * device driver at: * http://www.tele.ucl.ac.be/PEOPLE/DOUXCHAMPS/ieee1394/cameras/ * * AV/C cameras seem able to be used for video phone. You are welcome to * write supporting codes for AV/C cameras! * * * Installation and Use: * * To enable 1394 camera support, you have to define the "TRY_1394DC" * shell environment variable at compilation time of PWLib, OpenH323, and * ohphone. To select your 1394 camera for video input device instead of * usual Video4Linux devices, specify "/dev/raw1394" or "/dev/video1394" * as the filename of video input device. For example "ohphone * --videoinput /dev/raw1394" should use your 1394 camera as video input. * * "/dev/video1394" uses faster DMA transfer for video input. * * If you use DEVFS, the filename for DMA transfer may be /dev/video1394/0. * * Requirements for Installation: * * You needs the following softwares to compile the 1394 camera support * module in PWLib. * * - libdc1394 0.9.0 or later. * - Linux 2.4.19 or later, which is required by the above version of * libdc1394 * - libraw1394 0.9.0 or later * * You cannot compile it with older versions of libdc1394. * * Troubleshooting: * * If this module does not work for you, please verify the following * items before sending email: * * 1) Can you view image of your camera by other programs? A sample * program called "grab_gray_image" is included in the example * directory of libdc1394. Please run grab_gray_image and see what * happens. You can also use Coriander instead. * (http://www.tele.ucl.ac.be/PEOPLE/DOUXCHAMPS/ieee1394/coriander/). * 2) If you have make sure other programs can use the camera, but * this module still does not work, please run the debbuging version * of ohphone with option "-tttt -o log.txt". Examine the file "log.txt" * and you may see what is wrong. * * * Problem Reports: * They should be send to Ryutaroh Matsumoto . * * * Acknowledgment: * R. Matsumoto thanks Dr. Derek Smithies for his kind support for making * this module. * * * Technical Notes for Programmers * ------------------------------------------------------------ * * Test Environment: * This module was tested against: * * Pentium III * Linux 2.4.19 * libraw1394 0.9.0 * libdc1394 0.9.0 * * Irez StealthFire Camera (http://www.irez.com) * OrangeMicro iBot Camera (http://www.orangemicro.com) * * * Internal Structure: * This module has been tested against the ohphone and GnomeMeeting * video phone programs. They use 352x288 and 176x144 resolutions in * YUV420P color format. So this module only supports these * resolutions and YUV420P. * * 1394 Digital Cameras has many resolutions and color formats. Among * them, this module uses: * 160x120 YUV(4:4:4) for 176x144 PTlib resolution, and * 320x240 YUV(4:2:2) for 352x288 PTlib resolution. * The bus speed is always set to P_DC1394_DEFAULT_SPEED (400 Mbps). * If transfer at P_DC1394_DEFAULT_SPEED is not supported by your * camera, this module does not capture images from yours. In such * a case please set P_DC1394_DEFAULT_SPEED to appropriate value. * * Conversion routines from above formats to YUV420P were added to * src/ptlib/common/vconvert.cxx * * ToDo or Bugs: * This module does not implement GetBrightness() etc. 1394 cameras * can do both automatic control and manual control of brightness * etc., and they are usually set to automatic * control. Get/SetBrightness() etc. cannot access manual/automatic * selection. So we cannot implement an interface that can fully * control all of 1394 camera features. I decided not to implement * controlling interface at all. Those features can be controlled by * Coriander program even when ohphone or GnomeMeeting is being used. * Please use Coriander. * * PVideoInputDevice_1394DC does not allow creation of two or more instances. * * The bus speed is always set to P_DC1394_DEFAULT_SPEED (400 Mbps). * If transfer at P_DC1394_DEFAULT_SPEED is not supported by your * camera, this module does not capture images from yours. In such * a case please set P_DC1394_DEFAULT_SPEED to appropriate value. * * Copyright: * Copyright (c) 2002 Ryutaroh Matsumoto * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * * * $Log: video4dc1394.cxx,v $ * Revision 1.8.2.1 2006/04/30 21:30:56 dsandras * Backport from HEAD. * * Revision 1.9 2006/04/30 21:25:20 dsandras * Fixed resolution detection thanks to Luc Saillard . * Thanks a lot! * * Revision 1.8 2005/12/01 00:43:45 csoutheren * Fixed typo * * Revision 1.7 2005/11/30 12:47:39 csoutheren * Removed tabs, reformatted some code, and changed tags for Doxygen * * Revision 1.6 2005/08/09 09:08:10 rjongbloed * Merged new video code from branch back to the trunk. * * Revision 1.5.6.2 2005/07/24 09:01:48 rjongbloed * Major revisions of the PWLib video subsystem including: * removal of F suffix on colour formats for vertical flipping, all done with existing bool * working through use of RGB and BGR formats so now consistent * cleaning up the plug in system to use virtuals instead of pointers to functions. * rewrite of SDL to be a plug in compatible video output device. * extensive enhancement of video test program * * Revision 1.5.6.1 2005/07/17 09:27:07 rjongbloed * Major revisions of the PWLib video subsystem including: * removal of F suffix on colour formats for vertical flipping, all done with existing bool * working through use of RGB and BGR formats so now consistent * cleaning up the plug in system to use virtuals instead of pointers to functions. * rewrite of SDL to be a plug in compatible video output device. * extensive enhancement of video test program * * Revision 1.5 2004/06/15 23:55:50 csoutheren * Added check for different versions of dc1394 API * * Revision 1.4 2004/06/15 15:38:29 dsandras * Fixed bug with latest API of libdc1394. * * Revision 1.3 2004/06/14 20:43:33 dsandras * Try to fix compilation. * * Revision 1.2 2004/05/10 10:09:19 csoutheren * Removed printf that was interpreted as a trigraph * * Revision 1.1 2003/12/17 15:40:56 dominance * Added DC Plugin as provided by Julien Puydt . Needs manual patching of plugins/configure for now though. (i.e. disabled by default, run autoconf in plugins/) * * Revision 1.9 2003/03/17 07:53:04 robertj * Removed canCaptureVideo variable as this is really a virtual function to * distinguish PVideoOutputDevice from PVideoInputDevice, it is not dynamic. * * Revision 1.8 2002/08/21 00:00:31 dereks * Patches from Ryutaroh, to improve firewire (linux only) support. Many thanks. * * Revision 1.7 2002/05/30 22:49:35 dereks * correct implementation of GetInputDeviceNames(). * * Revision 1.6 2002/03/04 01:21:31 dereks * Add frame rate support to Firewire camera. Thanks Ryutaroh Matsumoto. * * Revision 1.5 2002/02/28 19:44:03 dereks * Add complete readme on Firewire usage. Thanks to Ryutaroh Matsumoto. * * Revision 1.4 2002/02/21 20:00:21 dereks * Fix memory leak. Thanks Ryutaroh Matsumoto. * * Revision 1.3 2002/02/21 19:49:57 dereks * Fix spelling mistake. Thanks Ryutaroh * * Revision 1.2 2002/02/20 20:27:28 dereks * updates to previous checkin. * * Revision 1.1 2002/02/20 02:37:26 dereks * Initial release of Firewire camera support for linux. * Many thanks to Ryutaroh Matsumoto . * * * * */ #pragma implementation "videoio1394dc.h" #include #include #include #include #include "videoio1394dc.h" #include PCREATE_VIDINPUT_PLUGIN(1394DC); #ifndef P_DC1394_DEFAULT_SPEED #define P_DC1394_DEFAULT_SPEED SPEED_400 #endif //#define ESTIMATE_CAPTURE_PERFORMANCE #ifdef ESTIMATE_CAPTURE_PERFORMANCE // for debugging static PInt64 start_time; static int num_captured; #endif /////////////////////////////////////////////////////////////////////////////// // PVideoInput1394DC PVideoInputDevice_1394DC::PVideoInputDevice_1394DC() { handle = NULL; is_capturing = FALSE; capturing_duration = 10000; // arbitrary large value suffices } PVideoInputDevice_1394DC::~PVideoInputDevice_1394DC() { Close(); } #define OK 1 #define NG 0 static int kernel_version_ok(void) { struct utsname utsbuf; unsigned major_ver, minor_ver, minorminor_ver; if (uname(&utsbuf) == -1) return NG; /* utsbuf.release looks like "2.4.19-pre8". */ if (sscanf(utsbuf.release, "%u.%u.%u", &major_ver, &minor_ver, &minorminor_ver) < 3) return NG; /* Should we return OK? */ if (major_ver >= 3) return OK; else if (major_ver <= 1) return NG; if (minor_ver >= 6) return OK; else if (minor_ver <= 3) return NG; else if (minor_ver == 4) return minorminor_ver >= 19; else /* if (minor_ver == 5) */ return minorminor_ver >= 9; } BOOL PVideoInputDevice_1394DC::Open(const PString & devName, BOOL startImmediate) { if (!kernel_version_ok()) { PTRACE(0, "The Linux kernel version is too old."); return FALSE; } if (IsOpen()) { PTRACE(0, "You cannot open PVideoInputDevice_1394DC twice."); return FALSE; } if (devName == "/dev/raw1394") UseDMA = FALSE; // Don't forget /dev/video1394/0 else if (strncmp(devName, "/dev/video1394", 14) == 0) UseDMA = TRUE; else { PTRACE(0, "devName must be /dev/raw1394 or /dev/video1394"); return FALSE; } // See if devName is accessible. if (!PFile::Exists(devName)) { PTRACE(1, devName << " is not accessible."); return FALSE; } /*----------------------------------------------------------------------- * Open ohci and asign handle to it *-----------------------------------------------------------------------*/ handle = dc1394_create_handle(0); if (handle==NULL) { PTRACE(0, "Unable to aquire a raw1394 handle\ndid you insmod the drivers?\n"); return FALSE; } /*----------------------------------------------------------------------- * get the camera nodes and describe them as we find them *-----------------------------------------------------------------------*/ int numNodes = raw1394_get_nodecount(handle); camera_nodes = dc1394_get_camera_nodes(handle,&numCameras,0); if (numCameras<1) { PTRACE(0, "no cameras found :(\n"); dc1394_destroy_handle(handle); handle = NULL; return FALSE; } /*----------------------------------------------------------------------- * to prevent the iso-transfer bug from raw1394 system, check if * camera is highest node. For details see * http://linux1394.sourceforge.net/faq.html#DCbusmgmt * and * http://sourceforge.net/tracker/index.php?func=detail&aid=435107&group_id=8157&atid=108157 *-----------------------------------------------------------------------*/ for (int i=0; iConvert((const BYTE *)camera.capture_buffer, buffer, bytesReturned); else { PTRACE(1, "Converter must exist. Something goes wrong."); return FALSE; } #ifdef ESTIMATE_CAPTURE_PERFORMANCE ++num_captured; PTime now; double capturing_time = (double)((now.GetTimestamp()-start_time))/1000000; ::fprintf(stderr, "time %f, num_captured=%d, fps=%f\n", capturing_time, num_captured, num_captured/capturing_time); #endif if (UseDMA) dc1394_dma_done_with_buffer(&camera); return TRUE; } BOOL PVideoInputDevice_1394DC::GetFrameData(BYTE * buffer, PINDEX * bytesReturned) { if(frameRate>0) { if (msBetweenFrames > capturing_duration) PThread::Current()->Sleep(msBetweenFrames - capturing_duration); PTime start; if ( !GetFrameDataNoDelay(buffer, bytesReturned)) return FALSE; PTime end; capturing_duration = (int)((end-start).GetMilliSeconds()); return TRUE; } return GetFrameDataNoDelay(buffer,bytesReturned); } void PVideoInputDevice_1394DC::ClearMapping() { } BOOL PVideoInputDevice_1394DC::TestAllFormats() { return TRUE; } BOOL PVideoInputDevice_1394DC::SetColourFormat(const PString & newFormat) { if (newFormat != colourFormat) { return FALSE; } return TRUE; } BOOL PVideoInputDevice_1394DC::SetFrameSize(unsigned width, unsigned height) { if ((!(width == 320 && height == 240)) && (!(width == 160 && height == 120))) return FALSE; frameWidth = width; frameHeight = height; if (frameWidth == 320 && frameHeight == 240) colourFormat = "UYVY422"; else if (frameWidth == 160 && frameHeight == 120) colourFormat = "UYV444"; frameBytes = PVideoDevice::CalculateFrameBytes(frameWidth, frameHeight, colourFormat); if (IsCapturing()) { Stop(); Start(); } return TRUE; } BOOL PVideoInputDevice_1394DC::SetFrameSizeConverter(unsigned width, unsigned height, BOOL bScaleNotCrop) { if (width == CIFWidth && height == CIFHeight && (supportedFormat & DC1394_FORMAT_320x240)) SetFrameSize(320, 240); else if (width == QCIFWidth && height == QCIFHeight && (supportedFormat & DC1394_FORMAT_160x120)) SetFrameSize(160, 120); else if (width == QCIFWidth && height == QCIFHeight && (supportedFormat & DC1394_FORMAT_320x240)) SetFrameSize(320, 240); else if (width == CIFWidth && height == CIFHeight && (supportedFormat & DC1394_FORMAT_160x120)) SetFrameSize(160, 120); else { PTRACE(1, width << "x" << height << " is not supported."); return FALSE; } if (converter != NULL) delete converter; desiredFrameWidth = width; desiredFrameHeight = height; converter = PColourConverter::Create(colourFormat, desiredColourFormat, width, height); if (converter == NULL) { PTRACE(1, "Failed to make a converter."); return FALSE; } if (converter->SetSrcFrameSize(frameWidth, frameHeight) == FALSE) { PTRACE(1, "Failed to set source frame size of a converter."); return FALSE; } return TRUE; } BOOL PVideoInputDevice_1394DC::SetColourFormatConverter(const PString & colourFmt) { if (colourFmt != "YUV420P") { PTRACE(1, colourFmt << " is unsupported."); return FALSE; } desiredColourFormat = colourFmt; return SetFrameSizeConverter(desiredFrameWidth, desiredFrameHeight, FALSE); } // End Of File ///////////////////////////////////////////////////////////////