--- /dev/null
+#ifndef _VIDEOINPUT\r
+#define _VIDEOINPUT\r
+\r
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+//THE SOFTWARE.\r
+\r
+//////////////////////////////////////////////////////////\r
+//Written by Theodore Watson - theo.watson@gmail.com //\r
+//Do whatever you want with this code but if you find //\r
+//a bug or make an improvement I would love to know! //\r
+// //\r
+//Warning This code is experimental //\r
+//use at your own risk :) //\r
+//////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////\r
+/* Shoutouts \r
+\r
+Thanks to: \r
+ \r
+ Dillip Kumar Kara for crossbar code.\r
+ Zachary Lieberman for getting me into this stuff\r
+ and for being so generous with time and code.\r
+ The guys at Potion Design for helping me with VC++\r
+ Josh Fisher for being a serious C++ nerd :)\r
+ Golan Levin for helping me debug the strangest \r
+ and slowest bug in the world!\r
+ \r
+ And all the people using this library who send in \r
+ bugs, suggestions and improvements who keep me working on \r
+ the next version - yeah thanks a lot ;)\r
+ \r
+*/\r
+/////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <math.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+\r
+//this is for TryEnterCriticalSection\r
+#ifndef _WIN32_WINNT\r
+ # define _WIN32_WINNT 0x400\r
+#endif\r
+#include <windows.h>\r
+\r
+\r
+//Example Usage\r
+/*\r
+ //create a videoInput object\r
+ videoInput VI;\r
+ \r
+ //Prints out a list of available devices and returns num of devices found\r
+ int numDevices = VI.listDevices(); \r
+ \r
+ int device1 = 0; //this could be any deviceID that shows up in listDevices\r
+ int device2 = 1; //this could be any deviceID that shows up in listDevices\r
+ \r
+ //if you want to capture at a different frame rate (default is 30) \r
+ //specify it here, you are not guaranteed to get this fps though.\r
+ //VI.setIdealFramerate(dev, 60); \r
+ \r
+ //setup the first device - there are a number of options:\r
+ \r
+ VI.setupDevice(device1); //setup the first device with the default settings\r
+ //VI.setupDevice(device1, VI_COMPOSITE); //or setup device with specific connection type\r
+ //VI.setupDevice(device1, 320, 240); //or setup device with specified video size\r
+ //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type\r
+\r
+ //VI.setFormat(device1, VI_NTSC_M); //if your card doesn't remember what format it should be\r
+ //call this with the appropriate format listed above\r
+ //NOTE: must be called after setupDevice!\r
+ \r
+ //optionally setup a second (or third, fourth ...) device - same options as above\r
+ VI.setupDevice(device2); \r
+\r
+ //As requested width and height can not always be accomodated\r
+ //make sure to check the size once the device is setup\r
+\r
+ int width = VI.getWidth(device1);\r
+ int height = VI.getHeight(device1);\r
+ int size = VI.getSize(device1);\r
+ \r
+ unsigned char * yourBuffer1 = new unsigned char[size];\r
+ unsigned char * yourBuffer2 = new unsigned char[size];\r
+ \r
+ //to get the data from the device first check if the data is new\r
+ if(VI.isFrameNew(device1)){\r
+ VI.getPixels(device1, yourBuffer1, false, false); //fills pixels as a BGR (for openCV) unsigned char array - no flipping\r
+ VI.getPixels(device1, yourBuffer2, true, true); //fills pixels as a RGB (for openGL) unsigned char array - flipping!\r
+ }\r
+ \r
+ //same applies to device2 etc\r
+ \r
+ //to get a settings dialog for the device\r
+ VI.showSettingsWindow(device1);\r
+ \r
+ \r
+ //Shut down devices properly\r
+ VI.stopDevice(device1);\r
+ VI.stopDevice(device2);\r
+*/\r
+\r
+\r
+////////////////////////////////////// VARS AND DEFS //////////////////////////////////\r
+\r
+\r
+//STUFF YOU CAN CHANGE\r
+\r
+//change for verbose debug info\r
+static bool verbose = true;\r
+\r
+//if you need VI to use multi threaded com\r
+//#define VI_COM_MULTI_THREADED\r
+\r
+//STUFF YOU DON'T CHANGE\r
+\r
+//videoInput defines\r
+#define VI_VERSION 0.1995\r
+#define VI_MAX_CAMERAS 20\r
+#define VI_NUM_TYPES 18 //DON'T TOUCH\r
+#define VI_NUM_FORMATS 18 //DON'T TOUCH\r
+\r
+//defines for setPhyCon - tuner is not as well supported as composite and s-video \r
+#define VI_COMPOSITE 0\r
+#define VI_S_VIDEO 1\r
+#define VI_TUNER 2\r
+#define VI_USB 3\r
+#define VI_1394 4\r
+\r
+//defines for formats\r
+#define VI_NTSC_M 0\r
+#define VI_PAL_B 1\r
+#define VI_PAL_D 2\r
+#define VI_PAL_G 3\r
+#define VI_PAL_H 4\r
+#define VI_PAL_I 5\r
+#define VI_PAL_M 6\r
+#define VI_PAL_N 7\r
+#define VI_PAL_NC 8\r
+#define VI_SECAM_B 9\r
+#define VI_SECAM_D 10\r
+#define VI_SECAM_G 11\r
+#define VI_SECAM_H 12\r
+#define VI_SECAM_K 13\r
+#define VI_SECAM_K1 14\r
+#define VI_SECAM_L 15\r
+#define VI_NTSC_M_J 16\r
+#define VI_NTSC_433 17\r
+\r
+\r
+//allows us to directShow classes here with the includes in the cpp\r
+struct ICaptureGraphBuilder2;\r
+struct IGraphBuilder;\r
+struct IBaseFilter;\r
+struct IAMCrossbar;\r
+struct IMediaControl;\r
+struct ISampleGrabber;\r
+struct IMediaEventEx;\r
+struct IAMStreamConfig;\r
+struct _AMMediaType;\r
+class SampleGrabberCallback;\r
+typedef _AMMediaType AM_MEDIA_TYPE;\r
+\r
+//keeps track of how many instances of VI are being used\r
+//don't touch\r
+static int comInitCount = 0;\r
+\r
+\r
+//////////////////////////////////////// VIDEO DEVICE ///////////////////////////////////\r
+\r
+class videoDevice{\r
+\r
+ \r
+ public:\r
+ \r
+ videoDevice();\r
+ void setSize(int w, int h);\r
+ void NukeDownstream(IBaseFilter *pBF);\r
+ void destroyGraph();\r
+ ~videoDevice();\r
+ \r
+ int videoSize;\r
+ int width;\r
+ int height;\r
+ int tryWidth;\r
+ int tryHeight;\r
+ \r
+ ICaptureGraphBuilder2 *pCaptureGraph; // Capture graph builder object\r
+ IGraphBuilder *pGraph; // Graph builder object\r
+ IMediaControl *pControl; // Media control object\r
+ IBaseFilter *pVideoInputFilter; // Video Capture filter\r
+ IBaseFilter *pGrabberF;\r
+ IBaseFilter * pDestFilter;\r
+ IAMStreamConfig *streamConf;\r
+ ISampleGrabber * pGrabber; // Grabs frame\r
+ AM_MEDIA_TYPE * pAmMediaType;\r
+ \r
+ IMediaEventEx * pMediaEvent;\r
+ \r
+ GUID videoType;\r
+ long formatType;\r
+ \r
+ SampleGrabberCallback * sgCallback; \r
+ \r
+ bool tryDiffSize;\r
+ bool useCrossbar;\r
+ bool readyToCapture;\r
+ bool sizeSet;\r
+ bool setupStarted;\r
+ bool specificFormat;\r
+ bool autoReconnect;\r
+ int nFramesForReconnect;\r
+ unsigned long nFramesRunning;\r
+ int connection;\r
+ int storeConn;\r
+ int myID;\r
+ long requestedFrameTime; //ie fps\r
+ \r
+ char nDeviceName[255];\r
+ WCHAR wDeviceName[255];\r
+ \r
+ unsigned char * pixels;\r
+ char * pBuffer;\r
+\r
+};\r
+\r
+\r
+\r
+\r
+////////////////////////////////////// VIDEO INPUT /////////////////////////////////////\r
+\r
+\r
+\r
+class videoInput{\r
+\r
+ public:\r
+ videoInput();\r
+ ~videoInput();\r
+ \r
+ //turns off console messages - default is to print messages\r
+ static void setVerbose(bool _verbose);\r
+ \r
+ //Functions in rough order they should be used.\r
+ static int listDevices(bool silent = false);\r
+\r
+ //needs to be called after listDevices - otherwise returns NULL\r
+ static char * getDeviceName(int deviceID);\r
+ \r
+ //choose to use callback based capture - or single threaded\r
+ void setUseCallback(bool useCallback); \r
+ \r
+ //call before setupDevice\r
+ //directshow will try and get the closest possible framerate to what is requested\r
+ void setIdealFramerate(int deviceID, int idealFramerate);\r
+\r
+ //some devices will stop delivering frames after a while - this method gives you the option to try and reconnect\r
+ //to a device if videoInput detects that a device has stopped delivering frames. \r
+ //you MUST CALL isFrameNew every app loop for this to have any effect\r
+ void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect);\r
+ \r
+ //Choose one of these four to setup your device\r
+ bool setupDevice(int deviceID);\r
+ bool setupDevice(int deviceID, int w, int h);\r
+\r
+ //These two are only for capture cards\r
+ //USB and Firewire cameras souldn't specify connection \r
+ bool setupDevice(int deviceID, int connection); \r
+ bool setupDevice(int deviceID, int w, int h, int connection); \r
+ \r
+ //If you need to you can set your NTSC/PAL/SECAM\r
+ //preference here. if it is available it will be used.\r
+ //see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B\r
+ //should be called after setupDevice\r
+ //can be called multiple times\r
+ bool setFormat(int deviceNumber, int format); \r
+ \r
+ //Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true\r
+ bool isFrameNew(int deviceID); \r
+ \r
+ bool isDeviceSetup(int deviceID);\r
+ \r
+ //Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too\r
+ unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false);\r
+ \r
+ //Or pass in a buffer for getPixels to fill returns true if successful.\r
+ bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false);\r
+ \r
+ //Launches a pop up settings window\r
+ //For some reason in GLUT you have to call it twice each time. \r
+ void showSettingsWindow(int deviceID);\r
+ \r
+ //Manual control over settings thanks..... \r
+ //These are experimental for now.\r
+ bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);\r
+ bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL);\r
+ bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue);\r
+\r
+ bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);\r
+ bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL);\r
+ bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue);\r
+\r
+ //bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);\r
+\r
+ //get width, height and number of pixels\r
+ int getWidth(int deviceID);\r
+ int getHeight(int deviceID);\r
+ int getSize(int deviceID);\r
+ \r
+ //completely stops and frees a device\r
+ void stopDevice(int deviceID);\r
+ \r
+ //as above but then sets it up with same settings\r
+ bool restartDevice(int deviceID);\r
+ \r
+ //number of devices available\r
+ int devicesFound;\r
+ \r
+ long propBrightness;\r
+ long propContrast;\r
+ long propHue;\r
+ long propSaturation;\r
+ long propSharpness;\r
+ long propGamma;\r
+ long propColorEnable;\r
+ long propWhiteBalance;\r
+ long propBacklightCompensation;\r
+ long propGain;\r
+\r
+ long propPan;\r
+ long propTilt;\r
+ long propRoll;\r
+ long propZoom;\r
+ long propExposure;\r
+ long propIris;\r
+ long propFocus;\r
+ \r
+ \r
+ private: \r
+ void setPhyCon(int deviceID, int conn); \r
+ void setAttemptCaptureSize(int deviceID, int w, int h); \r
+ bool setup(int deviceID);\r
+ void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip);\r
+ int start(int deviceID, videoDevice * VD); \r
+ int getDeviceCount();\r
+ void getMediaSubtypeAsString(GUID type, char * typeAsString);\r
+ \r
+ HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName);\r
+ static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter);\r
+ HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath);\r
+ HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode);\r
+ \r
+ //don't touch\r
+ static bool comInit();\r
+ static bool comUnInit();\r
+\r
+ int connection;\r
+ int callbackSetCount;\r
+ bool bCallback;\r
+ \r
+ GUID CAPTURE_MODE;\r
+ \r
+ //Extra video subtypes\r
+ GUID MEDIASUBTYPE_Y800;\r
+ GUID MEDIASUBTYPE_Y8;\r
+ GUID MEDIASUBTYPE_GREY;\r
+\r
+ videoDevice * VDList[VI_MAX_CAMERAS];\r
+ GUID mediaSubtypes[VI_NUM_TYPES];\r
+ long formatTypes[VI_NUM_FORMATS];\r
+\r
+ static void __cdecl basicThread(void * objPtr);\r
+\r
+ static char deviceNames[VI_MAX_CAMERAS][255];\r
+\r
+}; \r
+ \r
+ #endif\r