diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cd108f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +!*.lib \ No newline at end of file diff --git a/CameraFinder.sln b/CameraFinder.sln new file mode 100644 index 0000000..42d1575 --- /dev/null +++ b/CameraFinder.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33122.133 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CameraFinder", "CameraFinder\CameraFinder.vcxproj", "{700D42A1-6E71-4662-8AC8-6EFDFACB841B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Debug|x64.ActiveCfg = Debug|x64 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Debug|x64.Build.0 = Debug|x64 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Debug|x86.ActiveCfg = Debug|Win32 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Debug|x86.Build.0 = Debug|Win32 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Release|x64.ActiveCfg = Release|x64 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Release|x64.Build.0 = Release|x64 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Release|x86.ActiveCfg = Release|Win32 + {700D42A1-6E71-4662-8AC8-6EFDFACB841B}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CCF97F09-85F8-4056-8EFD-68CBDB827C21} + EndGlobalSection +EndGlobal diff --git a/CameraFinder/CameraFinder.vcxproj b/CameraFinder/CameraFinder.vcxproj new file mode 100644 index 0000000..15d64c4 --- /dev/null +++ b/CameraFinder/CameraFinder.vcxproj @@ -0,0 +1,140 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {700d42a1-6e71-4662-8ac8-6efdfacb841b} + CameraFinder + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/CameraFinder/CameraFinder.vcxproj.filters b/CameraFinder/CameraFinder.vcxproj.filters new file mode 100644 index 0000000..cd6d584 --- /dev/null +++ b/CameraFinder/CameraFinder.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + ソース ファイル + + + + + ヘッダー ファイル + + + \ No newline at end of file diff --git a/CameraFinder/main.cpp b/CameraFinder/main.cpp new file mode 100644 index 0000000..f1b031b --- /dev/null +++ b/CameraFinder/main.cpp @@ -0,0 +1,64 @@ +#include +#include +#include "videoInput.h" + +#ifdef _DEBUG +#pragma comment(lib, "videoInputD.lib") +#else +#pragma comment(lib, "videoInput.lib") +#endif + +// ���C���֐� +int main(int argc, char* argv[]) { + videoInput::setVerbose(false); + videoInput vi; + auto devList = vi.getDeviceList(); + + // �������w�肳��Ȃ��ꍇ�� + // �v���O�������� + // ���ׂẴJ��������W���o�͂ɗ񋓂��� + if (argc == 1) { + std::cout << std::endl; + std::cout << "------------------------------------" << std::endl; + std::cout << "Camera Finder ver 1.0 by T.Nakaguchi" << std::endl; + std::cout << "------------------------------------" << std::endl << std::endl; + std::cout << "Usage: CameraFinder.exe" << std::endl; + std::cout << "�v���O�������̕\���ƑS�J�����ꗗ�̕\��" << std::endl << std::endl; + std::cout << "Usage: CameraFinder.exe str" << std::endl; + std::cout << "������str�ŃJ���������������C�q�b�g�����J�����ԍ���\��" << std::endl; + std::cout << "�J�����ԍ��̓v���O�����̏I���R�[�h�ɂ��o��" << std::endl << std::endl; + std::cout << "Usage: CameraFinder.exe id" << std::endl; + std::cout << "id�ԍ��i����1���j�̃J�������̕\��" << std::endl << std::endl; + + std::cout << "id name" << std::endl; + for (int i = 0; i < devList.size(); i++) { + std::cout << "[" << i << "] " << devList[i] << std::endl; + } + return 0; + } + + // �����Ɉꌅ�̐������^����ꂽ�ꍇ�́C���̃J����ID�ɑ�������f�o�C�X����W���o�͂ɕ\������ + if (strlen(argv[1]) == 1 && *argv[1] >= '0' && *argv[1] <= '9') { + int id = *argv[1] - '0'; + if (id < devList.size()) { + std::cout << vi.getDeviceName(id) << std::endl; + return 0; + } + else { + std::cout << "wrong id" << std::endl; + return -1; + } + } + + // ������Ńf�o�C�X�������� + for (int i = 0; i < devList.size(); i++) { + if (devList[i].find(argv[1]) != std::string::npos) { + std::cout << i << std::endl; + return i; + } + } + + // ����������̃f�o�C�X�����‚���Ȃ��� + std::cout << -1 << std::endl; + return -1; +} diff --git a/CameraFinder/videoInput.h b/CameraFinder/videoInput.h new file mode 100644 index 0000000..9d14598 --- /dev/null +++ b/CameraFinder/videoInput.h @@ -0,0 +1,416 @@ +#ifndef _VIDEOINPUT +#define _VIDEOINPUT + +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. + +////////////////////////////////////////////////////////// +//Written by Theodore Watson - theo.watson@gmail.com // +//Do whatever you want with this code but if you find // +//a bug or make an improvement I would love to know! // +// // +//Warning This code is experimental // +//use at your own risk :) // +////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +/* Shoutouts + +Thanks to: + + Dillip Kumar Kara for crossbar code. + Zachary Lieberman for getting me into this stuff + and for being so generous with time and code. + The guys at Potion Design for helping me with VC++ + Josh Fisher for being a serious C++ nerd :) + Golan Levin for helping me debug the strangest + and slowest bug in the world! + + And all the people using this library who send in + bugs, suggestions and improvements who keep me working on + the next version - yeah thanks a lot ;) + +*/ +///////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma comment(lib,"Strmiids.lib") +#endif + +#include +#include +#include +#include +#include +#include +#include + +//this is for TryEnterCriticalSection +#ifndef _WIN32_WINNT + # define _WIN32_WINNT 0x501 +#endif +#include + + +//Example Usage +/* + //create a videoInput object + videoInput VI; + + //Prints out a list of available devices and returns num of devices found + int numDevices = VI.listDevices(); + + int device1 = 0; //this could be any deviceID that shows up in listDevices + int device2 = 1; //this could be any deviceID that shows up in listDevices + + //if you want to capture at a different frame rate (default is 30) + //specify it here, you are not guaranteed to get this fps though. + //VI.setIdealFramerate(dev, 60); + + //setup the first device - there are a number of options: + + VI.setupDevice(device1); //setup the first device with the default settings + //VI.setupDevice(device1, VI_COMPOSITE); //or setup device with specific connection type + //VI.setupDevice(device1, 320, 240); //or setup device with specified video size + //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type + + //VI.setFormat(device1, VI_NTSC_M); //if your card doesn't remember what format it should be + //call this with the appropriate format listed above + //NOTE: must be called after setupDevice! + + //optionally setup a second (or third, fourth ...) device - same options as above + VI.setupDevice(device2); + + //As requested width and height can not always be accomodated + //make sure to check the size once the device is setup + + int width = VI.getWidth(device1); + int height = VI.getHeight(device1); + int size = VI.getSize(device1); + + unsigned char * yourBuffer1 = new unsigned char[size]; + unsigned char * yourBuffer2 = new unsigned char[size]; + + //to get the data from the device first check if the data is new + if(VI.isFrameNew(device1)){ + VI.getPixels(device1, yourBuffer1, false, false); //fills pixels as a BGR (for openCV) unsigned char array - no flipping + VI.getPixels(device1, yourBuffer2, true, true); //fills pixels as a RGB (for openGL) unsigned char array - flipping! + } + + //same applies to device2 etc + + //to get a settings dialog for the device + VI.showSettingsWindow(device1); + + + //Shut down devices properly + VI.stopDevice(device1); + VI.stopDevice(device2); +*/ + + +////////////////////////////////////// VARS AND DEFS ////////////////////////////////// + + +//STUFF YOU DON'T CHANGE + +//videoInput defines +#define VI_VERSION 0.200 +#define VI_MAX_CAMERAS 20 +#define VI_NUM_TYPES 20 //DON'T TOUCH +#define VI_NUM_FORMATS 18 //DON'T TOUCH + +//defines for setPhyCon - tuner is not as well supported as composite and s-video +#define VI_COMPOSITE 0 +#define VI_S_VIDEO 1 +#define VI_TUNER 2 +#define VI_USB 3 +#define VI_1394 4 + +//defines for formats +#define VI_NTSC_M 0 +#define VI_PAL_B 1 +#define VI_PAL_D 2 +#define VI_PAL_G 3 +#define VI_PAL_H 4 +#define VI_PAL_I 5 +#define VI_PAL_M 6 +#define VI_PAL_N 7 +#define VI_PAL_NC 8 +#define VI_SECAM_B 9 +#define VI_SECAM_D 10 +#define VI_SECAM_G 11 +#define VI_SECAM_H 12 +#define VI_SECAM_K 13 +#define VI_SECAM_K1 14 +#define VI_SECAM_L 15 +#define VI_NTSC_M_J 16 +#define VI_NTSC_433 17 + +// added by gameover +#define VI_MEDIASUBTYPE_RGB24 0 +#define VI_MEDIASUBTYPE_RGB32 1 +#define VI_MEDIASUBTYPE_RGB555 2 +#define VI_MEDIASUBTYPE_RGB565 3 +#define VI_MEDIASUBTYPE_YUY2 4 +#define VI_MEDIASUBTYPE_YVYU 5 +#define VI_MEDIASUBTYPE_YUYV 6 +#define VI_MEDIASUBTYPE_IYUV 7 +#define VI_MEDIASUBTYPE_UYVY 8 +#define VI_MEDIASUBTYPE_YV12 9 +#define VI_MEDIASUBTYPE_YVU9 10 +#define VI_MEDIASUBTYPE_Y411 11 +#define VI_MEDIASUBTYPE_Y41P 12 +#define VI_MEDIASUBTYPE_Y211 13 +#define VI_MEDIASUBTYPE_AYUV 14 +#define VI_MEDIASUBTYPE_Y800 15 +#define VI_MEDIASUBTYPE_Y8 16 +#define VI_MEDIASUBTYPE_GREY 17 +#define VI_MEDIASUBTYPE_MJPG 18 +#define VI_MEDIASUBTYPE_H264 19 + +//allows us to directShow classes here with the includes in the cpp +struct ICaptureGraphBuilder2; +struct IGraphBuilder; +struct IBaseFilter; +struct IAMCrossbar; +struct IMediaControl; +struct ISampleGrabber; +struct IMediaEventEx; +struct IAMStreamConfig; +struct _AMMediaType; +class SampleGrabberCallback; +typedef _AMMediaType AM_MEDIA_TYPE; + + + + +//////////////////////////////////////// VIDEO DEVICE /////////////////////////////////// + +class videoDevice{ + + + public: + + videoDevice(); + void setSize(int w, int h); + void NukeDownstream(IBaseFilter *pBF); + void destroyGraph(); + ~videoDevice(); + + int videoSize; + int width; + int height; + int tryWidth; + int tryHeight; + + ICaptureGraphBuilder2 *pCaptureGraph; // Capture graph builder object + IGraphBuilder *pGraph; // Graph builder object + IMediaControl *pControl; // Media control object + IBaseFilter *pVideoInputFilter; // Video Capture filter + IBaseFilter *pGrabberF; + IBaseFilter * pDestFilter; + IAMStreamConfig *streamConf; + ISampleGrabber * pGrabber; // Grabs frame + AM_MEDIA_TYPE * pAmMediaType; + + IMediaEventEx * pMediaEvent; + + GUID videoType; + long formatType; + + SampleGrabberCallback * sgCallback; + + bool tryDiffSize; + bool useCrossbar; + bool readyToCapture; + bool sizeSet; + bool setupStarted; + bool specificFormat; + bool autoReconnect; + int nFramesForReconnect; + unsigned long nFramesRunning; + int connection; + int storeConn; + int myID; + long requestedFrameTime; //ie fps + + char nDeviceName[255]; + WCHAR wDeviceName[255]; + + unsigned char * pixels; + char * pBuffer; + +}; + + + + +////////////////////////////////////// VIDEO INPUT ///////////////////////////////////// + + + +class videoInput{ + + public: + videoInput(); + ~videoInput(); + + //turns off console messages - default is to print messages + static void setVerbose(bool _verbose); + + //this allows for multithreaded use of VI ( default is single threaded ). + //call this before any videoInput calls. + //note if your app has other COM calls then you should set VIs COM usage to match the other COM mode + static void setComMultiThreaded(bool bMulti); + + //Functions in rough order they should be used. + static int listDevices(bool silent = false); + static std::vector getDeviceList(); + + //needs to be called after listDevices - otherwise returns NULL + static const char * getDeviceName(int deviceID); + static int getDeviceIDFromName(const char * name); + + //needs to be called after listDevices - otherwise returns empty string + static const std::wstring& getUniqueDeviceName(int deviceID); + static int getDeviceIDFromUniqueName(const std::wstring& uniqueName); + + //choose to use callback based capture - or single threaded + void setUseCallback(bool useCallback); + + //call before setupDevice + //directshow will try and get the closest possible framerate to what is requested + void setIdealFramerate(int deviceID, int idealFramerate); + + //some devices will stop delivering frames after a while - this method gives you the option to try and reconnect + //to a device if videoInput detects that a device has stopped delivering frames. + //you MUST CALL isFrameNew every app loop for this to have any effect + void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect); + + //Choose one of these four to setup your device + bool setupDevice(int deviceID); + bool setupDevice(int deviceID, int w, int h); + + //These two are only for capture cards + //USB and Firewire cameras souldn't specify connection + bool setupDevice(int deviceID, int connection); + bool setupDevice(int deviceID, int w, int h, int connection); + + //If you need to you can set your NTSC/PAL/SECAM + //preference here. if it is available it will be used. + //see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B + //should be called after setupDevice + //can be called multiple times + bool setFormat(int deviceNumber, int format); + void setRequestedMediaSubType(int mediatype); // added by gameover + + //Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true + bool isFrameNew(int deviceID); + + bool isDeviceSetup(int deviceID); + + //Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too + unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false); + + //Or pass in a buffer for getPixels to fill returns true if successful. + bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false); + + //Launches a pop up settings window + //For some reason in GLUT you have to call it twice each time. + void showSettingsWindow(int deviceID); + + //Manual control over settings thanks..... + //These are experimental for now. + bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = 0, bool useDefaultValue = false); + bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = 0); + bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); + + bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = 0, bool useDefaultValue = false); + bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = 0); + bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); + + //bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = 0, bool useDefaultValue = false); + + //get width, height and number of pixels + int getWidth(int deviceID); + int getHeight(int deviceID); + int getSize(int deviceID); + + //completely stops and frees a device + void stopDevice(int deviceID); + + //as above but then sets it up with same settings + bool restartDevice(int deviceID); + + //number of devices available + int devicesFound; + + long propBrightness; + long propContrast; + long propHue; + long propSaturation; + long propSharpness; + long propGamma; + long propColorEnable; + long propWhiteBalance; + long propBacklightCompensation; + long propGain; + + long propPan; + long propTilt; + long propRoll; + long propZoom; + long propExposure; + long propIris; + long propFocus; + + private: + + void setPhyCon(int deviceID, int conn); + void setAttemptCaptureSize(int deviceID, int w, int h); + bool setup(int deviceID); + void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip); + int start(int deviceID, videoDevice * VD); + int getDeviceCount(); + void getMediaSubtypeAsString(GUID type, char * typeAsString); + + HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName); + static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter); + HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath); + HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode); + + //don't touch + static bool comInit(); + static bool comUnInit(); + + int connection; + int callbackSetCount; + bool bCallback; + + GUID CAPTURE_MODE; + GUID requestedMediaSubType; + + //Extra video subtypes + GUID MEDIASUBTYPE_Y800; + GUID MEDIASUBTYPE_Y8; + GUID MEDIASUBTYPE_GREY; + GUID MEDIASUBTYPE_H264; + + videoDevice * VDList[VI_MAX_CAMERAS]; + GUID mediaSubtypes[VI_NUM_TYPES]; + long formatTypes[VI_NUM_FORMATS]; + + static void __cdecl basicThread(void * objPtr); + + static char deviceNames[VI_MAX_CAMERAS][255]; + + static std::vector deviceUniqueNames; + +}; + + #endif diff --git a/CameraFinder/videoInput.lib b/CameraFinder/videoInput.lib new file mode 100644 index 0000000..991bf25 --- /dev/null +++ b/CameraFinder/videoInput.lib Binary files differ diff --git a/CameraFinder/videoInputD.lib b/CameraFinder/videoInputD.lib new file mode 100644 index 0000000..5ffecf6 --- /dev/null +++ b/CameraFinder/videoInputD.lib Binary files differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..d8e6c55 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +Camera Finder +=============== +USBカメラの情報取得と検索 + +#### 実行環境 +- CameraFinder.exe 実行 + +#### ソフトウェアの使用方法 +- Usage: CameraFinder.exe +プログラム情報の表示と全カメラ一覧の表示 + +- Usage: CameraFinder.exe str +文字列strでカメラ名を検索し,ヒットしたカメラ番号を表示 +カメラ番号はプログラムの終了コードにも出力 + +- Usage: CameraFinder.exe id +id番号(数字1桁)のカメラ名の表示 + +#### 開発環境 +- Visual C++ 2022 +- Windows 11