Blame |
Last modification |
View Log
| RSS feed
/* ========================================================================
* PROJECT: DirectShow Video Processing Library (DSVL)
* Version: 0.0.8 (05/13/2005)
* ========================================================================
* Author: Thomas Pintaric, Vienna University of Technology
* Contact: pintaric@ims.tuwien.ac.at http://ims.tuwien.ac.at/~thomas
* =======================================================================
*
* Copyright (C) 2005 Vienna University of Technology
*
* This library 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.
*
* For further information please contact Thomas Pintaric under
* <pintaric@ims.tuwien.ac.at> or write to Thomas Pintaric,
* Vienna University of Technology, Favoritenstr. 9-11/E188/2, A-1040
* Vienna, Austria.
* ========================================================================*/
#include <streams.h>
#include <atlcomcli.h> // CComPtr
#include <comutil.h> // _bstr_t
#include "Qedit.h"
#include <map>
using namespace std;
#include "DSVL_PixelFormat.h"
const PIXELFORMAT default_PIXELFORMAT = PIXELFORMAT_RGB32;
#include "tinyxml.h"
// -----------------------------------------------------------------------------------------------------------------
#define WM_GRAPHNOTIFY WM_APP + 1
#define CLASSNAME "EventNotify"
// -----------------------------------------------------------------------------------------------------------------
typedef enum _VIDEO_INPUT_DEVICE
{
WDM_VIDEO_CAPTURE_FILTER = 0, // select video source from among WDM Streaming Capture Device filters in
// class CLSID_VideoInputDeviceCategory.
ASYNC_FILE_INPUT_FILTER = 1, // read video from an AVI file (through an asynchronous file input filter)
INVALID_INPUT_FILTER = 2 // do not use
} VIDEO_INPUT_DEVICE;
static const char *VIDEO_INPUT_DEVICE_names[]=
{
"WDM_CAP",
"AVI_FILE",
"invalid" // do not use
};
const VIDEO_INPUT_DEVICE default_VIDEO_INPUT_DEVICE = WDM_VIDEO_CAPTURE_FILTER;
// -----------------------------------------------------------------------------------------------------------------
typedef enum _VIDEO_INPUT_FLAGS // can be combined, i.e. (WDM_SHOW_DIALOG|WDM_MATCH_FILTER_NAME)
{
WDM_MATCH_FORMAT = 0x0001, // first media type matching the a given set of format requirements
WDM_SHOW_FORMAT_DIALOG = 0x0002, // displays either the capture pin's property pages (non-DV cameras) or
// the DV-decoder filter's format dialog before connecting anything
WDM_SHOW_CONTROL_DIALOG = 0x0004, // displays the source filter's property pages before connecting anything
WDM_MATCH_FILTER_NAME = 0x0008, // tries find a match based on a filter name substring, i.e. "QuickCam" or "Sony"
WDM_MATCH_IEEE1394_ID = 0x0010, // match filter based on a unique 64-bit IEEE 1394 device ID (MSDV driver only)
// this technique allows to explicitly choose between different cameras connected
// to the same IEEE 1394 bus. Setting this flag usually requires use of the WDM
// MSDV driver(qdv.dll)
// >> use "/bin/IEEE1394_id.exe" to determine your camera's ID.
WDM_USE_MAX_FRAMERATE = 0x0020 // uses the max. available frame rate for the format requested
} VIDEO_INPUT_FLAGS;
// Media type matching is based on the AM_MEDIA_TYPE structures obtained from
// each WDM Video Capture Filter.
//
// AM_MEDIA_TYPE.majortype (MUST BE MEDIATYPE_Video)
// AM_MEDIA_TYPE.subtype
// AM_MEDIA_TYPE.formattype (MUST BE FORMAT_VideoInfo)
// VIDEOINFOHEADER.AvgTimePerFrame
// VIDEOINFOHEADER.BITMAPINFOHEADER.biWidth
// VIDEOINFOHEADER.BITMAPINFOHEADER.biHeight
const VIDEO_INPUT_FLAGS default_VIDEO_INPUT_FLAGS = WDM_SHOW_FORMAT_DIALOG;
// -----------------------------------------------------------------------------------------------------------------
typedef enum _ASYNC_INPUT_FLAGS
{
ASYNC_INPUT_DO_NOT_USE_CLOCK = 0x0100, // call IMediaFilter::SetSyncSource(NULL) on async file source filter
// this will effectively prevent samples from being dropped, but
// may result in 100% CPU usage on single-processor systems
ASYNC_LOOP_VIDEO = 0x0200, // continuously loops through an input file
ASYNC_RENDER_SECONDARY_STREAMS = 0x0400 // The Async File Source Filter is always used in combination with an
// AVI Splitter Filter (CLSID_AviSplitter), where Stream 0 is assumed
// to contain video data (MEDIATYPE_Video). This flag instructs DSVL_GraphManager
// to call IGraphBuilder->Render(IPin*) on Streams 1..n
// Set this flag if your AVI file contains an audio stream AND you want it
// rendered by DirectSound (usually through CLSID_DSoundRender).
// DO NOT SET this flag if your AVI file contains more than one video stream
// not yet implemented:
// ASYNC_SHOW_DECODER_DIALOG = 0x0800, // displays either the video decoder's property pages
} ASYNC_INPUT_FLAGS;
const DWORD default_ASYNC_INPUT_FLAGS = 0;
// -----------------------------------------------------------------------------------------------------------------
typedef enum _CP_INTERFACE
{
CP_CameraControl = 0, // IAMCameraControl
CP_VideoProcAmp = 1 // IAMVideoProcAmp
} CP_INTERFACE;
typedef void (*PTR_UserCallback)(IMediaSample*);
typedef void (*PTR_SimpleUserCallback)(BYTE*,int,int,PIXELFORMAT,REFERENCE_TIME);
// -----------------------------------------------------------------------------------------------------------------
typedef struct _DS_MEDIA_FORMAT
{
VIDEO_INPUT_DEVICE inputDevice;
LONG biWidth;
LONG biHeight;
double frameRate;
GUID subtype;
bool isInterlaced;
LPWSTR sourceFilterName; // (inputDevice == WDM_VIDEO_CAPTURE_FILTER): WDM capture filter's friendly/device name
// (inputDevice == ASYNC_FILE_INPUT_FILTER): input file name
bool isDeviceName; // false: friendly name, true: device name
DWORD inputFlags; // (inputDevice == WDM_VIDEO_CAPTURE_FILTER): combination of ASYNC_INPUT_FLAGS
// (inputDevice == ASYNC_FILE_INPUT_FILTER): combination of VIDEO_INPUT_FLAGS
// NOTE: don't forget to set (defaultInputFlags = false) if you use custom flags!
bool defaultInputFlags;
PIXELFORMAT pixel_format; // default: PIXELFORMAT_RGB32
char* ieee1394_id; // unique 64-bit camera identifier (IEEE 1394 devices only)
// will be ignored/set to zero for non-IEEE 1394 cameras
bool flipH; // applies to PIXELFORMAT_RGB32 only
bool flipV; // applies to PIXELFORMAT_RGB32 only
} DS_MEDIA_FORMAT;
DS_MEDIA_FORMAT default_DS_MEDIA_FORMAT();
// -----------------------------------------------------------------------------------------------------------------
#ifndef __MEMORY_BUFFER_HANDLE__
#define __MEMORY_BUFFER_HANDLE__
#define MIN_ALLOCATOR_BUFFERS_PER_CLIENT 3
#define DEF_CONCURRENT_CLIENTS 3
struct MemoryBufferHandle
{
unsigned long n; // sample number
LONGLONG t; // timestamp
};
#endif
struct MemoryBufferEntry
{
unsigned int use_count;
REFERENCE_TIME timestamp;
IMediaSample* media_sample;
};
//###############################################################################################
class DSVL_GraphManager;
//------------------------------------------------------------------------------------------------
double avg2fps(REFERENCE_TIME AvgTimePerFrame, int precision = 3);
REFERENCE_TIME fps2avg(double fps);
//------------------------------------------------------------------------------------------------
class DSVL_GraphManager : public ISampleGrabberCB
{
public:
//IUnknown interface
HRESULT WINAPI QueryInterface( REFIID iid, void** ppvObject );
ULONG WINAPI AddRef();
ULONG WINAPI Release();
// ISampleGrabberCB interfaces
HRESULT WINAPI SampleCB(double SampleTime, IMediaSample *pSample);
HRESULT WINAPI BufferCB(double sampleTimeSec, BYTE* bufferPtr, long bufferLength);
private:
unsigned long fRefCount;
public:
DSVL_GraphManager();
~DSVL_GraphManager();
/*****************************************************************************/
HRESULT BuildGraphFromXMLString(char* xml_string = NULL);
HRESULT BuildGraphFromXMLFile(char* xml_filename = NULL);
/*****************************************************************************/
HRESULT ReleaseGraph();
bool IsGraphInitialized();
protected:
REFERENCE_TIME current_timestamp;
std::map<unsigned long, MemoryBufferEntry> mb;
unsigned long sample_counter;
unsigned int m_currentAllocatorBuffers;
public:
HRESULT GetCurrentMediaFormatEx(DS_MEDIA_FORMAT *mf);
HRESULT GetCurrentMediaFormat(LONG* frame_width, LONG *frame_height, double* frames_per_second, PIXELFORMAT* pixel_format);
HRESULT GetCurrentTimestamp(REFERENCE_TIME *Timestamp);
// I'd recommend you Lock() before querying for timestamps
REFERENCE_TIME GetCurrentTimestamp();
DWORD WaitForNextSample(long dwMilliseconds = INFINITE);
// behaves just like WaitForSingleObject
HRESULT EnableMemoryBuffer(unsigned int _maxConcurrentClients = DEF_CONCURRENT_CLIENTS,
unsigned int _allocatorBuffersPerClient = MIN_ALLOCATOR_BUFFERS_PER_CLIENT);
HRESULT DisableMemoryBuffer();
HRESULT CheckoutMemoryBuffer(MemoryBufferHandle* pHandle,
BYTE** Buffer,
unsigned int *Width = NULL,
unsigned int *Height = NULL,
PIXELFORMAT* PixelFormat = NULL,
REFERENCE_TIME* Timestamp = NULL);
// every check-out operation will increment an internal instance counter
// samples get released only if there are no active instances
HRESULT CheckinMemoryBuffer(MemoryBufferHandle Handle, bool ForceRelease = false);
// decrements the instance counter
protected:
// display property pages
HRESULT ShowFilterProperties(HWND hWnd = NULL);
HRESULT ShowPinProperties(HWND hWnd = NULL);
private:
HRESULT BuildGraphFromXMLHandle(TiXmlHandle xml_h);
// ------------------------------------------------------------------------
public:
// valid types for (long property): CameraControlProperty, VideoProcAmpProperty
HRESULT GetCameraParameterRange(CP_INTERFACE interface_type,
long property,
long *pMin,
long *pMax,
long *pSteppingDelta,
long *pDefault,
long *pCapsFlags);
HRESULT GetCameraParameter(CP_INTERFACE interface_type, long Property, long *lValue, bool *bAuto);
HRESULT SetCameraParameter(CP_INTERFACE interface_type, long Property, long lValue, bool bAuto);
protected:
long GetCameraPropertyAUTOFlag(CP_INTERFACE interface_type, bool bAUTO = true);
HRESULT GetCameraParameter(CP_INTERFACE interface_type, long Property, long *lValue, long *Flags);
HRESULT SetCameraParameter(CP_INTERFACE interface_type, long Property, long lValue, long Flags);
public:
// applies settings to a normalized the parameter range [0..1]
HRESULT GetCameraParameterN(CP_INTERFACE interface_type, long Property, double *dValue);
HRESULT SetCameraParameterN(CP_INTERFACE interface_type, long Property, double dValue); // dValue will be clamped to [0..1]
HRESULT SetCameraParameterToDefault(CP_INTERFACE interface_type, long Property, bool bAuto = TRUE);
// bAuto: indicates if the property should be controlled automatically
HRESULT ResetCameraParameters(bool bAuto = TRUE); // reset all parameters to their defaults
// Applies to all methods above:
// -----------------------------
// "Property" can be one of the following:
// (see the Microsoft DirectX 8.1 (C++) SDK documentation for details)
//
// interface_type == CP_CameraControl
// CameraControl_Pan
// CameraControl_Tilt
// CameraControl_Roll
// CameraControl_Zoom
// CameraControl_Exposure
// CameraControl_Iris
// CameraControl_Focus
// interface_type == CP_VideoProcAmp
// VideoProcAmp_Brightness,
// VideoProcAmp_Contrast,
// VideoProcAmp_Hue,
// VideoProcAmp_Saturation,
// VideoProcAmp_Sharpness,
// VideoProcAmp_Gamma,
// VideoProcAmp_ColorEnable,
// VideoProcAmp_WhiteBalance,
// VideoProcAmp_BacklightCompensation,
// VideoProcAmp_Gain
//
//
// Return values: S_OK call succeeded
// -------------- S_FALSE call succeeded, but value remained unchanged
// (GetCameraParameterN/SetCameraParameterN only)
// E_INVALIDARG interface not supported by WDM driver / unknown interface
// E_FAIL call failed
// ------------------------------------------------------------------------
// media flow control
HRESULT Run();
HRESULT Pause();
HRESULT Stop(bool forcedStop = false);
inline void Lock() { m_CSec.Lock(); }
inline void Unlock() { m_CSec.Unlock(); }
//inline void Lock() {}
//inline void Unlock() {}
private:
bool m_bGraphIsInitialized;
CCritSec m_CSec;
#ifdef _DEBUG
DWORD dwRegisterROT;
#endif
DS_MEDIA_FORMAT media_format;
HANDLE m_ESync;
const LPTSTR m_ESyncName;
//void* sync_uuid_p; // (GUID*)
//protected:
#pragma warning(disable : 4251)
// >> warning C4251: 'DSVL_GraphManager::captureGraphBuilder' : class 'ATL::CComPtr<T>'
// >> needs to have dll-interface to be used by clients of class 'DSVL_GraphManager'
CComPtr <IGraphBuilder> graphBuilder;
CComPtr <IMediaControl> mediaControl;
CComPtr <ICaptureGraphBuilder2> captureGraphBuilder;
CComPtr <IMediaEventEx> mediaEvent;
CComPtr <IMediaSeeking> mediaSeeking;
CComPtr <IAMCameraControl> cameraControl;
CComPtr <IAMDroppedFrames> droppedFrames;
CComPtr <IAMVideoControl> videoControl;
CComPtr <IAMVideoProcAmp> videoProcAmp;
CComPtr<IBaseFilter> sourceFilter;
CComPtr<IPin> capturePin;
CComPtr<IBaseFilter> decoderFilter;
CComPtr<IBaseFilter> rendererFilter;
CComPtr<IBaseFilter> grabberFilter;
CComPtr<ISampleGrabber> sampleGrabber;
};
DWORD WINAPI TShowFilterProperties(LPVOID lpParameter);
DWORD WINAPI TShowPinProperties(LPVOID lpParameter);