Subversion Repositories Projects

Rev

Blame | Last modification | View Log | RSS feed

//*****************************************************************************************
//  File:       WebCamLib.h
//  Project:    WebcamLib
//  Author(s):  John Conwell
//              Gary Caldwell
//
//  Declares the webcam DirectShow wrapper used by TouchlessLib
//*****************************************************************************************

#pragma once

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;

namespace WebCamLib
{
        /// <summary>
        /// Store webcam name, index
        /// </summary>
        public ref class CameraInfo
        {
        public:
                CameraInfo( int index, String^ name );

                property int Index
                {
                        int get();
                private: void set( int value );
                }

                property String^ Name
                {
                        String^ get();
                private: void set( String^ value );
                }

        private:
                int index;
                String^ name;
        };

        public enum class PropertyTypeMask : int
        {
                CameraControlPropertyMask = 0x01000,
                VideoProcAmpPropertyMask = 0x02000,
        };

        // Source: https://msdn.microsoft.com/en-us/library/aa925325.aspx
        public enum class CameraControlProperty : int
        {
                Pan_degrees,
                Tilt_degrees,
                Roll_degrees,
                Zoom_mm,
                Exposure_lgSec,
                Iris_10f,
                FocalLength_mm,
                Flash,
        };

        // Source: https://msdn.microsoft.com/en-us/library/aa920611.aspx
        public enum class VideoProcAmpProperty : int
        {
                Brightness,
                Contrast,
                Hue,
                Saturation,
                Sharpness,
                Gamma,
                ColorEnable,
                WhiteBalance,
                BacklightCompensation,
                Gain,
        };

        public enum class CameraProperty : int
        {
                Pan_degrees = WebCamLib::CameraControlProperty::Pan_degrees | PropertyTypeMask::CameraControlPropertyMask,
                Tilt_degrees = WebCamLib::CameraControlProperty::Tilt_degrees | PropertyTypeMask::CameraControlPropertyMask,
                Roll_degrees = WebCamLib::CameraControlProperty::Roll_degrees | PropertyTypeMask::CameraControlPropertyMask,
                Zoom_mm = WebCamLib::CameraControlProperty::Zoom_mm | PropertyTypeMask::CameraControlPropertyMask,
                Exposure_lgSec = WebCamLib::CameraControlProperty::Exposure_lgSec | PropertyTypeMask::CameraControlPropertyMask,
                Iris_10f = WebCamLib::CameraControlProperty::Iris_10f | PropertyTypeMask::CameraControlPropertyMask,
                FocalLength_mm = WebCamLib::CameraControlProperty::FocalLength_mm | PropertyTypeMask::CameraControlPropertyMask,
                Flash = WebCamLib::CameraControlProperty::Flash | PropertyTypeMask::CameraControlPropertyMask,
                Brightness = WebCamLib::VideoProcAmpProperty::Brightness | PropertyTypeMask::VideoProcAmpPropertyMask,
                Contrast = WebCamLib::VideoProcAmpProperty::Contrast | PropertyTypeMask::VideoProcAmpPropertyMask,
                Hue = WebCamLib::VideoProcAmpProperty::Hue | PropertyTypeMask::VideoProcAmpPropertyMask,
                Saturation = WebCamLib::VideoProcAmpProperty::Saturation | PropertyTypeMask::VideoProcAmpPropertyMask,
                Sharpness = WebCamLib::VideoProcAmpProperty::Sharpness | PropertyTypeMask::VideoProcAmpPropertyMask,
                Gamma = WebCamLib::VideoProcAmpProperty::Gamma | PropertyTypeMask::VideoProcAmpPropertyMask,
                ColorEnable = WebCamLib::VideoProcAmpProperty::ColorEnable | PropertyTypeMask::VideoProcAmpPropertyMask,
                WhiteBalance = WebCamLib::VideoProcAmpProperty::WhiteBalance | PropertyTypeMask::VideoProcAmpPropertyMask,
                BacklightCompensation = WebCamLib::VideoProcAmpProperty::BacklightCompensation | PropertyTypeMask::VideoProcAmpPropertyMask,
                Gain = WebCamLib::VideoProcAmpProperty::Gain | PropertyTypeMask::VideoProcAmpPropertyMask,
        };

        public ref class CameraPropertyCapabilities
        {
        public:
                CameraPropertyCapabilities( int cameraIndex, CameraProperty prop, bool isGetSupported, bool isSetSupported, bool isGetRangeSupported );

                property int CameraIndex
                {
                        int get();
                private: void set( int cameraIndex );
                }

                property CameraProperty Property
                {
                        CameraProperty get();
                private: void set( CameraProperty value );
                }

                property bool IsGetSupported
                {
                        bool get();
                private: void set( bool value );
                }

                property bool IsSetSupported
                {
                        bool get();
                private: void set( bool value );
                }

                property bool IsGetRangeSupported
                {
                        bool get();
                private: void set( bool value );
                }

                property bool IsSupported
                {
                        bool get();
                }

                property bool IsFullySupported
                {
                        bool get();
                }

        private:
                int cameraIndex;
                CameraProperty prop;
                bool isGetSupported, isSetSupported, isGetRangeSupported;
        };

        /// <summary>
        /// DirectShow wrapper around a web cam, used for image capture
        /// </summary>
        public ref class CameraMethods
        {
        public:
                /// <summary>
                /// Initializes information about all web cams connected to machine
                /// </summary>
                CameraMethods();

                /// <summary>
                /// Delegate used by DirectShow to pass back captured images from webcam
                /// </summary>
                delegate void CaptureCallbackDelegate(
                        int dwSize,
                        [MarshalAsAttribute(UnmanagedType::LPArray, ArraySubType = UnmanagedType::I1, SizeParamIndex = 0)] array<System::Byte>^ abData);

                /// <summary>
                /// Event callback to capture images from webcam
                /// </summary>
                event CaptureCallbackDelegate^ OnImageCapture;

                /// <summary>
                /// Retrieve information about a specific camera
                /// Use the count property to determine valid indicies to pass in
                /// </summary>
                CameraInfo^ GetCameraInfo(int camIndex);

                /// <summary>
                /// Start the camera associated with the input handle
                /// </summary>
                bool StartCamera(int camIndex, interior_ptr<int> width, interior_ptr<int> height, interior_ptr<int> bpp);

                /// <summary>
                /// Start the camera associated with the input handle
                /// </summary>
                void StartCamera(int camIndex, interior_ptr<int> width, interior_ptr<int> height, interior_ptr<int> bpp, interior_ptr<bool> successful);

                #pragma region Camera Property Support
                void IsPropertySupported( CameraProperty prop, interior_ptr<bool> result );

                bool IsPropertySupported( CameraProperty prop );

                void GetProperty( CameraProperty prop, bool isValue, interior_ptr<long> value, interior_ptr<bool> bAuto, interior_ptr<bool> successful );

                bool GetProperty( CameraProperty prop, bool isValue, interior_ptr<long> value, interior_ptr<bool> bAuto );

                void GetProperty_value( CameraProperty prop, interior_ptr<long> value, interior_ptr<bool> bAuto, interior_ptr<bool> successful );

                bool GetProperty_value( CameraProperty prop, interior_ptr<long> value, interior_ptr<bool> bAuto );

                void GetProperty_percentage( CameraProperty prop, interior_ptr<long> percentage, interior_ptr<bool> bAuto, interior_ptr<bool> successful);

                bool GetProperty_percentage( CameraProperty prop, interior_ptr<long> percentage, interior_ptr<bool> bAuto );

                void SetProperty( CameraProperty prop, bool isValue, long value, bool bAuto, interior_ptr<bool> successful );

                bool SetProperty( CameraProperty prop, bool isValue, long value, bool bAuto );

                void SetProperty_value( CameraProperty prop, long value, bool bAuto, interior_ptr<bool> successful );

                bool SetProperty_value( CameraProperty prop, long value, bool bAuto );

                void SetProperty_value( CameraProperty prop, long value, bool bAuto, bool throwValidationError, interior_ptr<bool> successful );

                bool SetProperty_value( CameraProperty prop, long value, bool bAuto, bool throwValidationError );

                void SetProperty_percentage( CameraProperty prop, long percentage, bool bAuto, interior_ptr<bool> successful );

                bool SetProperty_percentage( CameraProperty prop, long percentage, bool bAuto );

                void PropertyHasRange( CameraProperty prop, interior_ptr<bool> successful );

                bool PropertyHasRange( CameraProperty prop );

                void GetPropertyRange( CameraProperty prop, interior_ptr<long> min, interior_ptr<long> max, interior_ptr<long> steppingDelta, interior_ptr<long> defaults, interior_ptr<bool> bAuto, interior_ptr<bool> successful );

                bool GetPropertyRange( CameraProperty prop, interior_ptr<long> min, interior_ptr<long> max, interior_ptr<long> steppingDelta, interior_ptr<long> defaults, interior_ptr<bool> bAuto );

                void ValidatePropertyValue( CameraProperty prop, long value, interior_ptr<bool> successful );

                bool ValidatePropertyValue( CameraProperty prop, long value );

                CameraPropertyCapabilities^ GetPropertyCapability( CameraProperty prop );

                property IDictionary<CameraProperty, CameraPropertyCapabilities^> ^ PropertyCapabilities
                {
                        IDictionary<CameraProperty, CameraPropertyCapabilities^> ^ get();
                }
                #pragma endregion

                void GetCaptureSizes(int index, IList<Tuple<int,int,int>^> ^ sizes);

                property IList<Tuple<int,int,int>^> ^ CaptureSizes
                {
                        IList<Tuple<int,int,int>^> ^ get();
                }

                /// <summary>
                /// Stops the currently running camera and cleans up any global resources
                /// </summary>
                void Cleanup();

                /// <summary>
                /// Stops the currently running camera
                /// </summary>
                void StopCamera();

                /// <summary>
                /// Show the properties dialog for the specified webcam
                /// </summary>
                void DisplayCameraPropertiesDialog(int camIndex);

                /// <summary>
                /// Count of the number of cameras installed
                /// </summary>
                property int Count;

                /// <summary>
                /// Queries which camera is currently running via StartCamera(), -1 for none
                /// </summary>
                property int ActiveCameraIndex
                {
                        int get()
                        {
                                return activeCameraIndex;
                        }
                }

                /// <summary>
                /// IDisposable
                /// </summary>
                ~CameraMethods();

        protected:
                /// <summary>
                /// Finalizer
                /// </summary>
                !CameraMethods();

                #pragma region Camera Property Support
                bool IsCameraControlProperty( CameraProperty prop );

                bool IsVideoProcAmpProperty( CameraProperty prop );

                bool IsPropertyMaskEqual( CameraProperty prop, PropertyTypeMask mask );

                WebCamLib::CameraControlProperty GetCameraControlProperty( CameraProperty prop );

                WebCamLib::VideoProcAmpProperty GetVideoProcAmpProperty( CameraProperty prop );

                bool IsPropertySupported( WebCamLib::CameraControlProperty prop );

                bool IsPropertySupported( WebCamLib::VideoProcAmpProperty prop );

                bool GetPropertyRange( WebCamLib::CameraControlProperty prop, interior_ptr<long> min, interior_ptr<long> max, interior_ptr<long> steppingDelta, interior_ptr<long> defaults, interior_ptr<bool> bAuto );

                bool GetPropertyRange( WebCamLib::VideoProcAmpProperty prop, interior_ptr<long> min, interior_ptr<long> max, interior_ptr<long> steppingDelta, interior_ptr<long> defaults, interior_ptr<bool> bAuto );

                bool GetProperty_value( WebCamLib::CameraControlProperty prop, interior_ptr<long> value, interior_ptr<bool> bAuto );

                bool GetProperty_value( WebCamLib::VideoProcAmpProperty prop, interior_ptr<long> value, interior_ptr<bool> bAuto );

                bool SetProperty_value( WebCamLib::CameraControlProperty prop, long value, bool bAuto );

                bool SetProperty_value( WebCamLib::VideoProcAmpProperty prop, long value, bool bAuto );
                #pragma endregion

        private:
                /// <summary>
                /// Pinned pointer to delegate for CaptureCallbackDelegate
                /// Keeps the delegate instance in one spot
                /// </summary>
                GCHandle ppCaptureCallback;

                /// <summary>
                /// Initialize information about webcams installed on machine
                /// </summary>
                void RefreshCameraList();

                /// <summary>
                /// Has dispose already happened?
                /// </summary>
                bool disposed;

                /// <summary>
                /// Which camera is running? -1 for none
                /// </summary>
                int activeCameraIndex;

                /// <summary>
                /// Releases all unmanaged resources
                /// </summary>
                void CleanupCameraInfo();

                /// <summary>
                /// Setup the callback functionality for DirectShow
                /// </summary>
                HRESULT ConfigureSampleGrabber(IBaseFilter *pIBaseFilter);

                HRESULT SetCaptureFormat(IBaseFilter* pCap, int width, int height, int bpp );
        };

        // Forward declarations of callbacks
        typedef void (__stdcall *PFN_CaptureCallback)(DWORD dwSize, BYTE* pbData);
        PFN_CaptureCallback g_pfnCaptureCallback = NULL;

        /// <summary>
        /// Lightweight SampleGrabber callback interface
        /// </summary>
        class SampleGrabberCB : public ISampleGrabberCB
        {
        public:
                SampleGrabberCB()
                {
                        m_nRefCount = 0;
                }

                virtual HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime, IMediaSample *pSample)
                {
                        return E_FAIL;
                }

                virtual HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen)
                {
                        if (g_pfnCaptureCallback != NULL)
                        {
                                g_pfnCaptureCallback(BufferLen, pBuffer);
                        }

                        return S_OK;
                }

                virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
                {
                        return E_FAIL;  // Not a very accurate implementation
                }

                virtual ULONG STDMETHODCALLTYPE AddRef()
                {
                        return ++m_nRefCount;
                }

                virtual ULONG STDMETHODCALLTYPE Release()
                {
                        int n = --m_nRefCount;
                        if (n <= 0)
                        {
                                delete this;
                        }
                        return n;
                }

        private:
                int m_nRefCount;
        };
}