Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraSourceQTKit.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_CameraSourceQTKit_h_
00003 #define INCLUDED_CameraSourceQTKit_h_
00004 
00005 #include "local/DataSource.h"
00006 #include "Shared/plistCollections.h"
00007 #include <QTKit/QTKit.h>
00008 #include <CoreVideo/CVPixelBuffer.h> // for kCVPixelFormatTypes
00009 #include <QuickTime/ImageCompression.h> // for kComponentVideoUnsigned
00010 
00011 @class CameraSourceQTKitDelegate;
00012 
00013 //! This interfaces with a specific camera through the QTKit API, which is the only capture interface which supports 64-bit on OS X
00014 class CameraSourceQTKit : public DataSource, public virtual plist::Dictionary {
00015 public:
00016   
00017   //! If true, will attempt to use Apple's Grand Central Dispatch to do block processing... this parallelizes image processing, may slightly increase total CPU usage but reduces per-frame wall time
00018   plist::Primitive<bool> parallel;
00019   
00020   //! If true, upsamples color channels horizontally to match Y channel, otherwise downsamples everything to common resolution (y/4, u,v/2); set to true to use full resolution of camera (either as the “full” layer or if you are accessing the “double” layer), set to false if you are using half-resolution as the resolution of the “full” layer
00021   plist::Primitive<bool> highRes;
00022   
00023   //! Controls the resolution layer at which the image should be processed.\n 0 indicates "automatic" mode (picks layer closest to image's resolution), positive numbers indicate the resolution layer directly.\n Negative values are relative to the number of layers marked available by the vision setup, so that typically -1 would correspond to the "double" layer, and -2 would correspond to the "full" layer.
00024   plist::Primitive<int> layer;
00025   
00026   //! Conversion formats supported for requesting camera output
00027   enum PixelFormat_t {
00028     TYPE_UNKNOWN=0, //!< should avoid requesting any format, see what the camera's “native” format is
00029     TYPE_YUVS = kComponentVideoUnsigned, //!< the native format for iSight camera on 2010 Macbook Pros, 10.6.3
00030     TYPE_2VUY = kCVPixelFormatType_422YpCbCr8, //!< alternative supported format of 2010 iSight camera on 10.6.3, byte reordering of #TYPE_YUVS
00031     TYPE_GRAY = kCVPixelFormatType_8IndexedGray_WhiteIsZero //!< alternative supported format of 2010 iSight camera on 10.6.3, Y channel only
00032   };
00033   
00034   //! If non-empty, requests the camera convert to the specified format (a four character code aka FourCC)
00035   plist::NamedEnumeration<PixelFormat_t> format;
00036   
00037   //! constructor
00038   CameraSourceQTKit(const std::string& srcName, QTCaptureDevice* capDevice)
00039     : DataSource(), parallel(true), highRes(false), layer(0), format(TYPE_UNKNOWN), name(srcName), device(capDevice), session(NULL), delegate(NULL), frame(0), lastTime(0), duration(0), oneFrame(false), frameLock(), frameCond()
00040   {
00041     init();
00042   }
00043   
00044   //! destructor
00045   ~CameraSourceQTKit();
00046   
00047   virtual unsigned int nextTimestamp() { return static_cast<unsigned int>((lastTime+duration)*1000); }
00048   virtual const std::string& nextName() { return name; }
00049   
00050   virtual void registerSource();
00051   virtual void deregisterSource();
00052   virtual bool advance();
00053   
00054   //! called from #delegate with each frame
00055   void processImage(CVImageBufferRef videoFrame, QTSampleBuffer* sampleBuffer);
00056 
00057 protected:
00058   void init(); //!< general initialization: add configuration entries, retain #device and create #delegate
00059   void doFreeze();
00060   void doUnfreeze();
00061   
00062   //! Returns the four-character-code as a string for display
00063   static std::string CC2Str(unsigned int fourcc);
00064   
00065   //! returns the display string as a four-character-code
00066   static unsigned int Str2CC(const std::string& fourcc);
00067   
00068   
00069   //! yuyv ordering, upsample by duplicating u and v columns
00070   /*! Uses CCIR601 range (e.g. Y ∈ [16,235] ) */
00071   void process_yuvs_U(const unsigned char * s, unsigned int srcWidth, unsigned int srcHeight);
00072   
00073   //! yuyv ordering, downsample to common resolution (y/4, u,v/2)
00074   /*! Uses CCIR601 range (e.g. Y ∈ [16,235] ) */
00075   void process_yuvs_D(const unsigned char * s, unsigned int srcWidth, unsigned int srcHeight);
00076   
00077   
00078   //! uyvy ordering, upsample by duplicating u and v columns
00079   /*! Uses CCIR601 range (e.g. Y ∈ [16,235] ) */
00080   void process_2vuy_D(const unsigned char * s, unsigned int srcWidth, unsigned int srcHeight);
00081   
00082   //! uyvy ordering, downsample to common resolution (y/4, u,v/2)
00083   /*! Uses CCIR601 range (e.g. Y ∈ [16,235] ) */
00084   void process_2vuy_U(const unsigned char * s, unsigned int srcWidth, unsigned int srcHeight);
00085   
00086   
00087   //! Grayscale, white is 0
00088   /*! Need to convert to CCIR601 (y = (255-g)·219/255+16) and fill in u=v=128 
00089    *  You might think compressing the Y range would lower quality, but inspecting data from iSight indicates it originates as CCIR601,
00090    *  with this setting showing gaps in the histogram as it was stretched to full range, so really this is just resetting */
00091   void process_grayscale_zerowhite(const unsigned char * s, unsigned int srcWidth, unsigned int srcHeight);
00092 
00093   std::string name;
00094   QTCaptureDevice* const device; //!< the camera associated with this instance
00095   QTCaptureSession* session; //!< the capture session created in registerSource (thus non-NULL if registered), used to start/stop capture when frozen
00096   CameraSourceQTKitDelegate* delegate; //!< receives per-frame callbacks from the #session, forwards calls to processImage()
00097   
00098   unsigned int frame; //!< a frame index counter
00099   float lastTime; //!< time in seconds of ideal frame arrival time, if drifts more than a frame duration, reset via get_time()
00100   float duration; //!< the frame duration encoded in the captured frame meta-data
00101   bool oneFrame; //!< set to true by advance(), indicates capture should stop once a frame is sent
00102   Thread::Lock frameLock; //!< held by advance() when waiting for a frame
00103   Thread::Condition frameCond; //!< condition to wake up advance when a frame has been sent
00104   
00105 private:
00106   CameraSourceQTKit(const CameraSourceQTKit&); //!< do not copy
00107   CameraSourceQTKit& operator=(const CameraSourceQTKit&); //!< do not assign
00108 };
00109 
00110 @interface CameraSourceQTKitDelegate : NSObject {
00111 @public
00112   CameraSourceQTKit * target;
00113 }
00114 -(CameraSourceQTKitDelegate*) initWithTarget:(CameraSourceQTKit*)tgt;
00115 @end
00116 
00117 
00118 
00119 /*! @file
00120  * @brief 
00121  * @author Ethan Tira-Thompson (ejt) (Creator)
00122  */
00123 
00124 #endif

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:38 2016 by Doxygen 1.6.3