// DVP2420SampleDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DVP2420Sample.h"
#include "DVP2420SampleDlg.h"
#include "PRsettingDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Constants
#define BFT_BITMAP 0x4d42   /* 'BM' */

#define DibNumColors(lpbi)      ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
                                    ? (int)(1 << (int)(lpbi)->biBitCount)          \
                                    : (int)(lpbi)->biClrUsed)

#define DibSize(lpbi)           ((lpbi)->biSize + (lpbi)->biSizeImage + (int)(lpbi)->biClrUsed * sizeof(RGBQUAD))

#define DibPaletteSize(lpbi)    (DibNumColors(lpbi) * sizeof(RGBQUAD))

typedef int (WINAPI* CreateEncSDKInstenceType)(void **pp);
typedef int (WINAPI* CreateDecSDKInstenceType)(void **pp);

HINSTANCE					dllEncHandle = NULL;
CreateEncSDKInstenceType	CreateEncSDKInstencePtr = NULL;
IDVP2420EncSDK	*pDVPEncSDK = NULL;

HINSTANCE					dllDecHandle = NULL;
CreateDecSDKInstenceType	CreateDecSDKInstencePtr = NULL;
IDVP2420DecSDK	*pDVPDecSDK = NULL;

const INT64 MBYTE		= 1024*1024;   // 1MB
const INT64 nMsgEvery			= 2*1024*1024;

FileBufferIO	file_writer[MAXCHS];
INT64	nAccumulatedSize[MAXCHS];
INT64	nSegmentSize[MAXCHS];
INT64	nMsgNext[MAXCHS];
double	dMByteSize[MAXCHS];
int		nSegmentCnt[MAXCHS];
int		nFileSize[MAXCHS];
char	sDestFileName[MAXCHS][MAX_FILENAME_LEN];

BOOL	bSkipDL[MAXCHS];
BOOL	bSave[MAXCHS];
BOOL	bPartition[MAXCHS];
BOOL	bFirst[MAXCHS];

HWND hMainWnd;
int nChCnt = 0;
int nPreviewCnt = 0;
CString msg;

void StreamReadOpen(int nChNum);
void StreamReadProc(int nChNum, BYTE *pStreamBuf, UINT32 nBytesToTransfer, BOOL bIFrame, UINT32 nIFrameOffset);
void StreamReadClose(int nChNum);

void MakeFileName(int nChNum, int nSignalType, int nMPEGType, char *pFileName)
{
	if (!pFileName)
		return;

	switch (nMPEGType)
	{
		case 0:
			strcpy(pFileName, "C:\\MPEG1");
			break;
		case 1:
			strcpy(pFileName, "C:\\MPEG2");
			break;
		case 2:
			strcpy(pFileName, "C:\\MPEG4");
			break;
	}

	switch (nSignalType)
	{
		case 0:
			strcat(pFileName, "PAL");
			break;
		case 1:
			strcat(pFileName, "NTSC");
			break;
	}

	switch (nChNum)
	{
		case 0:
			strcat(pFileName, "01.mpg");
			break;
		case 1:
			strcat(pFileName, "02.mpg");
			break;
	}
}

//StreamRead callback function sturcture
STREAMREAD_STRUCT StreamRead = {StreamReadOpen,
								StreamReadProc,
								StreamReadClose};

/********************************************************
*
*	StreamRead callback function
*
/********************************************************/

/**
 * @brief This function is the StreamReadOpen callback function that called when the stream read process is started.
 *
 * @param nChNum Specifies the video channel ID number.
 *
 */

void StreamReadOpen(int nChNum)
{
	nAccumulatedSize[nChNum] = 0;
	nSegmentSize[nChNum] = 0;
	nMsgNext[nChNum] = nMsgEvery;
	dMByteSize[nChNum] = 0.0;
	nSegmentCnt[nChNum] = 0;
	bFirst[nChNum] = TRUE;

	if (bSave[nChNum])
	{
		file_writer[nChNum].openFile(sDestFileName[nChNum], "wb");
		pDVPEncSDK->DVP2420_SetFileName(nChNum, sDestFileName[nChNum]);
	}
}

/**
 * @brief This function is the StreamReadProc callback function that called when the stream is read.
 *
 * @param nChNum Specifies the video channel ID number.
 * @param pStreamBuf A byte point of the data buffer that stores the encoded data.
 * @param nBytesToTransfer Specifies the size of the encoded data.
 * @param bIFrame Specifies if there is any I-frame in this encoded data. The value 1 means true, the value 0 means false.
 * @param nIFrameOffset Specifies the number of bytes from the start of the data buffer to first I-frame start code.
 *
 */

void StreamReadProc(int nChNum, BYTE *pStreamBuf, UINT32 nBytesToTransfer, BOOL bIFrame, UINT32 nIFrameOffset)
{
	nAccumulatedSize[nChNum] += (INT64)nBytesToTransfer;
	if ( nAccumulatedSize[nChNum] >= (INT64)nMsgNext[nChNum] ) {
		dMByteSize[nChNum] = (double)nAccumulatedSize[nChNum] / MBYTE;
		msg.Format(_T("Channel %d : %.2f MBytes\n"), nChNum+1, dMByteSize[nChNum]);
		SetDlgItemText(hMainWnd, IDC_STATUS_TEXT, msg);
		nMsgNext[nChNum] += nMsgEvery;
	}

	nSegmentSize[nChNum] += (INT64)nBytesToTransfer;
	if (bPartition[nChNum] && nSegmentSize[nChNum] > nFileSize[nChNum]*MBYTE && bIFrame && !bFirst[nChNum]) {
		if (file_writer[nChNum].IsFileOpened())
		{
			file_writer[nChNum].writeFile(pStreamBuf, nIFrameOffset);
			file_writer[nChNum].closeFile();

			char *pDest;
			char sNextFileName[MAX_FILENAME_LEN];
			strcpy(sNextFileName, sDestFileName[nChNum]);
			pDest = strrchr(sNextFileName, '.');
			sprintf(pDest, "_%04d.mpg", ++nSegmentCnt[nChNum]);
			file_writer[nChNum].openFile(sNextFileName, "wb");
			file_writer[nChNum].writeFile(pStreamBuf+nIFrameOffset, nBytesToTransfer-nIFrameOffset);
			nSegmentSize[nChNum] = 0;
			pDVPEncSDK->DVP2420_SetFileName(nChNum, sNextFileName);
		}
	}
	else {
		if (file_writer[nChNum].IsFileOpened())
		{
			file_writer[nChNum].writeFile(pStreamBuf, nBytesToTransfer);
		}
	}

	bFirst[nChNum] = FALSE;
}

/**
 * @brief This function is the StreamReadClose callback function that called when the stream read process is finished.
 *
 * @param nChNum Specifies the video channel ID number.
 *
 */

void StreamReadClose(int nChNum)
{
	if (file_writer[nChNum].IsFileOpened())
		file_writer[nChNum].closeFile();
}

/********************************************************
*
*	MotionDetect callback function
*
/********************************************************/

/**
 * @brief This function is the MotionDetectProc callback function that called when there are the motions being detected in the specified video region.
 *
 * @param nChNum Specifies the video channel ID number.
 * @param nRegionNum Specifies the ID number of the video region.
 * @param mbCount Specifies the number of the macroblocks that there are motions being detected.
 *
 */
void MotionDetectProc(int nChNum, int nRegionNum, unsigned short mbCount)
{
	msg.Format(_T("Channel %d : region %d, block count = [0x%08x]\n"), nChNum+1, nRegionNum+1, mbCount);
	SetDlgItemText(hMainWnd, IDC_STATUS_TEXT, msg);
}

/********************************************************
*
*	EncoderFail callback function
*
/********************************************************/

void EncFailProc(int nChNum)
{
	msg.Format(_T("Channel %d : Encoding failed!!\n"), nChNum+1);
	SetDlgItemText(hMainWnd, IDC_STATUS_TEXT, msg);
}

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDVP2420SampleDlg dialog

CDVP2420SampleDlg::CDVP2420SampleDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDVP2420SampleDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDVP2420SampleDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	for (int i=0; i<MAXCHS; i++)
	{
		m_bChipInited[i]	= FALSE;
		m_bEncoded[i]		= FALSE;
		m_bDecoded[i]		= FALSE;
		m_bPreviewed[i]		= FALSE;
		m_bDetected[i]		= FALSE;
		bSkipDL[i]			= FALSE;
		bSave[i]			= TRUE;
		bPartition[i]		= FALSE;
		m_pPreviewDlg[i]	= NULL;
		m_pPlaybackDlg[i]	= NULL;
	}
}

void CDVP2420SampleDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDVP2420SampleDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDVP2420SampleDlg, CDialog)
	//{{AFX_MSG_MAP(CDVP2420SampleDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_ENCODE_BTN, OnEncodeBtn)
	ON_BN_CLICKED(IDC_PREVIEW_BTN, OnPreviewBtn)
	ON_CBN_SELCHANGE(IDC_CHANNEL_COMBO, OnSelchangeChannelCombo)
	ON_BN_CLICKED(IDC_PLAYBACK_BTN, OnPlaybackBtn)
	ON_BN_CLICKED(IDC_SNAPSHOT_BTN, OnSnapshotBtn)
	ON_BN_CLICKED(IDC_MOTION_BTN, OnMotionBtn)
	ON_BN_CLICKED(IDC_SENSOR_BTN, OnSensorBtn)
	ON_BN_CLICKED(IDC_GPIO_BTN, OnGpioBtn)
	ON_BN_CLICKED(IDC_ENCSET_BTN, OnEncsetBtn)
	ON_BN_CLICKED(IDC_DIVX_BTN, OnDivxBtn)
	ON_BN_CLICKED(IDC_BROWSE_BTN, OnBrowseBtn)
	ON_BN_CLICKED(IDC_SAVE_CHK, OnSaveChk)
	ON_BN_CLICKED(IDC_PARTITION_CHK, OnPartitionChk)
	ON_CBN_SELCHANGE(IDC_MPEG_COMBO, OnSelchangeMpegCombo)
	ON_CBN_SELCHANGE(IDC_SIGNAL_COMBO, OnSelchangeSignalCombo)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDVP2420SampleDlg message handlers

BOOL CDVP2420SampleDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	hMainWnd = this->GetSafeHwnd();
	dllEncHandle = LoadLibrary("DVP2420EncSDK.dll");
    if (dllEncHandle) 
    { 
		//Use GetProcAddress to get SDK function pointer
		CreateEncSDKInstencePtr = (CreateEncSDKInstenceType)GetProcAddress(dllEncHandle, "DVP2420_CreateEncSDKInstence");

		// If the function address is valid, call the function. 
		if (CreateEncSDKInstencePtr)
		{
			CreateEncSDKInstencePtr((void **)&pDVPEncSDK);
			if (!pDVPEncSDK)
				return TRUE;
		}
		else
			return TRUE;
	}

	int retval = pDVPEncSDK->DVP2420_InitSDK();		//Initializes the DVP2420 Encoding SDK.
	if (retval == ENC_SUCCEEDED)
	{
		pDVPEncSDK->DVP2420_GetChipCount(&nChCnt);
		char ChannelNo[20];
		for (int i=0; i<nChCnt; i++) {
			sprintf(ChannelNo, "Channel %d", i+1);
			((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->AddString(ChannelNo);
		}
		((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->SetCurSel(0);
		GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_PREVIEW_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_MOTION_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_SENSOR_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_GPIO_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_ENCSET_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_DIVX_BTN)->EnableWindow(TRUE);
		GetDlgItem(IDC_SAVE_CHK)->EnableWindow(TRUE);
		GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(TRUE);
		((CButton*)GetDlgItem(IDC_SAVE_CHK))->SetCheck(TRUE);
	}

	dllDecHandle = LoadLibrary("DVP2420DecSDK.dll");
	if (dllDecHandle) 
	{ 
		//Use GetProcAddress to get SDK function pointer
		CreateDecSDKInstencePtr = (CreateDecSDKInstenceType)GetProcAddress(dllDecHandle, "DVP2420_CreateDecSDKInstence");

		// If the function address is valid, call the function. 
		if (CreateDecSDKInstencePtr)
		{
			CreateDecSDKInstencePtr((void **)&pDVPDecSDK);
			GetDlgItem(IDC_PLAYBACK_BTN)->EnableWindow(TRUE);
		}
	}
	
	((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->SetCurSel(1);
	((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->SetCurSel(2);
	((CComboBox *)GetDlgItem(IDC_VIDEOSIZE_COMBO))->SetCurSel(0);

	msg.Format(_T("DVP2420EncSDK V%.2f"), pDVPEncSDK->DVP2420_GetSDKVersion());
	SetDlgItemText(IDC_STATUS_TEXT, msg);
	GetDlgItem(IDC_FILENAME_EDIT)->SetWindowText("C:\\MPEG4NTSC01.mpg");
	GetDlgItem(IDC_SIZE_EDIT)->SetWindowText("5");
	GetCurrentDirectory(MAX_FILENAME_LEN, m_CurPath);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDVP2420SampleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDVP2420SampleDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDVP2420SampleDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CDVP2420SampleDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	for (int i=0; i<MAXCHS; i++)
	{
		if (m_pPlaybackDlg[i])
		{
			delete m_pPlaybackDlg[i];
			m_pPlaybackDlg[i] = NULL;
		}
	}

	if (pDVPEncSDK)
	{
		pDVPEncSDK->DVP2420_CloseSDK();	//Closes up the SDK
		pDVPEncSDK = NULL;
	}

	//Free the library:
	if (dllDecHandle)
		FreeLibrary(dllDecHandle);

	if (dllEncHandle)
	//Free the library:
	    FreeLibrary(dllEncHandle);
}

void CDVP2420SampleDlg::OnEncodeBtn() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();
	int nSignalType = ((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->GetCurSel();
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();
	int nVideoSize = ((CComboBox *)GetDlgItem(IDC_VIDEOSIZE_COMBO))->GetCurSel();
	bSave[nChNum] = ((CButton*)GetDlgItem(IDC_SAVE_CHK))->GetCheck();

	if (m_bEncoded[nChNum])
	{
		//Stop video encode
		if (pDVPEncSDK->DVP2420_StopEncode(nChNum) != ENC_SUCCEEDED) {
			SetDlgItemText(IDC_STATUS_TEXT, "Stop Encodeing failed!\n");
			return;
		}

		//Release chip
		if (pDVPEncSDK->DVP2420_ReleaseChips(nChNum) != ENC_SUCCEEDED)
		{
			SetDlgItemText(IDC_STATUS_TEXT, "Release Chip failed!\n");
			return;
		}

		if (m_pPlaybackDlg[nChNum])
		{
			if (!m_bPreviewed[nChNum] && m_pPlaybackDlg[nChNum]->m_bDecoded != TRUE)
				m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(TRUE);
		}

		GetDlgItem(IDC_SAVE_CHK)->EnableWindow(TRUE);
		GetDlgItem(IDC_FILENAME_EDIT)->EnableWindow(TRUE);
		GetDlgItem(IDC_BROWSE_BTN)->EnableWindow(TRUE);
		if (bSave[nChNum])
			GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(TRUE);
		if (bPartition[nChNum])
			GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(TRUE);
		
		msg.Format(_T("Channel %d : Stop video encoding() success!\n"), nChNum+1);
		SetDlgItemText(IDC_STATUS_TEXT, msg);
		GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(TRUE);
		SetDlgItemText(IDC_ENCODE_BTN, "Encode");
		m_bEncoded[nChNum] = FALSE;
		m_bChipInited[nChNum] = FALSE;
		return;
	}

	switch (nSignalType)
	{
		case 0:
			nSignalType = PAL;
			break;
		case 1:
			nSignalType = NTSC;
			break;
	}

	switch (nMPEGType)
	{
		case 0:
			nMPEGType = MPEG1;
			break;
		case 1:
			nMPEGType = MPEG2;
			break;
		case 2:
			nMPEGType = MPEG4;
			break;
	}

	CString FileName;
	GetDlgItem(IDC_FILENAME_EDIT)->GetWindowText(FileName);
	strcpy(sDestFileName[nChNum], FileName.GetBuffer(MAX_FILENAME_LEN));
	FileName.ReleaseBuffer();

	CString FileSize;
	GetDlgItem(IDC_SIZE_EDIT)->GetWindowText(FileSize);
	nFileSize[nChNum] = atoi(FileSize.GetBuffer(10));
	FileSize.ReleaseBuffer();

	GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(FALSE);

	//Initialize chip
	if (!m_bChipInited[nChNum]) {
		if (pDVPEncSDK->DVP2420_InitChips(nChNum) == ENC_SUCCEEDED) {
			m_bChipInited[nChNum] = TRUE;
			SetDlgItemText(IDC_STATUS_TEXT, "Initialize chip success!\n");
		}
		else {
			SetDlgItemText(IDC_STATUS_TEXT, "Initialize chip failed!\n");
			GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
			return;
		}
	}

	if (!bSkipDL[nChNum]) {
		//Download firmware
		if (pDVPEncSDK->DVP2420_DownloadFW(nChNum) != ENC_SUCCEEDED) {
			//Release chip
			if (pDVPEncSDK->DVP2420_ReleaseChips(nChNum) == ENC_SUCCEEDED)
				m_bChipInited[nChNum] = FALSE;

			SetDlgItemText(IDC_STATUS_TEXT, "Download firmware failed!\n");
			GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
			return;
		}
		bSkipDL[nChNum] = TRUE;
	}

	if (pDVPEncSDK->DVP2420_SetSignalType(nChNum, nSignalType) != ENC_SUCCEEDED)
		TRACE("Set Signal Type Failed!\n");

	if (pDVPEncSDK->DVP2420_SetMPEGType(nChNum, nMPEGType, nVideoSize) != ENC_SUCCEEDED)
		TRACE("Set MPEG Type And Video Size Failed!\n");

	//Register StreamRead callback function
	pDVPEncSDK->DVP2420_RegStreamReadCB(&StreamRead);
	//Register MotionDetect callback function
	pDVPEncSDK->DVP2420_RegMotionDetectCB(MotionDetectProc);
	//Register EncodingFail callback function
	pDVPEncSDK->DVP2420_RegEncFailCB(EncFailProc);

	//Start video encode
	if (pDVPEncSDK->DVP2420_StartEncode(nChNum) != ENC_SUCCEEDED) {
		//Release chip
		if (pDVPEncSDK->DVP2420_ReleaseChips(nChNum) == ENC_SUCCEEDED)
			m_bChipInited[nChNum] = FALSE;

		SetDlgItemText(IDC_STATUS_TEXT, "Start encoding failed!\n");
		GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
		return;
	}

	if (m_pPlaybackDlg[nChNum])
	{
		((CButton *)m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK))->SetCheck(FALSE);
		m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(FALSE);
	}

	bPartition[nChNum] = ((CButton*)GetDlgItem(IDC_PARTITION_CHK))->GetCheck();
	GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(FALSE);
	GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(FALSE);
	GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(FALSE);
	GetDlgItem(IDC_SAVE_CHK)->EnableWindow(FALSE);
	GetDlgItem(IDC_FILENAME_EDIT)->EnableWindow(FALSE);
	GetDlgItem(IDC_BROWSE_BTN)->EnableWindow(FALSE);
	GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(FALSE);
	GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(FALSE);
	GetDlgItem(IDC_ENCODE_BTN)->EnableWindow(TRUE);
	SetDlgItemText(IDC_ENCODE_BTN, "Stop");
	m_bEncoded[nChNum] = TRUE;
}

void CDVP2420SampleDlg::OnPreviewBtn() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();

	if (m_bPreviewed[nChNum]) {
		//Stop video preview
		pDVPEncSDK->DVP2420_StopPreview(nChNum);

		if (m_pPlaybackDlg[nChNum])
		{
			if (!m_bEncoded[nChNum] && m_pPlaybackDlg[nChNum]->m_bDecoded != TRUE)
				m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(TRUE);
		}

		nPreviewCnt--;
		m_bPreviewed[nChNum] = FALSE;
		SetDlgItemText(IDC_PREVIEW_BTN, "Preview");
		GetDlgItem(IDC_SNAPSHOT_BTN)->EnableWindow(FALSE);
		m_pPreviewDlg[nChNum]->DestroyWindow();
		delete m_pPreviewDlg[nChNum];
		m_pPreviewDlg[nChNum] = NULL;
		return;
	}

	CPRSettingDlg PRSetingDlg;
	if (PRSetingDlg.DoModal() == IDOK) {
		
		m_pPreviewDlg[nChNum] = new CDialog();
		m_pPreviewDlg[nChNum]->Create(IDD_DISPLAY_DLG);
	    m_pPreviewDlg[nChNum]->ShowWindow(SW_SHOW);

		//Calculate the size of the display window
		int nVideoSize = PRSetingDlg.m_nVideoSize;
		int nSignalType = PRSetingDlg.m_nSignalType+1;

		int nWidth, nHeight;
		switch (nVideoSize)
		{
			case D1:
				nWidth = 720;
				nHeight = (nSignalType == NTSC) ? 480:576;
				break;
			case VGA:
				nWidth = 640;
				nHeight = (nSignalType == NTSC) ? 480:576;
				break;
			case QVGA:
				nWidth = 320;
				nHeight = (nSignalType == NTSC) ? 240:288;
				break;
			case SIF:
				nWidth = 352;
				nHeight = (nSignalType == NTSC) ? 240:288;
				break;
			case QCIF:
				nWidth = 176;
				nHeight = 144;
				break;
		}

	    RECT rcW, rcC;
		int xExtra, yExtra;
	    m_pPreviewDlg[nChNum]->GetWindowRect(&rcW);
		m_pPreviewDlg[nChNum]->GetClientRect(&rcC);
	    xExtra = rcW.right - rcW.left - rcC.right;
		yExtra = rcW.bottom - rcW.top - rcC.bottom;

		char caption[256];
		RECT rect;
		GetWindowRect(&rect);
		sprintf(caption, "Channel %d: Preview", nChNum+1);
		m_pPreviewDlg[nChNum]->SetWindowText(caption);
		m_pPreviewDlg[nChNum]->SetWindowPos(NULL, rect.left+nPreviewCnt*20, rect.bottom+nPreviewCnt*20, nWidth+xExtra, nHeight+yExtra, SWP_NOZORDER);

		BOOL bDisableAudio = PRSetingDlg.m_bDisableAudio;
		//Start video preview
		if (pDVPEncSDK->DVP2420_StartPreview(nChNum, m_pPreviewDlg[nChNum]->GetSafeHwnd(), 30, bDisableAudio) != ENC_SUCCEEDED)
		{
			m_pPreviewDlg[nChNum]->DestroyWindow();
			delete m_pPreviewDlg[nChNum];
			m_pPreviewDlg[nChNum] = NULL;
			SetDlgItemText(IDC_STATUS_TEXT, "Start preview failed!\n");
			return;
		}

		if (m_pPlaybackDlg[nChNum])
		{
			((CButton *)m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK))->SetCheck(FALSE);
			m_pPlaybackDlg[nChNum]->GetDlgItem(IDC_DISPLAYWND_CHK)->EnableWindow(FALSE);
		}

		nPreviewCnt++;
		m_bPreviewed[nChNum] = TRUE;
		SetDlgItemText(IDC_PREVIEW_BTN, "Stop");
		GetDlgItem(IDC_SNAPSHOT_BTN)->EnableWindow(TRUE);
	}
}

void CDVP2420SampleDlg::OnPlaybackBtn() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();

	if (m_pPlaybackDlg[nChNum])
	{
		delete m_pPlaybackDlg[nChNum];
		m_pPlaybackDlg[nChNum] = NULL;
	}

	m_pPlaybackDlg[nChNum] = new CPlaybackDlg(this, nChNum);
	m_pPlaybackDlg[nChNum]->Create(IDD_PLAYBACK_DLG);
	m_pPlaybackDlg[nChNum]->ShowWindow(SW_SHOW);
	CString sCaption;
	sCaption.Format(_T("Channel %d: Playback"), nChNum+1);
	m_pPlaybackDlg[nChNum]->SetWindowText(sCaption);
	m_bDecoded[nChNum] = TRUE;
	GetDlgItem(IDC_PLAYBACK_BTN)->EnableWindow(FALSE);
}

void CDVP2420SampleDlg::OnSnapshotBtn() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();

	long lBufSize = 0;
	long *lpImageBuf = NULL;
	if (pDVPEncSDK->DVP2420_GetCurImage(nChNum, lpImageBuf, &lBufSize) == FAILURE) {
		return;
	}

	lpImageBuf = new long [lBufSize];
	if (pDVPEncSDK->DVP2420_GetCurImage(nChNum, lpImageBuf, &lBufSize) == FAILURE) {
		delete lpImageBuf;
		lpImageBuf = NULL;
		return;
	}
	
	BITMAPFILEHEADER    hdr;
	DWORD               dwSize, dwWritten;
	LPBITMAPINFOHEADER  pdib = (LPBITMAPINFOHEADER) lpImageBuf;

	// Create a new file to store the bitmap data
	HANDLE hFile = CreateFile("DVP2420SDK.bmp", GENERIC_WRITE, FILE_SHARE_READ, NULL,
                          CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

	if (hFile == INVALID_HANDLE_VALUE)
		return;

	// Initialize the bitmap header
	dwSize = DibSize(pdib);
	hdr.bfType          = BFT_BITMAP;
	hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
	hdr.bfReserved1     = 0;
	hdr.bfReserved2     = 0;
	hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + pdib->biSize +
	DibPaletteSize(pdib);

	// Write the bitmap header and bitmap bits to the file
	WriteFile(hFile, (LPCVOID) &hdr, sizeof(BITMAPFILEHEADER), &dwWritten, 0);
	WriteFile(hFile, (LPCVOID) pdib, dwSize, &dwWritten, 0);

	// Close the file
	CloseHandle(hFile);
	delete lpImageBuf;
	lpImageBuf = NULL;
}

void CDVP2420SampleDlg::OnMotionBtn() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();

	if (m_bDetected[nChNum] == TRUE) {
		pDVPEncSDK->DVP2420_StopMotionDetect(nChNum);

		msg.Format(_T("Channel %d : Stop Motion Detect!\n"), nChNum+1);
		SetDlgItemText(IDC_STATUS_TEXT, msg);
		GetDlgItem(IDC_MOTION_BTN)->SetWindowText("Motion Detect");
		m_bDetected[nChNum] = FALSE;
		return;
	}

	pDVPEncSDK->DVP2420_StartMotionDetect(nChNum);

	msg.Format(_T("Channel %d : Start Motion Detect!\n"), nChNum+1);
	SetDlgItemText(IDC_STATUS_TEXT, msg);
	GetDlgItem(IDC_MOTION_BTN)->SetWindowText("Stop");
	m_bDetected[nChNum] = TRUE;
}

void CDVP2420SampleDlg::OnSensorBtn() 
{
	// TODO: Add your control notification handler code here
	CSensorCtrlDlg SensorCtrlDlg;
	SensorCtrlDlg.DoModal();
}

void CDVP2420SampleDlg::OnGpioBtn() 
{
	// TODO: Add your control notification handler code here
	CGPIOCtrlDlg GPIOCtrlDlg;
	GPIOCtrlDlg.DoModal();
}

void CDVP2420SampleDlg::OnEncsetBtn() 
{
	// TODO: Add your control notification handler code here
	CEncParamSetDlg EncParamSetDlg;
	EncParamSetDlg.DoModal();
}

void CDVP2420SampleDlg::OnDivxBtn() 
{
	// TODO: Add your control notification handler code here
	CString FileName;
	char dest_filename[MAX_FILENAME_LEN];
	char divx_filename[MAX_FILENAME_LEN];
	int i=0;

	GetDlgItem(IDC_FILENAME_EDIT)->GetWindowText(FileName);
	strcpy(dest_filename, FileName.GetBuffer(MAX_FILENAME_LEN));
	strcpy(divx_filename, dest_filename);

	if (strlen(dest_filename) == 0) {
		SetDlgItemText(IDC_STATUS_TEXT, "Not indicate the output filename.");
		return;
	}

	for (i=(int)strlen(divx_filename); i > 0; i--) {
		if (divx_filename[i] == '.') {
			break;
		}
	}
	strcpy(&divx_filename[i], ".avi\0");

	HRESULT hr = pDVPEncSDK->DVP2420_PSMPEG4ToDivx(dest_filename, divx_filename);
	if (SUCCEEDED(hr))
		SetDlgItemText(IDC_STATUS_TEXT, "MPEG-4 to DiVX conversion, success!");
	else
		SetDlgItemText(IDC_STATUS_TEXT, "MPEG-4 to DiVX conversion, failure!");
}

void CDVP2420SampleDlg::OnBrowseBtn() 
{
	// TODO: Add your control notification handler code here
	CFileDialog FileDlg (FALSE, "mpg", "*.mpg", 
		OFN_FILEMUSTEXIST| OFN_HIDEREADONLY, "Movie Files (*.mpg)", this);

	if (FileDlg.DoModal() ==IDOK) {
		GetDlgItem(IDC_FILENAME_EDIT)->SetWindowText(FileDlg.GetPathName());
		GetDlgItem(IDC_FILENAME_EDIT)->UpdateWindow();
		FileDlg.GetPathName().ReleaseBuffer();
		SetCurrentDirectory(m_CurPath);
	}
}

void CDVP2420SampleDlg::OnSelchangeChannelCombo() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();
	int nSignalType = ((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->GetCurSel();
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();
	if (m_bEncoded[nChNum])
	{
		SetDlgItemText(IDC_ENCODE_BTN, "Stop");
		GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(FALSE);
		GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(FALSE);
		GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(FALSE);
		GetDlgItem(IDC_SAVE_CHK)->EnableWindow(FALSE);
		GetDlgItem(IDC_FILENAME_EDIT)->EnableWindow(FALSE);
		GetDlgItem(IDC_BROWSE_BTN)->EnableWindow(FALSE);
		GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(FALSE);
		GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(FALSE);

		if (bSave[nChNum])
			((CButton*)GetDlgItem(IDC_SAVE_CHK))->SetCheck(TRUE);
		else
			((CButton*)GetDlgItem(IDC_SAVE_CHK))->SetCheck(FALSE);

		if (bPartition[nChNum])
			((CButton*)GetDlgItem(IDC_PARTITION_CHK))->SetCheck(TRUE);
		else
			((CButton*)GetDlgItem(IDC_PARTITION_CHK))->SetCheck(FALSE);
	}
	else
	{
		SetDlgItemText(IDC_ENCODE_BTN, "Encode");
		GetDlgItem(IDC_SIGNAL_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_MPEG_COMBO)->EnableWindow(TRUE);
		if (nMPEGType != 0)
			GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(TRUE);
		GetDlgItem(IDC_SAVE_CHK)->EnableWindow(TRUE);
		GetDlgItem(IDC_FILENAME_EDIT)->EnableWindow(TRUE);
		GetDlgItem(IDC_BROWSE_BTN)->EnableWindow(TRUE);

		if (((CButton*)GetDlgItem(IDC_SAVE_CHK))->GetCheck())
			GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(TRUE);
		else
			GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(FALSE);

		if (((CButton*)GetDlgItem(IDC_PARTITION_CHK))->GetCheck())
			GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(TRUE);
		else
			GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(FALSE);
	}
	
	if (m_bPreviewed[nChNum])
	{
		SetDlgItemText(IDC_PREVIEW_BTN, "Stop");
		GetDlgItem(IDC_SNAPSHOT_BTN)->EnableWindow(TRUE);
	}
	else
	{
		SetDlgItemText(IDC_PREVIEW_BTN, "Preview");
		GetDlgItem(IDC_SNAPSHOT_BTN)->EnableWindow(FALSE);
	}

	if (m_bDecoded[nChNum])
		GetDlgItem(IDC_PLAYBACK_BTN)->EnableWindow(FALSE);
	else
		GetDlgItem(IDC_PLAYBACK_BTN)->EnableWindow(TRUE);

	if (m_bDetected[nChNum])
		GetDlgItem(IDC_MOTION_BTN)->SetWindowText("Stop");
	else
		GetDlgItem(IDC_MOTION_BTN)->SetWindowText("Motion Detect");

	char sFileName[MAX_FILENAME_LEN];
	MakeFileName(nChNum, nSignalType, nMPEGType, sFileName);
//	sprintf(sFileName, "C:\\Stream%02d.mpg", nChNum+1);
	GetDlgItem(IDC_FILENAME_EDIT)->SetWindowText(sFileName);
	GetDlgItem(IDC_FILENAME_EDIT)->UpdateWindow();
}

void CDVP2420SampleDlg::OnSelchangeSignalCombo() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();
	int nSignalType = ((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->GetCurSel();
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();

	char sFileName[MAX_FILENAME_LEN];
	MakeFileName(nChNum, nSignalType, nMPEGType, sFileName);
	GetDlgItem(IDC_FILENAME_EDIT)->SetWindowText(sFileName);
	GetDlgItem(IDC_FILENAME_EDIT)->UpdateWindow();
}

void CDVP2420SampleDlg::OnSelchangeMpegCombo() 
{
	// TODO: Add your control notification handler code here
	int nChNum = ((CComboBox *)GetDlgItem(IDC_CHANNEL_COMBO))->GetCurSel();
	int nSignalType = ((CComboBox *)GetDlgItem(IDC_SIGNAL_COMBO))->GetCurSel();
	int nMPEGType = ((CComboBox *)GetDlgItem(IDC_MPEG_COMBO))->GetCurSel();

	switch (nMPEGType)
	{
		case 0:
			((CComboBox *)GetDlgItem(IDC_VIDEOSIZE_COMBO))->SetCurSel(3);
			GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(FALSE);
			GetDlgItem(IDC_DIVX_BTN)->EnableWindow(FALSE);
			break;
		case 1:
			GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(TRUE);
			GetDlgItem(IDC_DIVX_BTN)->EnableWindow(FALSE);
			break;
		case 2:
			GetDlgItem(IDC_VIDEOSIZE_COMBO)->EnableWindow(TRUE);
			GetDlgItem(IDC_DIVX_BTN)->EnableWindow(TRUE);
			break;
	}

	char sFileName[MAX_FILENAME_LEN];
	MakeFileName(nChNum, nSignalType, nMPEGType, sFileName);
	GetDlgItem(IDC_FILENAME_EDIT)->SetWindowText(sFileName);
	GetDlgItem(IDC_FILENAME_EDIT)->UpdateWindow();
}

void CDVP2420SampleDlg::OnSaveChk() 
{
	// TODO: Add your control notification handler code here
	if (((CButton*)GetDlgItem(IDC_SAVE_CHK))->GetCheck() == TRUE) {
		GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(TRUE);
	}
	else {
		((CButton*)GetDlgItem(IDC_PARTITION_CHK))->SetCheck(FALSE);
		GetDlgItem(IDC_PARTITION_CHK)->EnableWindow(FALSE);
		GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(FALSE);
	}
}

void CDVP2420SampleDlg::OnPartitionChk() 
{
	// TODO: Add your control notification handler code here
	if (((CButton*)GetDlgItem(IDC_PARTITION_CHK))->GetCheck() == TRUE)
		GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(TRUE);
	else
		GetDlgItem(IDC_SIZE_EDIT)->EnableWindow(FALSE);
}
