text: /*
   *  Player - One Hell of a Robot Server
   *  Copyright (C) 2000  Brian Gerkey et al.
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   */
  ///////////////////////////////////////////////////////////////////////////
  //
  // Desc: 1394 camera capture
  // Author: Nate Koenig, Andrew Howard
  // Date: 03 June 2004
  // CVS: $Id: camera1394.cc 8463 2009-12-16 00:33:35Z gbiggs $
  //
  ///////////////////////////////////////////////////////////////////////////
  
  /** @ingroup drivers */
  /** @{ */
  /** @defgroup driver_camera1394 camera1394
   * @brief Firewire camera capture
  
   The camera1394 driver captures images from IEEE1394 (Firewire, iLink)
   cameras.
  
   @par Compile-time dependencies
  
   - libraw1394
   - libdc1394_control
  
   @par Provides
  
   - @ref interface_camera
  
   @par Requires
  
   - none
  
   @par Configuration requests
  
   - none
  
   @par Configuration file options
  
   - guid (string [16 digits])
   - Default: None
   - The GUID of the 1394 camera to use (only for libdc1394 >= 2.0)
   - Example: guid "0800460200060121"
   - Currently, if using libdc1394 >= 2.0 
     - You should use GUID if you are on port > 0
     - To get GUID, run Player once with no GUID and look at the .player log file for the GUID of detected cameras.
  
   - port (integer)
   - Default: 0
   - The 1394 port the camera is attached to.
   - v2 of the dc1394 API no longer supports ports other than 0.  If your camera is on a port > 0, and you are on Linux, you probably have /usr/include/dc1394/linux/control.h, which should allow you to use ports > 0 (if this file was detected during ./configure).  Otherwise, use the GUID of the camera.
  
   - node (integer)
   - Default: 0
   - The node within the port
  
   - framerate (float)
   - Default: 15
   - Requested frame rate (frames/second)
  
   - mode (string)
   - Default: "640x480_yuv422"
   - Capture mode (size and color layour).  Valid modes are:
   - "320x240_yuv422"
   - "640x480_mono"
   - "640x480_yuv422"
   - "640x480_rgb"
   - "800x600_mono"
   - "800x600_yuv422" - will be rescaled to 600x450
   - "1024x768_mono"
   - "1024x768_yuv422" - will be rescaled to 512x384
   - "1280x960_mono"
   - "1280x960_yuv422" - will be rescaled to 640x480
   - "FORMAT7_MODE0" - only available with libdc1394 >= 2.0
   - Currently, all mono modes will produce 8-bit monochrome images unless
   a color decoding option is provided (see bayer).
   - All yuv422 modes are converted to RGB24
  
   - force_raw (integer)
   - Default: 0
   - Force the driver to use (slow) memory capture instead of DMA transfer
   (for buggy 1394 drivers).
  
   - save (integer)
   - Default: 0
   - Debugging option: set this to write each frame as an image file on disk.
  
   - bayer (string)
   - Default: None.
   - Bayer color decoding options for cameras such as the Point Grey Dragonfly and Bummblebee.
   Option activates color decoding and specifies the Bayer color pattern. Valid modes are:
   - "BGGR"
   - "GRBG"
   - "RGGB"
   - "GBRG"
  
   - method (string)
   - Default: None (or "DownSample" if bayer option is specified)
   - Determines the algorithm used for Bayer coloro decoding. Valid modes are:
   - "DownSample"
   - "Nearest"
   - "Edge"
  
   - brightness (string or unsigned int)
   - Default: None
   - Sets the camera brightness setting. Valid modes are:
   - "auto"
   - any suitable unsigned integer
  
   - exposure (string or unsigned int)
   - Default: None
   - Sets the camera exposure setting. Valid modes are:
   - "auto"
   - any suitable unsigned integer
  
   - shutter (string or unsigned int)
   - Default: None
   - Sets the camera shutter setting. Valid modes are:
   - "auto"
   - any suitable unsigned integer
  
   - gain (string or unsigned int)
   - Default: None
   - Sets the camera gain setting. Valid modes are:
   - "auto"
   - any suitable unsigned integer
  
   - whitebalance (string)
   - Default: None
   - Sets the manual camera white balance setting. Valid modes are:
   - "auto" (only for dc1394 v2)
   - a string containing two suitable blue and red value unsigned integers
  
   - dma_buffers
   - Default: 4
   - the number of DMA buffers to use
  
   - iso_speed (unsigned int)
   - Default: 400
   - Sets the data rate of the 1394 bus. Valid rates are 100, 200, 400, 800, 1600, 3200.
   @par Example
  
   @verbatim
   driver
   (
   name "camera1394"
   provides ["camera:0"]
   )
   @endverbatim
  
   @author Nate Koenig, Andrew Howard; major code rewrite by Paul Osmialowski, newchief@king.net.pl
   */
  /** @} */
  
  #include <errno.h>
  #include <string.h>
  #include <math.h>
  #include <stdlib.h>       // for atoi(3)
  #include <stddef.h>       // for NULL
  #include <unistd.h>
  #include <assert.h>
  
  #include <camera1394.h>
  
  #ifdef HAVE_LIBRAW1394
  #include <libraw1394/raw1394.h>
  #endif
  
  #if DC1394_DMA_SETUP_CAPTURE_ARGS == 20
  #include <dc1394/control.h>
  #define LIBDC1394_VERSION  0200
  #else
  #include <libdc1394/dc1394_control.h>
  #endif
  #include <libplayercore/playercore.h>
  
  #if DC1394_2_LINUX == 1
  
  extern "C" {
  #include <dc1394/linux/control.h>
    void get_port(dc1394camera_t* camera, uint& cam_port){
      dc1394_camera_get_linux_port(camera, &cam_port);  
    }
  }
  #endif
  
  
  // for color and format conversion (located in cmvision)
  #include "conversions.h"
  
  #define NUM_DMA_BUFFERS 4
  
  // lots of defines are renames in v2 API, mask this so we dont have to
  // modify all our code
  #if DC1394_DMA_SETUP_CAPTURE_ARGS == 20
  // Frame rate enum
  #define FRAMERATE_1_875 DC1394_FRAMERATE_1_875
  #define FRAMERATE_3_75 DC1394_FRAMERATE_3_75
  #define FRAMERATE_7_5 DC1394_FRAMERATE_7_5
  #define FRAMERATE_15 DC1394_FRAMERATE_15
  #define FRAMERATE_30 DC1394_FRAMERATE_30
  #define FRAMERATE_60 DC1394_FRAMERATE_60
  #define FRAMERATE_120 DC1394_FRAMERATE_120
  #define FRAMERATE_240 DC1394_FRAMERATE_240
  
  // Format - not used in new API
  #define FORMAT_VGA_NONCOMPRESSED 0
  #define FORMAT_SVGA_NONCOMPRESSED_1 0
  #define FORMAT_SVGA_NONCOMPRESSED_2 0
  #define FORMAT_6 0
  #define FORMAT_7 0
  
  // mode enumneration
  #define 	  MODE_160x120_YUV444	  DC1394_VIDEO_MODE_160x120_YUV444
  #define 	  MODE_320x240_YUV422	  DC1394_VIDEO_MODE_320x240_YUV422
  #define 	  MODE_640x480_YUV411	  DC1394_VIDEO_MODE_640x480_YUV411
  #define 	  MODE_640x480_YUV422	  DC1394_VIDEO_MODE_640x480_YUV422
  #define 	  MODE_640x480_RGB	  DC1394_VIDEO_MODE_640x480_RGB8
  #define 	  MODE_640x480_MONO	  DC1394_VIDEO_MODE_640x480_MONO8
  #define 	  MODE_640x480_MONO16	  DC1394_VIDEO_MODE_640x480_MONO16
  #define 	  MODE_800x600_YUV422	  DC1394_VIDEO_MODE_800x600_YUV422
  #define 	  MODE_800x600_RGB	  DC1394_VIDEO_MODE_800x600_RGB8
  #define 	  MODE_800x600_MONO	  DC1394_VIDEO_MODE_800x600_MONO8
  #define 	  MODE_1024x768_YUV422	  DC1394_VIDEO_MODE_1024x768_YUV422
  #define 	  MODE_1024x768_RGB	  DC1394_VIDEO_MODE_1024x768_RGB8
  #define 	  MODE_1024x768_MONO	  DC1394_VIDEO_MODE_1024x768_MONO8
  #define 	  MODE_800x600_MONO16	  DC1394_VIDEO_MODE_800x600_MONO16
  #define 	  MODE_1024x768_MONO16	  DC1394_VIDEO_MODE_1024x768_MONO16
  #define 	  MODE_1280x960_YUV422	  DC1394_VIDEO_MODE_1280x960_YUV422
  #define 	  MODE_1280x960_RGB	  DC1394_VIDEO_MODE_1280x960_RGB8
  #define 	  MODE_1280x960_MONO	  DC1394_VIDEO_MODE_1280x960_MONO8
  #define 	  MODE_1600x1200_YUV422	  DC1394_VIDEO_MODE_1600x1200_YUV422
  #define 	  MODE_1600x1200_RGB	  DC1394_VIDEO_MODE_1600x1200_RGB8
  #define 	  MODE_1600x1200_MONO	  DC1394_VIDEO_MODE_1600x1200_MONO8
  #define 	  MODE_1280x960_MONO16	  DC1394_VIDEO_MODE_1280x960_MONO16
  #define 	  MODE_1600x1200_MONO16	  DC1394_VIDEO_MODE_1600x1200_MONO16
  #define 	  MODE_EXIF	          DC1394_VIDEO_MODE_EXIF
  #define 	  MODE_FORMAT7_0	  DC1394_VIDEO_MODE_FORMAT7_0
  #define 	  MODE_FORMAT7_1	  DC1394_VIDEO_MODE_FORMAT7_1
  #define 	  MODE_FORMAT7_2	  DC1394_VIDEO_MODE_FORMAT7_2
  #define 	  MODE_FORMAT7_3	  DC1394_VIDEO_MODE_FORMAT7_3
  #define 	  MODE_FORMAT7_4	  DC1394_VIDEO_MODE_FORMAT7_4
  #define 	  MODE_FORMAT7_5	  DC1394_VIDEO_MODE_FORMAT7_5
  #define 	  MODE_FORMAT7_6	  DC1394_VIDEO_MODE_FORMAT7_6
  #define 	  MODE_FORMAT7_7	  DC1394_VIDEO_MODE_FORMAT7_7
  
  // Feature enumeration
  #define	  FEATURE_BRIGHTNESS	  DC1394_FEATURE_BRIGHTNESS
  #define	  FEATURE_EXPOSURE	  DC1394_FEATURE_EXPOSURE
  #define	  FEATURE_SHARPNESS	  DC1394_FEATURE_SHARPNESS
  #define	  FEATURE_WHITE_BALANCE	  DC1394_FEATURE_WHITE_BALANCE
  #define	  FEATURE_HUE	  DC1394_FEATURE_HUE
  #define	  FEATURE_SATURATION	  DC1394_FEATURE_SATURATION
  #define	  FEATURE_GAMMA	  DC1394_FEATURE_GAMMA
  #define	  FEATURE_SHUTTER	  DC1394_FEATURE_SHUTTER
  #define	  FEATURE_GAIN	  DC1394_FEATURE_GAIN
  #define	  FEATURE_IRIS	  DC1394_FEATURE_IRIS
  #define	  FEATURE_FOCUS	  DC1394_FEATURE_FOCUS
  #define	  FEATURE_TEMPERATURE	  DC1394_FEATURE_TEMPERATURE
  #define	  FEATURE_TRIGGER	  DC1394_FEATURE_TRIGGER
  #define	  FEATURE_TRIGGER_DELAY	  DC1394_FEATURE_TRIGGER_DELAY
  #define	  FEATURE_WHITE_SHADING	  DC1394_FEATURE_WHITE_SHADING
  #define	  FEATURE_FRAME_RATE	  DC1394_FEATURE_FRAME_RATE
  #define	  FEATURE_ZOOM	  DC1394_FEATURE_ZOOM
  #define	  FEATURE_PAN	  DC1394_FEATURE_PAN
  #define	  FEATURE_TILT	  DC1394_FEATURE_TILT
  #define	  FEATURE_OPTICAL_FILTER	  DC1394_FEATURE_OPTICAL_FILTER
  #define	  FEATURE_CAPTURE_SIZE	  DC1394_FEATURE_CAPTURE_SIZE
  #define	  FEATURE_CAPTURE_QUALITY	  DC1394_FEATURE_CAPTURE_QUALITY
  
  #else
  
  // speed enumerations
  #define DC1394_ISO_SPEED_100 SPEED_100
  #define DC1394_ISO_SPEED_200 SPEED_200
  #define DC1394_ISO_SPEED_400 SPEED_400
  #ifdef SPEED_800
  #define DC1394_ISO_SPEED_800 SPEED_800
  #endif
  #ifdef SPEED_1600
  #define DC1394_ISO_SPEED_1600 SPEED_1600
  #endif
  #ifdef SPEED_3200
  #define DC1394_ISO_SPEED_3200 SPEED_3200
  #endif
  
  #endif
  
  const timespec NSLEEP_TIME = { 0, 10000 }; // (0s, 10ms) => max 100Hz
  
  // Driver for detecting laser retro-reflectors.
  class Camera1394: public ThreadedDriver {
  	// Constructor
  public:
  	Camera1394(ConfigFile* cf, int section);
  
  public:
  	virtual int SetZoom(unsigned int zoom);
  	virtual int GetZoom(unsigned int* zoom);
  	virtual int SetFocus(unsigned int focus);
  	virtual int GetFocus(unsigned int* focus);
  	virtual int SetIris(unsigned int iris);
  	virtual int GetIris(unsigned int* iris);
  	virtual int SetBrightness(unsigned int brightness);
  	virtual int SetExposure(unsigned int exposure);
  	virtual int SetShutter(unsigned int shutter);
  	virtual int SetGain(unsigned int gain);
  	virtual int SetWhiteBalance(const char* whitebalance);
  
  	// Main function for device thread.
  private:
  	virtual void Main();
  
  private:
  	virtual void MainQuit();
  	virtual int MainSetup();
  	void SafeCleanup();
  
  	// This method will be invoked on each incoming message
  public:
  	virtual int ProcessMessage(QueuePointer & resp_queue, player_msghdr * hdr,
  			void * data);
  
  private:
  	// Save a frame to memory
  	int GrabFrame();
  
  	// Save a frame to disk
  	int SaveFrame(const char *filename);
  
  	// Update the device data (the data going back to the client).
  	void RefreshData();
  
  	// Video device
  	unsigned int port;
  	unsigned int node;
          char guid[1024];
          bool use_guid;
  
  #ifdef HAVE_LIBRAW1394
  private: raw1394handle_t handle;
  #endif
  
  #if LIBDC1394_VERSION == 0200
  private: dc1394camera_t * camera;
  	// Camera features
  private: dc1394featureset_t features;
  private: dc1394format7modeset_t modeset;
  #else
  private:
  	dc1394_cameracapture camera;
  	// Camera features
  private:
  	dc1394_feature_set features;
  #endif
  
  	// Capture method: RAW or VIDEO (DMA)
  private:
  	enum {
  		methodRaw, methodVideo, methodNone
  	};
  private:
  	int method;
  private:
  	bool forceRaw;
  
  #if LIBDC1394_VERSION == 0200
  private: dc1394framerate_t frameRate;
  private: unsigned int format;
  private: dc1394video_mode_t mode;
  private: dc1394speed_t iso_speed;
  #else
  private:
  	unsigned int frameRate;
  private:
  	unsigned int format;
  private:
  	unsigned int mode;
  private:
  	unsigned int iso_speed;
  #endif
  
  	// number of DMA buffers to use
  private:
  	unsigned int num_dma_buffers;
  
  	// Write frames to disk?
  private:
  	int save;
  
  	// Capture timestamp
  private:
  	double frameTime;
  
  	// Data to send to server
  private:
  	player_camera_data_t * data;
  
  	// Bayer Colour Conversion
  private:
  	bool DoBayerConversion;
  private:
  	bayer_pattern_t BayerPattern;
  private:
  	int BayerMethod;
  
  	// Camera settings
  private:
  
  	IntProperty MinZoom, MaxZoom, Zoom;
  	IntProperty MinFocus, MaxFocus, Focus;
  	IntProperty MinIris, MaxIris, Iris;
  	IntProperty Brightness, Exposure, Shutter, Gain;
  	StringProperty WhiteBalance;
  	/*  private: bool setFocus, setIris, setBrightness, setExposure, setWhiteBalance, setShutter, setGain;
  	 private: bool autoFocus, autoIris, autoBrightness, autoExposure, autoShutter, autoGain;
  	 private: unsigned int focus, iris, brightness, exposure, redBalance, blueBalance, shutter, gain;
  	 private: unsigned int min_zoom, max_zoom, min_focus, max_focus, min_iris, max_iris;*/
  
  private:
  	int frameno;
  };
  
  // Initialization function
  Driver* Camera1394_Init(ConfigFile* cf, int section) {
  	return ((Driver*) (new Camera1394(cf, section)));
  }
  
  // a driver registration function
  void camera1394_Register(DriverTable* table) {
  	table->AddDriver("camera1394", Camera1394_Init);
  }
  
  const int PROPERTY_NOT_SET = -2;
  const int PROPERTY_AUTO = -1;
  
  ////////////////////////////////////////////////////////////////////////////////
  // Constructor
  Camera1394::Camera1394(ConfigFile* cf, int section) :
  	ThreadedDriver(cf, section, true, PLAYER_MSGQUEUE_DEFAULT_MAXLEN,
  			PLAYER_CAMERA_CODE),
  	MinZoom("min_zoom", PROPERTY_NOT_SET, true, this, cf, section),
  	MaxZoom("max_zoom", PROPERTY_NOT_SET, true, this, cf, section),
  	Zoom("zoom", PROPERTY_NOT_SET, false, this, cf, section),
  	MinFocus("min_focus", PROPERTY_NOT_SET, true, this, cf, section),
  	MaxFocus("max_focus", PROPERTY_NOT_SET, true, this, cf, section),
  	Focus("focus", PROPERTY_NOT_SET, false, this, cf, section),
  	MinIris("min_iris", PROPERTY_NOT_SET, true, this, cf, section),
  	MaxIris("max_iris", PROPERTY_NOT_SET, true, this, cf, section),
  	Iris("iris", PROPERTY_NOT_SET, false, this, cf, section),
  	Brightness("brightness", PROPERTY_NOT_SET, false, this, cf, section),
  	Exposure("exposure", PROPERTY_NOT_SET, false, this, cf, section), 
  	Shutter("shutter", PROPERTY_NOT_SET, false, this, cf, section), 
  	Gain("gain", PROPERTY_NOT_SET, false, this, cf, section), 
  	WhiteBalance("whitebalance", "None", false, this, cf, section)
  {
  	float fps;
  
  	this->data = NULL;
  
  #ifdef HAVE_LIBRAW1394
  	this->handle = NULL;
  #endif
  	this->method = methodNone;
  
  	const char* str;
  	// The guid of the camera
  	str = cf->ReadString(section, "guid", "NONE");
  	this->use_guid=false;
  	if (strcmp(str,"NONE"))
  	  {
  	    use_guid=true;
  	    strcpy(this->guid,str); 
  	  }
  	
  	// The port the camera is attached to
  	this->port = cf->ReadInt(section, "port", 0);
  
  	// The node inside the port
  	this->node = cf->ReadInt(section, "node", 0);
  
  	// Video frame rate
  	fps = cf->ReadFloat(section, "framerate", 15);
  	if (fps < 3.75)
  		this->frameRate = FRAMERATE_1_875;
  	else if (fps < 7.5)
  		this->frameRate = FRAMERATE_3_75;
  	else if (fps < 15)
  		this->frameRate = FRAMERATE_7_5;
  	else if (fps < 30)
  		this->frameRate = FRAMERATE_15;
  	else if (fps < 60)
  		this->frameRate = FRAMERATE_30;
  	else
  		this->frameRate = FRAMERATE_60;
  
  	// Get uncompressed video
  	this->format = FORMAT_VGA_NONCOMPRESSED;
  
  	// Image size. This determines the capture resolution. There are a limited
  	// number of options available. At 640x480, a camera can capture at
  	// _RGB or _MONO or _MONO16.
  	str = cf->ReadString(section, "mode", "640x480_yuv422");
  	/*
  	 if (0==strcmp(str,"160x120_yuv444"))
  	 {
  	 this->mode = MODE_160x120_YUV444;
  	 }
  	 */
  	if (0 == strcmp(str, "320x240_yuv422")) {
  		this->mode = MODE_320x240_YUV422;
  	}
  	/*
  	 else if (0==strcmp(str,"640x480_mono16"))
  	 {
  	 this->mode = MODE_640x480_MONO16;
  	 assert(false);
  	 }
  	 else if (0==strcmp(str,"640x480_yuv411"))
  	 {
  	 this->mode = MODE_640x480_YUV411;
  	 }
  	 */
  	else if (0 == strcmp(str, "640x480_mono")) {
  		this->mode = MODE_640x480_MONO;
  	} else if (0 == strcmp(str, "640x480_yuv422")) {
  		this->mode = MODE_640x480_YUV422;
  	} else if (0 == strcmp(str, "640x480_rgb")) {
  		this->mode = MODE_640x480_RGB;
  	} else if (0 == strcmp(str, "800x600_mono")) {
  		this->mode = MODE_800x600_MONO;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_1;
  	} else if (0 == strcmp(str, "800x600_yuv422")) {
  		this->mode = MODE_800x600_YUV422;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_1;
  	} else if (0 == strcmp(str, "1024x768_mono")) {
  		this->mode = MODE_1024x768_MONO;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_1;
  	} else if (0 == strcmp(str, "1024x768_yuv422")) {
  		this->mode = MODE_1024x768_YUV422;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_1;
  	} else if (0 == strcmp(str, "1280x960_mono")) {
  		this->mode = MODE_1280x960_MONO;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_2;
  	} else if (0 == strcmp(str, "1280x960_yuv422")) {
  		this->mode = MODE_1280x960_YUV422;
  		this->format = FORMAT_SVGA_NONCOMPRESSED_2;
  	}
  #if LIBDC1394_VERSION == 0200
  	else if (0==strcmp(str,"FORMAT7_MODE0"))
  	{
  		this->mode = MODE_FORMAT7_0;
  		this->format = FORMAT_7;
  	}
  #endif
  	else {
  		PLAYER_ERROR1("unknown video mode [%s]", str);
  		this->SetError(-1);
  		return;
  	}
  
  	// Many cameras such as the Pt Grey Dragonfly and Bumblebee devices
  	// don't do onchip colour conversion. Various Bayer colour encoding
  	// patterns and decoding methods exist. They are now presented to the
  	// user as config file options.
  	// check Bayer colour decoding option
  	str = cf->ReadString(section, "bayer", "NONE");
  	this->DoBayerConversion = false;
  	if (strcmp(str, "NONE")) {
  		if (!strcmp(str, "BGGR")) {
  			this->DoBayerConversion = true;
  			this->BayerPattern = BAYER_PATTERN_BGGR;
  		} else if (!strcmp(str, "GRBG")) {
  			this->DoBayerConversion = true;
  			this->BayerPattern = BAYER_PATTERN_GRBG;
  		} else if (!strcmp(str, "RGGB")) {
  			this->DoBayerConversion = true;
  			this->BayerPattern = BAYER_PATTERN_RGGB;
  		} else if (!strcmp(str, "GBRG")) {
  			this->DoBayerConversion = true;
  			this->BayerPattern = BAYER_PATTERN_GBRG;
  		} else {
  			PLAYER_ERROR1("unknown bayer pattern [%s]", str);
  			this->SetError(-1);
  			return;
  		}
  	}
  	// Set default Bayer decoding method
  	if (this->DoBayerConversion)
  		this->BayerMethod = BAYER_DECODING_DOWNSAMPLE;
  	else
  		this->BayerMethod = NO_BAYER_DECODING;
  	// Check for user selected method
  	str = cf->ReadString(section, "method", "NONE");
  	if (strcmp(str, "NONE")) {
  		if (!this->DoBayerConversion) {
  			PLAYER_ERROR1(
  					"bayer method [%s] specified without enabling bayer conversion",
  					str);
  			this->SetError(-1);
  			return;
  		}
  		if (!strcmp(str, "DownSample")) {
  			this->BayerMethod = BAYER_DECODING_DOWNSAMPLE;
  		} else if (!strcmp(str, "Nearest")) {
  			this->BayerMethod = BAYER_DECODING_NEAREST;
  		} else if (!strcmp(str, "Edge")) {
  			this->BayerMethod = BAYER_DECODING_EDGE_SENSE;
  		} else {
  			PLAYER_ERROR1("unknown bayer method [%s]", str);
  			this->SetError(-1);
  			return;
  		}
  	}
  
  	// Force into raw mode
  	this->forceRaw = cf->ReadInt(section, "force_raw", 0);
  
  	// Save frames?
  	this->save = cf->ReadInt(section, "save", 0);
  
  	// Number of DMA buffers?
  	this->num_dma_buffers
  			= cf->ReadInt(section, "dma_buffers", NUM_DMA_BUFFERS);
  
  	// ISO Speed?
  	switch (cf->ReadInt(section, "iso_speed", 400)) {
  	case 100:
  		this->iso_speed = DC1394_ISO_SPEED_100;
  		break;
  	case 200:
  		this->iso_speed = DC1394_ISO_SPEED_200;
  		break;
  	case 400:
  		this->iso_speed = DC1394_ISO_SPEED_400;
  		break;
  #ifdef DC1394_ISO_SPEED_800
  		case 800:
  		this->iso_speed = DC1394_ISO_SPEED_800;
  		break;
  #endif
  #ifdef DC1394_ISO_SPEED_1600
  		case 1600:
  		this->iso_speed = DC1394_ISO_SPEED_1600;
  		break;
  #endif
  #ifdef DC1394_ISO_SPEED_3200
  		case 3200:
  		this->iso_speed = DC1394_ISO_SPEED_3200;
  		break;
  #endif
  	default:
  		PLAYER_ERROR("Unsupported iso_speed");
  		this->SetError(-1);
  		return;
  	}
  
  	return;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Safe Cleanup
  void Camera1394::SafeCleanup() {
  
  #if LIBDC1394_VERSION == 0200
  	if (this->camera)
  	{
  		//dc1394_cleanup_iso_channels_and_bandwidth(camera);
  		/* The above function has been removed from libdc1394 without a clear
  		 replacement...
  		 http://sourceforge.net/mailarchive/message.php?msg_id=1196638611.10412.31.camel%40pisces.mit.edu
  		 */
  		switch (this->method)
  		{
  			case methodRaw:
  			//dc1394_release_camera(this->camera);
  			break;
  			case methodVideo:
  			  dc1394_capture_stop(this->camera);
  			break;
  		}
  		dc1394_camera_free(this->camera);
  	}
  	this->camera = NULL;
  #else
  	if (this->handle) {
  		switch (this->method) {
  		case methodRaw:
  			dc1394_release_camera(this->handle, &this->camera);
  			break;
  		case methodVideo:
  			dc1394_dma_unlisten(this->handle, &this->camera);
  			dc1394_dma_release_camera(this->handle, &this->camera);
  			break;
  		}
  		dc1394_destroy_handle(this->handle);
  	}
  	this->handle = NULL;
  #endif
  	if (this->data) {
  		//     if (this->data->image) delete[](this->data->image);
  		if (this->data->image)
  			free(this->data->image);
  		this->data->image = NULL;
  		//     delete (this->data);
  		free(this->data);
  	}
  	this->data = NULL;
  }
  
  int Camera1394::SetZoom(unsigned int zoom) {
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_ZOOM, zoom))
  #else
  	if (DC1394_SUCCESS
  			!= dc1394_set_zoom(this->handle, this->camera.node, zoom))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Zoom value");
  		return -1;
  	}
  	return 0;
  }
  
  int Camera1394::GetZoom(unsigned int* zoom) {
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_value(this->camera, FEATURE_ZOOM, zoom))
  #else
  	if (DC1394_SUCCESS
  			!= dc1394_get_zoom(this->handle, this->camera.node, zoom))
  #endif
  	{
  		PLAYER_ERROR("Unable to get Zoom value");
  		return -1;
  	}
  	return 0;
  }
  
  int Camera1394::SetFocus(unsigned int focus) {
  	bool autoFocus = focus < 0;
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_FOCUS,autoFocus ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_FOCUS, autoFocus))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Focus mode");
  		this->SafeCleanup();
  		return -1;
  	}
  	if (!autoFocus) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_FOCUS, focus))
  #else
  		if (DC1394_SUCCESS != dc1394_set_focus(this->handle, this->camera.node,
  				focus))
  #endif
  		{
  			PLAYER_ERROR("Unable to set Focus value");
  			return -1;
  		}
  	}
  	return 0;
  }
  
  int Camera1394::GetFocus(unsigned int* focus) {
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_value(this->camera, FEATURE_FOCUS, focus))
  #else
  	if (DC1394_SUCCESS != dc1394_get_focus(this->handle, this->camera.node,
  			focus))
  #endif
  	{
  		PLAYER_ERROR("Unable to get Focus value");
  		return -1;
  	}
  	return 0;
  }
  
  int Camera1394::SetIris(unsigned int iris) {
  	bool autoIris = iris < 0;
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_IRIS,autoIris ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_IRIS, autoIris))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Iris mode");
  		this->SafeCleanup();
  		return -1;
  	}
  
  	if (!autoIris) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_IRIS, iris))
  #else
  		if (DC1394_SUCCESS != dc1394_set_iris(this->handle, this->camera.node,
  				iris))
  #endif
  		{
  			PLAYER_ERROR("Unable to set Iris value");
  			return -1;
  		}
  	}
  	return 0;
  }
  
  int Camera1394::GetIris(unsigned int* iris) {
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_value(this->camera, FEATURE_IRIS, iris))
  #else
  	if (DC1394_SUCCESS
  			!= dc1394_get_iris(this->handle, this->camera.node, iris))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Iris value");
  		return -1;
  	}
  	return 0;
  }
  
  int Camera1394::SetBrightness(unsigned int brightness) {
  	bool autoBrightness = brightness < 0;
  
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_BRIGHTNESS,autoBrightness ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_BRIGHTNESS, autoBrightness))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Brightness mode");
  		this->SafeCleanup();
  		return -1;
  	}
  
  	if (!autoBrightness) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_BRIGHTNESS, brightness))
  #else
  		if (DC1394_SUCCESS != dc1394_set_brightness(this->handle,
  				this->camera.node, brightness))
  #endif
  		{
  			PLAYER_ERROR("Unable to set Brightness value");
  			return -1;
  		}
  	}
  	return 0;
  }
  
  int Camera1394::SetExposure(unsigned int exposure) {
  	bool autoExposure = exposure < 0;
  
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_EXPOSURE,autoExposure ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_EXPOSURE, autoExposure))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Exposure mode");
  		this->SafeCleanup();
  		return -1;
  	}
  
  	if (!autoExposure) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_EXPOSURE, exposure))
  #else
  		if (DC1394_SUCCESS != dc1394_set_exposure(this->handle,
  				this->camera.node, exposure))
  #endif
  		{
  			PLAYER_ERROR("Unable to set Exposure value");
  			return -1;
  		}
  	}
  	return 0;
  }
  
  int Camera1394::SetShutter(unsigned int shutter) {
  	bool autoShutter = shutter < 0;
  
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_SHUTTER,autoShutter ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_SHUTTER, autoShutter))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Shutter mode");
  		this->SafeCleanup();
  		return -1;
  	}
  	if (!autoShutter) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_SHUTTER, shutter))
  #else
  		if (DC1394_SUCCESS != dc1394_set_shutter(this->handle,
  				this->camera.node, shutter))
  #endif
  		{
  			PLAYER_ERROR("Unable to set Shutter value");
  			return -1;
  		}
  	}
  	return 0;
  }
  
  int Camera1394::SetGain(unsigned int gain) {
  	bool autoGain = gain < 0;
  
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_GAIN,autoGain ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  #else
  	if (DC1394_SUCCESS != dc1394_auto_on_off(this->handle, this->camera.node,
  			FEATURE_GAIN, autoGain))
  #endif
  	{
  		PLAYER_ERROR("Unable to set Gain mode");
  		this->SafeCleanup();
  		return -1;
  	}
  	if (!autoGain) {
  #if LIBDC1394_VERSION == 0200
  		if (DC1394_SUCCESS != dc1394_feature_set_value(this->camera, FEATURE_GAIN,gain))
  #else
  		if (DC1394_SUCCESS != dc1394_set_gain(this->handle, this->camera.node,
  				gain))
  #endif
  		{
  			PLAYER_ERROR("Unable to Gain value");
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	return 0;
  }
  
  
  int Camera1394::SetWhiteBalance(const char* whitebalance) {
    bool setWhiteBalance = false;
    bool autoWhiteBalance = false;
    unsigned int blueBalance, redBalance;
    
    if (!strcmp(whitebalance,"auto"))
      {
  #if LIBDC1394_VERSION == 0200
        setWhiteBalance=true;
        autoWhiteBalance=true;
  #else
        setWhiteBalance=false;
  #endif
      }
    else
      {
        autoWhiteBalance=false;
        if(sscanf(whitebalance,"%u %u",&blueBalance,&redBalance)==2)
  	setWhiteBalance=true;
        else
  	PLAYER_ERROR1("didn't understand white balance values [%s]", whitebalance);
      }
    
    if (setWhiteBalance)
      {
  #if LIBDC1394_VERSION == 0200
        if (DC1394_SUCCESS != dc1394_feature_set_mode(this->camera, FEATURE_WHITE_BALANCE,autoWhiteBalance ? DC1394_FEATURE_MODE_AUTO : DC1394_FEATURE_MODE_MANUAL))
  	{
  	  PLAYER_ERROR("Unable to set White Balance mode");
  	  this->SafeCleanup();
  	  return -1;
  	}
        if (!autoWhiteBalance)
  	if (DC1394_SUCCESS != dc1394_feature_whitebalance_set_value(this->camera,blueBalance,redBalance))
  #else
  	  if (DC1394_SUCCESS != dc1394_set_white_balance(this->handle, this->camera.node,blueBalance,redBalance))
  #endif
  	    {
  	      PLAYER_ERROR("Unable to set White Balance");
  	      this->SafeCleanup();
  	      return -1;
  	    }
      }
    
    
    return 0;
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  // Set up the device (called by server thread).
  int Camera1394::MainSetup() {
  
  #if LIBDC1394_VERSION == 0200
  	dc1394speed_t speed;
  #else
  	unsigned int channel, speed;
  #endif
  
  	// Create a handle for the given port (port will be zero on most
  	// machines)
  #if LIBDC1394_VERSION == 0200
    // First we try to find a camera
    int err;
    dc1394_t *d;
    dc1394camera_list_t *list;
    
    d = dc1394_new ();
    err = dc1394_camera_enumerate (d, &list);
    if (err != DC1394_SUCCESS)
      {
        PLAYER_ERROR1("Could not get Camera List: %d\n", err);
        return -1;
      }
    
    if (list->num == 0)
      {
        PLAYER_ERROR("No cameras found");
        return -1;
      }
    
    char* temp=(char*)malloc(1024*sizeof(char));
    for (unsigned i=0; i < list->num; i++)
      {
        uint32_t camNode, camGeneration;
        
        // Create a camera
        this->camera = dc1394_camera_new (d, list->ids[i].guid);
        if (!camera)
  	PLAYER_ERROR1("Failed to initialize camera with guid %016llx",
  		      list->ids[i].guid);
        else PLAYER_MSG1(2,"Found camera with GUID %016llx",
  		       list->ids[i].guid);
        
        if (this->use_guid) {
  	
  	quadlet_t value[3];
  	
  	value[0]= camera->guid & 0xffffffff;
  	value[1]= (camera->guid >>32) & 0x000000ff;
  	value[2]= (camera->guid >>40) & 0xfffff;
  	
  	sprintf(temp,"%06x%02x%08x", value[2], value[1], value[0]);
  	
  	PLAYER_MSG2(5,"Comparing %s to %s",this->guid,temp);
  	if (strcmp(temp,this->guid)==0)
  	  break;
        }
        else 
  	{
  	  // Get the node of the camera
  	  dc1394_camera_get_node(this->camera, &camNode, &camGeneration);
  	  
  	  // Make sure we have the correct camera
  	  if (camNode == this->node)
  #if DC1394_2_LINUX == 1 
  	    {
  	      unsigned int cam_port;
  	      get_port(this->camera, cam_port);
  	      if (cam_port == this->port)
  		break;
  	    }
  #else
  	  break;
  #endif
  	}
        this->SafeCleanup();
      }
    free (temp);
    dc1394_camera_free_list (list);
    
    if (!camera)
      {
        if (this->use_guid)
  	PLAYER_ERROR1("Could not find camera with guid %s",
  		      this->guid);
        else 
  #if DC1394_2_LINUX == 1
  	PLAYER_ERROR2("Could not find camera with node %d, port %d",
  		      this->node, this->port);
  #else
        PLAYER_ERROR("On this system, you cannot specify a node/port.  You should specify the GUID of the camera.");
  #endif
        return -1;
      }
  
  #else
  	this->handle = dc1394_create_handle(this->port);
  	if (this->handle == NULL) {
  		PLAYER_ERROR("Unable to acquire a dc1394 handle");
  		this->SafeCleanup();
  		return -1;
  	}
  
  	this->camera.node = this->node;
  	this->camera.port = this->port;
  #endif
  
  	// apply user config file provided camera settings
  	if (this->Focus != PROPERTY_NOT_SET) {
  		if (this->SetFocus(this->Focus)) {
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	if (this->Iris != PROPERTY_NOT_SET) {
  		if (this->SetIris(this->Iris)) {
  			// error
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	if (this->Brightness != PROPERTY_NOT_SET) {
  		if (this->SetBrightness(this->Brightness)) {
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	if (this->Exposure != PROPERTY_NOT_SET) {
  		if (this->SetExposure(this->Exposure)) {
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	if (this->Shutter != PROPERTY_NOT_SET) {
  		if (this->SetShutter(this->Shutter)) {
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  	if (this->Gain != PROPERTY_NOT_SET) {
  		if (this->SetGain(this->Gain)) {
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  
  	if (strcmp(this->WhiteBalance,"None")) {
  	  if (this->SetWhiteBalance(this->WhiteBalance)) {
  	    this->SafeCleanup();
  	    return -1;
  	  }
  	}
  	
  
  	// Collects the available features for the camera described by node and
  	// stores them in features.
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_all(camera, &this->features))
  #else
  	if (DC1394_SUCCESS != dc1394_get_camera_feature_set(this->handle,
  			this->camera.node, &this->features))
  #endif
  	{
  		PLAYER_ERROR("Unable to get feature set");
  		this->SafeCleanup();
  		return -1;
  	}
  
  	uint32_t min_zoom, max_zoom;
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_boundaries(camera, FEATURE_ZOOM, &min_zoom, &max_zoom))
  #else
  	if ((DC1394_SUCCESS != dc1394_get_min_value(this->handle,
  			this->camera.node, FEATURE_ZOOM, &min_zoom))
  			|| (DC1394_SUCCESS != dc1394_get_max_value(this->handle,
  					this->camera.node, FEATURE_ZOOM, &max_zoom)))
  #endif
  	{
  		PLAYER_ERROR("Unable to get zoom boundaries");
  		this->SafeCleanup();
  		return -1;
  	}
  	MinZoom = min_zoom;
  	MaxZoom = max_zoom;
  
  	uint32_t min_focus,max_focus;
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_boundaries(camera, FEATURE_FOCUS, &min_focus, &max_focus))
  #else
  	if ((DC1394_SUCCESS != dc1394_get_min_value(this->handle,
  			this->camera.node, FEATURE_FOCUS, &min_focus))
  			|| (DC1394_SUCCESS != dc1394_get_max_value(this->handle,
  					this->camera.node, FEATURE_FOCUS, &max_focus)))
  #endif
  	{
  		PLAYER_ERROR("Unable to get focus boundaries");
  		this->SafeCleanup();
  		return -1;
  	}
  	MinFocus = min_focus;
  	MaxFocus = max_focus;
  
  	uint32_t min_iris, max_iris;
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_feature_get_boundaries(camera, FEATURE_IRIS, &min_iris, &max_iris))
  #else
  	if ((DC1394_SUCCESS != dc1394_get_min_value(this->handle,
  			this->camera.node, FEATURE_IRIS, &min_iris))
  			|| (DC1394_SUCCESS != dc1394_get_max_value(this->handle,
  					this->camera.node, FEATURE_IRIS, &max_iris)))
  #endif
  	{
  		PLAYER_ERROR("Unable to get iris boundaries");
  		this->SafeCleanup();
  		return -1;
  	}
  	MinIris = min_iris;
  	MaxIris = max_iris;
  
  	// TODO: need to indicate what formats the camera supports somewhere
  	// Remove; leave?
  
  #if LIBDC1394_VERSION == 0200
  	// if format 7 requested check that it is supported
  	if (FORMAT_7==this->format && DC1394_SUCCESS!=dc1394_format7_get_modeset(camera, &modeset))
  	{
  		bool HasMode7 = false;
  		for (unsigned int i=0;i<DC1394_VIDEO_MODE_FORMAT7_NUM;i++)
  		{
  			if (modeset.mode[i].present!=0)
  			{
  				HasMode7 = true;
  				break;
  			}
  		}
  		if (!HasMode7)
  		{
  			PLAYER_ERROR("Could not set Format 7");
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  #endif
  
  	// Get the ISO channel and speed of the video
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_video_get_iso_speed(this->camera, &speed))
  #else
  	if (DC1394_SUCCESS != dc1394_get_iso_channel_and_speed(this->handle,
  			this->camera.node, &channel, &speed))
  #endif
  	{
  		PLAYER_ERROR("Unable to get iso data; is the camera plugged in?");
  		this->SafeCleanup();
  		return -1;
  	}
  
  #if DC1394_DMA_SETUP_CAPTURE_ARGS == 11
  	// Set camera to use DMA, improves performance.
  	if (!this->forceRaw &&
  			dc1394_dma_setup_capture(this->handle, this->camera.node, channel,
  					this->format, this->mode, this->iso_speed,
  					this->frameRate, this->num_dma_buffers, 1, NULL,
  					&this->camera) == DC1394_SUCCESS)
  #elif DC1394_DMA_SETUP_CAPTURE_ARGS == 12
  	// Set camera to use DMA, improves performance.
  	if (!this->forceRaw &&
  			dc1394_dma_setup_capture(this->handle, this->camera.node, channel,
  					this->format, this->mode, this->iso_speed,
  					this->frameRate, this->num_dma_buffers, 1, 0, NULL,
  					&this->camera) == DC1394_SUCCESS)
  #elif LIBDC1394_VERSION == 0200
  	// Set camera to use DMA, improves performance.
  	bool DMA_Success = true;
  	if (!this->forceRaw)
  	{
  		// first set parameters that are common between format 7 and other modes
  		if (DC1394_SUCCESS != dc1394_video_set_framerate(camera,frameRate))
  		{
  			PLAYER_WARN("1394 failed to set frameRate");
  			DMA_Success = false;
  		}
  		if (DC1394_SUCCESS != dc1394_video_set_iso_speed(camera,this->iso_speed))
  		{
  			PLAYER_WARN("1394 failed to set iso speed");
  			DMA_Success = false;
  		}
  		if (DC1394_SUCCESS != dc1394_video_set_mode(camera,mode))
  		{
  			PLAYER_WARN("1394 failed to set mode");
  			DMA_Success = false;
  		}
  
  		// now start capture
  		if (DC1394_SUCCESS != dc1394_capture_setup(camera, this->num_dma_buffers, DC1394_CAPTURE_FLAGS_DEFAULT))
  		DMA_Success = false;
  	}
  	if (DMA_Success)
  #else
  	if (0)
  #endif
  	{
  		this->method = methodVideo;
  	} else {
  		PLAYER_WARN("DMA capture failed; falling back on RAW method");
  
  		// Set camera to use RAW method (fallback)
  #if LIBDC1394_VERSION == 0200
  		if (0)
  #else
  		if (dc1394_setup_capture(this->handle, this->camera.node, channel,
  				this->format, this->mode, SPEED_400, this->frameRate,
  				&this->camera) == DC1394_SUCCESS)
  #endif
  		{
  			this->method = methodRaw;
  		} else {
  			PLAYER_ERROR("unable to open camera in VIDE0 or RAW modes");
  			this->SafeCleanup();
  			return -1;
  		}
  	}
  
  	// Start transmitting camera data
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_video_set_transmission(this->camera, DC1394_ON))
  #else
  	if (DC1394_SUCCESS != dc1394_start_iso_transmission(this->handle,
  			this->camera.node))
  #endif
  	{
  		PLAYER_ERROR("unable to start camera");
  		this->SafeCleanup();
  		return -1;
  	}
  	return 0;
  }
  
  void Camera1394::MainQuit() {
  
  	// Stop transmitting camera data
  #if LIBDC1394_VERSION == 0200
  	if (DC1394_SUCCESS != dc1394_video_set_transmission(this->camera, DC1394_OFF)
  			|| DC1394_SUCCESS != dc1394_capture_stop(this->camera))
  #else
  	if (dc1394_stop_iso_transmission(this->handle, this->camera.node)
  			!= DC1394_SUCCESS)
  #endif
  		PLAYER_WARN("unable to stop camera");
  
  	// Free resources
  	this->SafeCleanup();
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Main function for device thread
  void Camera1394::Main() {
  	//   char filename[255];
  	//   int frameno;
  
  	frameno = 0;
  	//struct timeval now,old;
  	while (true) {
  
  		// Go to sleep for a while (this is a polling loop).
  		// We shouldn't need to sleep if GrabFrame is blocking.
  		nanosleep(&NSLEEP_TIME, NULL);
  
  		// Test if we are supposed to cancel this thread.
  		pthread_testcancel();
  
  		// Process any pending requests.
  		ProcessMessages();
  
  		// grab and save frame within RefreshData()
  		//     // Grab the next frame (blocking)
  		//     this->GrabFrame();
  
  		//     // this should go or be replaced
  		//     // Save frames; must be done after writedata (which will byteswap)
  		//     if (this->save)
  		//     {
  		//       //printf("click %d\n", frameno);
  		//       snprintf(filename, sizeof(filename), "click-%04d.ppm", frameno++);
  		//       this->SaveFrame(filename);
  		//     }
  
  		// Write data to server
  		this->RefreshData();
  
  		/*
  		 gettimeofday(&now,NULL);
  		 printf("dt = %lf\n",now.tv_sec-old.tv_sec+(now.tv_usec-old.tv_usec)*1.0e-6);
  		 old=now;
  		 */
  	}
  	printf("Camera1394::main() exited\n");
  
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Process an incoming message
  int Camera1394::ProcessMessage(QueuePointer & resp_queue, player_msghdr * hdr,
  		void * data) {
  	assert(hdr);
  
  	// handle changes in the properties that we can
  	if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
  			PLAYER_SET_INTPROP_REQ, device_addr)) {
  
  		player_intprop_req_t &req = *reinterpret_cast<player_intprop_req_t*> (data);
  		if (strcmp(Zoom.GetKey(),req.key)==0)
  		{
  			if (SetZoom(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Focus.GetKey(),req.key)==0)
  		{
  			if (SetFocus(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Iris.GetKey(),req.key)==0)
  		{
  			if (SetIris(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Brightness.GetKey(),req.key)==0)
  		{
  			if (SetBrightness(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Exposure.GetKey(),req.key)==0)
  		{
  			if (SetExposure(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Shutter.GetKey(),req.key)==0)
  		{
  			if (SetShutter(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  		else if (strcmp(Gain.GetKey(),req.key)==0)
  		{
  			if (SetGain(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  	}
  	else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
  			PLAYER_SET_STRPROP_REQ, device_addr)) {
  		player_strprop_req_t &req = *reinterpret_cast<player_strprop_req_t*> (data);
  		if (strcmp(WhiteBalance.GetKey(),req.key)==0)
  		{
  			if (SetWhiteBalance(req.value))
  			{
  				Publish(device_addr, resp_queue, PLAYER_MSGTYPE_RESP_NACK, hdr->subtype);
  				return 0;
  			}
  			return -1;
  		}
  	}
  	return -1;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Store an image frame into the 'frame' buffer
  int Camera1394::GrabFrame() {
  #if LIBDC1394_VERSION == 0200
  	dc1394video_frame_t * frame = NULL;
  #endif
  	switch (this->method) {
  	case methodRaw:
  #if LIBDC1394_VERSION == 0200
  		if (1)
  #else
  		if (dc1394_single_capture(this->handle, &this->camera)
  				!= DC1394_SUCCESS)
  #endif
  		{
  			PLAYER_ERROR("Unable to capture frame");
  			return -1;
  		}
  		break;
  	case methodVideo:
  #if LIBDC1394_VERSION == 0200
  		dc1394_capture_dequeue (camera, DC1394_CAPTURE_POLICY_WAIT, &frame);
  		if (!frame)
  #else
  		if (dc1394_dma_single_capture(&this->camera) != DC1394_SUCCESS)
  #endif
  		{
  			PLAYER_ERROR("Unable to capture frame");
  			return -1;
  		}
  		break;
  	default:
  		PLAYER_ERROR("Unknown grab method");
  		return -1;
  	}
  
  	unsigned int frame_width;
  	unsigned int frame_height;
  	uint8_t * capture_buffer;
  #if LIBDC1394_VERSION == 0200
  	frameTime = frame->timestamp*1.e-6;
  	frame_width = frame->size[0];
  	frame_height = frame->size[1];
  	capture_buffer = reinterpret_cast<uint8_t *>(frame->image);
  #else
  	frame_width = this->camera.frame_width;
  	frame_height = this->camera.frame_height;
  	capture_buffer = reinterpret_cast<uint8_t *> (this->camera.capture_buffer);
  #endif
  	assert(capture_buffer);
  	//   assert(!(this->data));
  	//   this->data = reinterpret_cast<player_camera_data_t *>(malloc(sizeof(player_camera_data_t)));
  	assert(this->data);
  	// memset(this->data, 0, sizeof(player_camera_data_t)); I assume everything is set properly later!
  	switch (this->mode) {
  	case MODE_320x240_YUV422:
  	case MODE_640x480_YUV422:
  	case MODE_800x600_YUV422:
  	case MODE_1024x768_YUV422:
  	case MODE_1280x960_YUV422:
  		this->data->bpp = 24;
  		this->data->format = PLAYER_CAMERA_FORMAT_RGB888;
  		this->data->image_count = frame_width * frame_height * 3;
  		this->data->image = reinterpret_cast<uint8_t *> (malloc(
  				this->data->image_count));
  		assert(this->data->image);
  		this->data->width = frame_width;
  		this->data->height = frame_height;
  		uyvy2rgb(reinterpret_cast<unsigned char *> (capture_buffer),
  				reinterpret_cast<unsigned char *> (this->data->image),
  				frame_width * frame_height);
  		break;
  	case MODE_640x480_RGB:
  		this->data->bpp = 24;
  		this->data->format = PLAYER_CAMERA_FORMAT_RGB888;
  		this->data->image_count = frame_width * frame_height * 3;
  		this->data->image = reinterpret_cast<uint8_t *> (malloc(
  				this->data->image_count));
  		assert(this->data->image);
  		this->data->width = frame_width;
  		this->data->height = frame_height;
  		memcpy(this->data->image, capture_buffer, this->data->image_count);
  		break;
  	case MODE_640x480_MONO:
  	case MODE_800x600_MONO:
  	case MODE_1024x768_MONO:
  	case MODE_1280x960_MONO:
  	case MODE_FORMAT7_0:
  		if (!DoBayerConversion) {
  			this->data->bpp = 8;
  			this->data->format = PLAYER_CAMERA_FORMAT_MONO8;
  			this->data->image_count = frame_width * frame_height;
  			this->data->image = reinterpret_cast<uint8_t *> (malloc(
  					this->data->image_count));
  			assert(this->data->image);
  			this->data->width = frame_width;
  			this->data->height = frame_height;
  			memcpy(this->data->image, capture_buffer, this->data->image_count);
  		} else {
  			this->data->bpp = 24;
  			this->data->format = PLAYER_CAMERA_FORMAT_RGB888;
  			switch (this->BayerMethod) {
  
  			case BAYER_DECODING_DOWNSAMPLE:
  				// quarter of the image but 3 bytes per pixel
  				this->data->image_count = (frame_width / 2)
  						* (frame_height / 2) * 3;
  				this->data->image = reinterpret_cast<uint8_t *> (malloc(
  						this->data->image_count));
  				assert(this->data->image);
  				BayerDownsample(
  						reinterpret_cast<unsigned char *> (capture_buffer),
  						reinterpret_cast<unsigned char *> (this->data->image),
  						frame_width / 2, frame_height / 2, this->BayerPattern);
  				break;
  			case BAYER_DECODING_NEAREST:
  				this->data->image_count = frame_width * frame_height * 3;
  				this->data->image = reinterpret_cast<uint8_t *> (malloc(
  						this->data->image_count));
  				assert(this->data->image);
  				BayerNearestNeighbor(
  						reinterpret_cast<unsigned char *> (capture_buffer),
  						reinterpret_cast<unsigned char *> (this->data->image),
  						frame_width, frame_height, this->BayerPattern);
  				break;
  			case BAYER_DECODING_EDGE_SENSE:
  				this->data->image_count = frame_width * frame_height * 3;
  				this->data->image = reinterpret_cast<uint8_t *> (malloc(
  						this->data->image_count));
  				assert(this->data->image);
  				BayerEdgeSense(
  						reinterpret_cast<unsigned char *> (capture_buffer),
  						reinterpret_cast<unsigned char *> (this->data->image),
  						frame_width, frame_height, this->BayerPattern);
  				break;
  			default:
  				PLAYER_ERROR("camera1394: Unknown Bayer Method");
  				return -1;
  			}
  			if (this->BayerMethod != BAYER_DECODING_DOWNSAMPLE) {
  				this->data->width = frame_width;
  				this->data->height = frame_height;
  			} else { //image is half the size of grabbed frame
  				this->data->width = frame_width / 2;
  				this->data->height = frame_height / 2;
  			}
  		}
  		break;
  	default:
  		PLAYER_ERROR("camera1394: Unknown mode");
  		return -1;
  	}
  #if LIBDC1394_VERSION == 0200
  	if (this->method == methodVideo) dc1394_capture_enqueue(camera, frame);
  #else
  	if (this->method == methodVideo)
  		dc1394_dma_done_with_buffer(&this->camera);
  #endif
  	this->data->compression = PLAYER_CAMERA_COMPRESS_RAW;
  	return 0;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Update the device data (the data going back to the client).
  void Camera1394::RefreshData() {
  	//   assert(!(this->data));
  	if (!(this->data))
  		this->data = reinterpret_cast<player_camera_data_t *> (malloc(
  				sizeof(player_camera_data_t)));
  	assert(this->data);
  
  	if (!GrabFrame()) {
  		// this should go or be replaced
  		// Save frames; must be done after writedata (which will byteswap)
  		if (this->save) {
  			char filename[255];
  			snprintf(filename, sizeof(filename), "click-%04d.ppm",
  					this->frameno++);
  			this->SaveFrame(filename);
  		}
  
  		assert(this->data);
  		if (!(this->data->image_count)) {
  			PLAYER_ERROR("No image data to publish");
  			return;
  		}
  		assert(this->data->image);
  
  		Publish(this->device_addr, PLAYER_MSGTYPE_DATA,
  				PLAYER_CAMERA_DATA_STATE,
  				reinterpret_cast<void *> (this->data),
  #if LIBDC1394_VERSION == 0200
  				0, &this->frameTime, false);
  #else
  				0, NULL, false);
  #endif
  		// I assume that Publish() freed this data!
  		this->data = NULL;
  	}
  	return;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Save a frame to disk
  int Camera1394::SaveFrame(const char *filename) {
  	FILE * fp;
  
  	assert(this->data);
  	if (!(this->data->image_count)) {
  		PLAYER_ERROR("No image data to write");
  		return -1;
  	}
  	assert(this->data->image);
  
  	fp = fopen(filename, "wb");
  	if (!fp) {
  		PLAYER_ERROR("Couldn't create image file");
  		return -1;
  	}
  
  	int ret = 0;
  	switch (this->data->format) {
  	case PLAYER_CAMERA_FORMAT_MONO8:
  		fprintf(fp, "P5\n%u %u\n255\n", this->data->width, this->data->height);
  		ret = fwrite((unsigned char*) this->data->image, 1,
  				this->data->image_count, fp);
  		break;
  	case PLAYER_CAMERA_FORMAT_RGB888:
  		fprintf(fp, "P6\n%u %u\n255\n", this->data->width, this->data->height);
  		ret = fwrite((unsigned char*) this->data->image, 1,
  				this->data->image_count, fp);
  		break;
  	default:
  		break;
  	}
  	fclose(fp);
  
  	if (ret < 0) {
  		PLAYER_ERROR("Failed to save frame");
  	}
  
  	return 0;
  }
  
  