/*! \file FrameRenderer.h
 *   \brief Описание классов для захвата видео с web камер
 */

/*! \mainpage  Классы для захвата видео с web камер
 *  \author Волков А.Д.
 *  \version 1.0
 *  \date 26.05.08
 */

#if !defined(AFX_FRAMERENDERER_H__93D88322_AAAA_11D5_BD90_E5B9C216A273__INCLUDED_)
#define AFX_FRAMERENDERER_H__93D88322_AAAA_11D5_BD90_E5B9C216A273__INCLUDED_

#include <strmif.h>
#include <uuids.h>
#include <control.h>
#include <DShow.h>

#define SAFE_RELEASE(p) if(p){p->Release();p=NULL;}
/*! \def SAFE_RELEASE(p)
 *  \brief Макрос удаление объекта
 */

class CSampleGrabber;

const GUID CLSID_SampleGrabber =
{0xC1F400A0,0x3F08,0x11D3,{0x9F,0x0B,0x00,0x60,0x08,0x03,0x9E,0x37}}; //!< Идентификатор CLSID граббера
const GUID IID_SampleGrabber =
{0x6B652FFF,0x11FE,0x4fce,{0x92,0xAD,0x02,0x66,0xB5,0xD7,0xC7,0x8F}};//!< Идентификатор IID граббера
/*
const GUID CLSID_NullRenderer =
{0xC1F400A4,0x3F08,0x11D3,{0x9F,0x0B,0x00,0x60,0x08,0x03,0x9E,0x37}};//!< Идентификатор CLSID рендера
*/

/*! \class CFrameGrabber
    \brief Класс граббера основной
 */
class CFrameGrabber
{
/*! \fn UINT ConfigureCamera_thread(LPVOID pParam)
 *  \brief Функция потока для вывода свойств
 */
friend UINT ConfigureCamera_thread(LPVOID pParam);
/*! \fn UINT ConfigureCamera_thread_new(LPVOID pParam)
 *  \brief Функция потока для вывода свойств (новый вариант)
 */
friend UINT ConfigureCamera_thread_new(LPVOID pParam);
/*! \fn UINT DisplayVideoCapture_thread(LPVOID pParam)
 *  \brief Функция потока для вывода свойств потока
 */
friend UINT DisplayVideoCapture_thread(LPVOID pParam);

private:
	CString m_strFileName;//!< Имя выходного видео файла
	bool bSaveFile;//!< Признак создания видео файла
	bool bShow;//!< Признак предварительного просмотра видео
	OAHWND m_Handle;//!< укзатель на окно вывода
	CRect m_VideoRect;//!< Область вывода видео
	HANDLE mutex;//!< Указатель на поток для захвата
	bool m_bCapturing;//!< флаг захвата
	IBaseFilter *m_pvideo;//!< Фильтер видео устройство
	IBaseFilter *m_paudio;//!< Фильтер аудио устройство
	IGraphBuilder *m_pGraph;//!< Интерфейс захвата
	CSampleGrabber *m_pGrabber; //!< Указатель класс 
	ICaptureGraphBuilder *m_pBuilder;//!< Интерфейс захвата
	IVideoWindow *m_pVideoWindow;//!< Интерфейс предварительного просмотра
private:
/*! \fn void CreateBuilder()
 *  \brief Cоздание устройства захвата
 *  \return функция не возрашает значений
 */
	void CreateBuilder();
/*! \fn void Preview()
 *  \brief Cоздание предварительного просмотра
 *  \return функция не возрашает значений
 */	
	void Preview();

/*! \fn IBaseFilter *ScanDevice(IID id, CStringArray *psa,CString * refs,bool bsearch)
 *  \brief Поиск устройств
 *  \param [in] id Идентификатор CLSID компаненты DirectShow,обеспечивающий создания графа и его функционирование
 *  \note CLSID_VideoInputDeviceCategory Видео устройства
 *  \note CLSID_AudioInputDeviceCategory Аудио устройства
 *  \param [out] psa список найденых устройств
 *  \param [in] refs имя устройства, которое надо найти
 *  \param [in] bsearch признак поиска
 *  \return функция возрашает NULL или указатель на фильтер устройства
 */

	IBaseFilter *ScanDevice(IID id, CStringArray *psa,CString * refs,bool bsearch);

/*! \fn	void *RecieveBitmap(long *pcbBuffer)
 *  \brief Получение массива яркостей
 *  \param [out] pcbBuffer указатель на переменную (длина массива)
 *  \return Функция возвращает массив цветовых значений пикселей (зависит от режима
 *  при стандартных значений 320x240 это массив из 76800 троек RGB (по байту на цвет))
 */
	void *RecieveBitmap(long *pcbBuffer);

/*! \fn void SaveToBitmap(void *psrcimg,long cbBuffer,CString szFileName)
 *  \brief Запись масcива цветовых значений в графический файл
 *  \param [in] psrcimg массив цветовых значений пикселей
 *  \param [in] cbBuffer длина массива
 *  \param [in] szFileName имя выходного графического файла
 *  \sa RecieveBitmap(long *pcbBuffer)
 */
	void SaveToBitmap(void *psrcimg,long cbBuffer,CString szFileName);

/*! \fn void QueryGraphInfo(IGraphBuilder *pgb)
 *  \brief Запрос информации о графе
 *  \param [out] pgb указатель на соединяющий граф
 */
	void QueryGraphInfo(IGraphBuilder *pgb);

/*! \fn void GetBitmapInfoHeader(BITMAPINFOHEADER *pbih)
 *  \brief Получить информацию о текущем изображении
 *  \param [out] pbih указатель на структуру BITMAPINFOHEADER
 */
	void GetBitmapInfoHeader(BITMAPINFOHEADER *pbih);
public:
	CFrameGrabber();
	virtual ~CFrameGrabber();
/*! \fn void ScanDevice(IID id, CStringArray *psa)
 *  \brief Поиск устройств
 *  \param [in] id Идентификатор CLSID компаненты DirectShow,обеспечивающий создания графа и его функционирование
 *  \note CLSID_VideoInputDeviceCategory Видео устройства
 *  \note CLSID_AudioInputDeviceCategory Аудио устройства
 *  \param [out] psa список найденых устройств
 *  \sa IBaseFilter *ScanDevice(IID id, CStringArray *psa,CString * refs,bool bsearch)
 */
	void ScanDevice(IID id, CStringArray *psa);
/*! \fn IBaseFilter *SelectVideoDevice(CString dev_video)
 *  \brief Выбор видео устройства
 *  \param [in] dev_video название видео устройства
 *  \return указатель на видео устройство
 *  \sa IBaseFilter *ScanDevice(IID id, CStringArray *psa,CString * refs,bool bsearch)
 */
	IBaseFilter *SelectVideoDevice(CString dev_video);
	IBaseFilter *SelectAudioDevice(CString dev_aduio);
	IBaseFilter *SelectVideoCompressor(CString video_compress_name);

/*! \fn bool Run()
 *  \brief Запуск работы видео устройства
 *  \return значение выполнения
 *  \retval true успешный запуск видео устройства
 *  \retval false устройство не запущено
 */
	bool Run();

/*! \fn void Stop()
 *  \brief Останов работы видео устройства
 */
	void Stop();

/*! \fn bool ConstructCaptureGraph(CString videodev)
 *  \brief Построение графа захвата информации
 *  \param [in] videodev имя видео источника
 *  \return возращает признак выполнения 
 *  \retval true граф настроен
 *  \retval false ошибка
 */
	bool ConstructCaptureGraph(CString videodev,CString audiodev);

/*! \fn void SetFileName(CString strFileName)
 *  \brief Задание имени выходного файла
 *  \param [in] strFileName имя видео файла
 *  \remarks задает имя выходному файлу и установливает признак создания видео файла
 *  \sa m_strFileName
 *  \sa bSaveFile
 */
	void SetFileName(CString strFileName);

/*! \fn void ConfigureCamera()
 *  \brief Вывод настроек видео источника
 */
	void ConfigureCamera();

/*! \fn void DisplayVideoCapturePinPropertyPage()
 *  \brief Вывод информации о видео потоке
 */
	void DisplayVideoCapturePinPropertyPage();

/*! \fn void SetVideoWindow(HWND Handle)
 *  \brief Установка указателя на окно и области вывода видео информации
 *  \param Handle указатель на окно вывода
 */
	void SetVideoWindow(HWND Handle);

/*! \fn void SetPreview(bool Prev)
 *  \brief Установка признака предварительного просмотра видео
 *  \param Prev Признак предварительного просмотра видео
 *  \sa bShow
 */
	void SetPreview(bool Prev);

/*! \overload void SetPreview(int iPrev)
 *  \brief  Установка признака предварительного просмотра видео
 *  \param iPrev Признак предварительного просмотра видео
 *  \sa bShow
 */
	void SetPreview(int iPrev);

/*! \fn bool SaveToBitmap(CString szFileName)
 *  \brief Запись масcива цветовых значений в графический файл
 *  \param [in] szFileName имя выходного графического файла 
 *  \sa void *RecieveBitmap(long *pcbBuffer)
 *  \sa void SaveToBitmap(void *psrcimg,long cbBuffer,CString szFileName)
 *  \return 
 *  \retval true файл записан
 *  \retval false ошибка
 */
	bool SaveToBitmap(CString szFileName);
};

/*! \fn DECLARE_INTERFACE(ISampleGrabber)
 *  \brief интерфейс граббера
 */
DECLARE_INTERFACE(ISampleGrabber):public IUnknown
{
	STDMETHOD(SetOneShot(BOOL OneShot)) = 0;
	STDMETHOD(SetMediaType(const AM_MEDIA_TYPE *pType)) = 0;
    STDMETHOD(GetConnectedMediaType(AM_MEDIA_TYPE *pType)) = 0;
	STDMETHOD(SetBufferSamples(BOOL BufferThem)) = 0;
	STDMETHOD(GetCurrentBuffer(long *pBufferSize,long *Buffer)) = 0;
	STDMETHOD(GetCurrentSample(IMediaSample **ppSample)) = 0;
};

/*! \class CSampleGrabber
    \brief Класс граббера дополнительный
 */
class CSampleGrabber
{
public:
	CSampleGrabber();
	virtual ~CSampleGrabber();
/*! \fn void AddToGraph(IGraphBuilder *pgraph)
 *  \brief Добавление фильтов к граберу
 *  \param pgraph указатель на граф
 */
	void AddToGraph(IGraphBuilder *pgraph);
public:
	IBaseFilter *m_pNullRenderer;//!< рендер
	IBaseFilter *m_pVideoRenderer;//!< Видео рендер
	IBaseFilter *m_pAudioRenderer;//!< Аудио рендер
	IBaseFilter *m_pFilter;//!< фильтр-граббер
	IFileSinkFilter *m_pSinkFilter;//!< Фильтер для записи AVI файла
	ISampleGrabber *m_pGrabber;//!< интерфейс граббера
	IPin *m_pInputPin;//!< Входной пин
	IPin *m_pOutputPin;//!< Выходной пин
};
#endif