首页 » 技术分享 » 分享一下海康威视古老的播放器源码

分享一下海康威视古老的播放器源码

 

一切高深的技术,翻开源码顿悟:

这是海康威视SDK附带的MFC Demo,年头有些久了,不过参考价值还是很大的:

/
// PlayerDlg.h : header file
/


#if !defined(AFX_PLAYERDLG_H__BC7E7078_7E67_40B3_85A4_591E51BB1A4A__INCLUDED_)
#define AFX_PLAYERDLG_H__BC7E7078_7E67_40B3_85A4_591E51BB1A4A__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "XColorStatic.h"
#include "XScrollBar.h"
#include "VolumeCtrl.h"
#include "seek.h"
#include "displayRect.h"
#include "VideoCtrlDlg.h"
#include "WatermarkDlg.h"


//文件头标
// 海康格式封装
#define HKM4_FILE_CODE		0x484B4D34	// "HKM4" 海康文件层,M卡老版本非标准MPEG4
#define HKH4_FILE_CODE		0x484B4834	// "HKH4" 海康H.264
#define HSM4_FILE_CODE		0x48534D34	// "HSM4" 海康系统层,标准MPEG4

// MPEG2-PS
#define PSM4_FILE_CODE		0x50534D34	// "PSM4" PS系统层,标准MPEG4
#define PSH4_FILE_CODE		0x50534834	// "PSH4" PS系统层,标准H264

// MPEG2-TS
#define TSM4_FILE_CODE		0x54534D34	// "PSM4" TS系统层,标准MPEG4
#define TSH4_FILE_CODE		0x54534834	// "PSH4" TS系统层,标准H264

// RTP
#define RTM4_FILE_CODE		0x52544D34	// "RTM4" RTP封装标准MPEG4
#define RTH4_FILE_CODE		0x52544834	// "RTH4" RTP封装标准H264

// 系统封装格式	
#define SYSTEM_NULL			0x0				// 没有系统层,纯音频流或视频流	
#define SYSTEM_HIK          0x1				//add 20071218
#define SYSTEM_MPEG2_PS     0x2				//add 20071218
#define SYSTEM_MPEG2_TS     0x3				//add 20071218
#define SYSTEM_RTP          0x4				//add 20071218

// 视频编码类型
#define VIDEO_NULL          0x0 // 没有视频
#define VIDEO_H264          0x1 // 标准H.264和海康H.264都可以用这个定义
#define VIDEO_MPEG4         0x3 // 标准MPEG4

// 音频编码类型
#define AUDIO_NULL          0x0000 // 没有音频
#define AUDIO_ADPCM         0x1000 // ADPCM 
#define AUDIO_MPEG          0x2000 // MPEG 系列音频,解码器能自适应各种MPEG音频
// G系列音频
#define AUDIO_G711_U		0x7110
#define AUDIO_G711_A		0x7111
#define AUDIO_G722_1		0x7221
#define AUDIO_G723_1        0x7231
#define AUDIO_G726          0x7260
#define AUDIO_G729          0x7290

#ifndef HIK_RTP_STREAM_TYPE_DEFINITION
#define HIK_RTP_STREAM_TYPE_DEFINITION

//RTP 负载类型,与TS/PS解析系统定义相同
/* 输入流类型声明 */
#define HIK_STD_STREAM_TYPE_RTP_NULL    0x00    /* 没有RTP流      */
#define HIK_STD_STREAM_TYPE_RTP_STM     0x91    /* 未定义的其他流 */
#define HIK_STD_STREAM_TYPE_RTP_G711    0x71    /* G711 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G722    0x72    /* G722 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G723    0x73    /* G723 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G726    0x76    /* G726 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G727    0x77    /* G727 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G728    0x78    /* G728 音频流    */
#define HIK_STD_STREAM_TYPE_RTP_G729    0x79    /* G729 音频流    */

#define HIK_STD_STREAM_TYPE_RTP_M1V     0x01    /* mpeg1 视频流   */
#define HIK_STD_STREAM_TYPE_RTP_M2V     0x02    /* mpeg2 视频流   */
#define HIK_STD_STREAM_TYPE_RTP_M1A     0x03    /* mpeg1 音频流   */
#define HIK_STD_STREAM_TYPE_RTP_M2A     0x04    /* mpeg2 音频流   */
#define HIK_STD_STREAM_TYPE_RTP_M4V     0x10    /* MPEG4视频流    */
#define HIK_STD_STREAM_TYPE_RTP_264     0x1b    /* H.264视频流	  */

#endif

#define HIK_STD_STREAM_TYPE_MPG2_TS		7    	/* TS流           */
#define HIK_STD_STREAM_TYPE_MPG2_PS     8       /* PS流           */

enum _VIDEO_PLAY_STATE 
{ 
	State_Close  = 0,
	State_Play   = 1,
	State_Pause  = 2,
	State_Stop   = 3,
	State_Step   = 4
};



/
// CPlayerDlg dialog
/
class CPlayerDlg : public CDialog
{
// Construction
public:
	CPlayerDlg(CWnd* pParent = NULL);			// standard constructor

public:
	BOOL		m_bInited;

	/************************************************************************/
	/* para used to cap pic */
	UINT		m_nCapPicType;					// 0 indicates default bmp, 1 indicates jpeg
	UINT		m_npic_bmp;						// capped bmp  pic number
	UINT		m_npic_jpeg;					// capped jpeg pic number
	CString		m_strCapPicPath;				// capped pic path
	/************************************************************************/

	BOOL		m_bStartDraw;                   // start drawing?
	BOOL		m_bFileRefCreated;              // has file ref created?
	BOOL		m_bFileEnd;                     // has file played to end?
	BOOL		m_bStreamType;                  // played as stream?
	BOOL		m_bPicQuality;                  // use high picture quality?
	BOOL        m_bDeflash;	                    // set I frame deflashing?
	BOOL		m_bHighFluid;					// hight fluid motion?
	BOOL		m_bSound;                       // open the sound or not?
	BOOL		m_bOpen;                        // has file opend?
	BOOL		m_bRepeatPlay;                  // play the file rewind?
	BOOL		m_bFullScreen;                  // full screen or not?
	BOOL		m_bConvertAVI;                  // convert to AVI or not?
	
	LONG		m_nSpeed;                       // video play speed
	LONG		m_nWidth;                       // image width
	LONG		m_nHeight;                      // image height
	LONG		m_nPrePlayPos;                  // pre play slider pos
	
	DWORD		m_dwScreenHeight;               // screem height
	DWORD		m_dwScreenWidth;                // screen width	
	CRect		m_rcScreen;						// dlg in which screen now

    DWORD       m_dwSysFormat;
	DWORD		m_dwHeadSize;                   // Hikvision file header length
	DWORD		m_dwMaxFileSize;                // Hikvision file size
	DWORD		m_dwTotalFrames;                // total frames
	DWORD		m_dwMaxFileTime;                // total file time(s)
	DWORD		m_dwDisplaySecond;              // seconds displayed at the statusbar
	DWORD		m_dwDisplayMinute;              // minutes displayed at the statusbar
	DWORD		m_dwDisplayHour;                // hours   displayed at the statusbar
	DWORD		m_dwDlgTopSize;                 // dlg top  space height
	DWORD		m_dwDlgEdge;                    // dlg edge space width 
	DWORD       m_dwImageSharpenLevel;          // image sharpen level (0 ~6)
	DWORD		m_dwOldDeviceNum;				// old display device sequence

	CRect		m_rcWindow;						// window rect
	CRect		m_rcDraw;						// draw rect
	CRect		m_rcDisplay;                    // mutli display rect
	CPoint		m_StartPoint;                   // start point

	HANDLE		m_hEventKill;                   // kill inputstream thread event
	HANDLE		m_hEventInput;                  // inputstream thread event
	HANDLE		m_hThread;                      // inputstream thread handle
	HANDLE		m_hStreamFile;                  // input file

	CString		m_strPlayFileName;              // playing h264 file path
	CString     m_strSaveAVIPath;               // saveing avi  file path
	
	CBitmap		m_HikvisionBmp;                 // hikvision bmp
	CBitmap		m_BlackBmp;                     // black bmp
	CBitmap		m_OverlayBmp;                   // overlay bmp
	
	CMenu*		      m_pMainMenu;              // pointer to the menu
	CSeek*			  m_pSeek;                  // seek dialog
	CDisplayRect*     m_pDisplayRegion;         // display region dialog
	CVideoCtrlDlg*    m_pVideoControl;			// video control dialog
	WINDOWPLACEMENT   m_OldWndpl;               // save dialog window pos
	CWatermarkDlg*     m_pWatermarkDlg;			// watermark dialog
	PBYTE			  m_pQcifTempBuf;			// convert qcif to avi

	
	_VIDEO_PLAY_STATE m_enumState;              // now the play state

public:
	BOOL SetDiplayMode(int nID);
	
	HANDLE	m_hTestFile;
	//错误信息
	char* MyErrorToString(DWORD error);

	BOOL PreTranslateMessage(MSG* lpmsg);       // overload to handle keydown message

	/*************************************************************************/
	/* button operation begin
	/*************************************************************************/
	// play / pause / stop
	void  Play();
	void  Pause();
	void  Stop();

	// gotostart / slow / fast / gotoend
	void  GotoStart();
	void  Slow();
	void  Fast();
	void  AdjustSpeed(int nSpeed);
	void  GotoEnd();

	// stepback / stepfore / cap picture
	void  StepBackward();
	void  StepForward();
	void  GetPic(PBYTE pImage, DWORD nBufSize);
	void  Cappic();

	// close or open sound
	void  Sound();
	// adjust sound
	void  AdjustSound(BOOL bFlag);
	/*************************************************************************/
	/* button operation over
	/*************************************************************************/
	

	
	/*************************************************************************/
	/* menu operation begin
	/*************************************************************************/
	// file operation:
	void  Open();
	void  Close();
	void  CutFile();
	void  SetSecretKey();

	// view operation:
	void  ViewFullScreen();
	void  ViewZoom(UINT nID);
	void  Infomation();
	void  SetDisplay();
	BOOL  SetDevice(UINT nID);
	void  GetWatermark();
	
	// control operation:
	void  VideoControl();
	void  Repeat();
	void  Locate();
  
	// option operation:
	void  StreamType();
	
	void  Deflash();
	void  Quality();
	void  HighFluid();
	void  ImageSharpenLevel(UINT nID);
	void  ThrowB(UINT nID);
	void  SetDecodeType(UINT nID);
	
	void  DisplayType(UINT nID);
	void  SelectTimer(UINT nID);
	void  ResetBuf();
	
	void  CapPicType(UINT nID);
	void  CappicPath();
	
	void  ConvertToAVI();

	// help operation:
	void  AppAbout();
	void  AppHelp();
	/*************************************************************************/
	/* menu operation over
	/*************************************************************************/



	/*************************************************************************/
	/*  assistant operation begin
	/*************************************************************************/	
	// open/close file or stream
	BOOL  BrowseFile(CString *strFileName);
	void  OpenFile();
	void  CloseFile();
	void  OpenStream();
	void  CloseStream();

	// set play state
	void  DrawStatus();
	void  SetState();
	void  SetAVIState();
	DWORD GetSpeedModulus(); 
	
	// sort the dialog control
	void  SetWindowSize();
	void  SortControl();
	void  InitWindowSize(DWORD cx, DWORD cy);

	// others
	CRect GetOnPicRect(CRect rcWnd, CRect rcOnWnd, LONG nPicWidth, LONG nPicHeight);	
	void  TestCapability(DWORD nDeviceNum);
	void  SetDisplayRegion(RECT);

	/*************************************************************************/
	/*  assistant operation over
	/*************************************************************************/


// Dialog Data
	//{{AFX_DATA(CPlayerDlg)
	enum { IDD = IDD_PLAYER_DIALOG };
	CButtonST		m_ctrlBtnCapPic;
	CButtonST		m_ctrlBtnSound;
	CButtonST		m_ctrlStepBackward;
	CButtonST		m_ctrlStepForward;
	CButtonST		m_ctrlBtnSlow;
	CButtonST		m_ctrlBtnFast;
	CButtonST		m_ctrlBtnGStart;
	CButtonST		m_ctrlBtnGEnd;
	CButtonST		m_ctrlBtnStop;
	CButtonST		m_ctrlBtnPlay;
	CButtonST		m_ctrlBtnPause;
	CStatic			m_ctrlVideoPic;
	CString			m_strPlayStateText;
	CXColorStatic	m_ctrlPlayText;
	//}}AFX_DATA
	CVolumeCtrl		m_SoundSlider;
	CXScrollBar		m_PlaySlider;
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CPlayerDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	HICON m_hIcon;


	// Generated message map functions
	//{{AFX_MSG(CPlayerDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnClose();
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnDropFiles(HDROP hDropInfo);
	afx_msg void OnMove(int x, int y);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
	afx_msg void OnDestroy();
	//}}AFX_MSG
	afx_msg LRESULT DisplayOk(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT WatermarkOk(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT SeekOk(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT VideoCtrlOK(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT PlayMessage(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT EncChangeMessage(WPARAM wParam, LPARAM lParam);
	afx_msg void OnMenuItem(UINT nID);
	afx_msg void OnButtonItem(UINT nID);
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_PLAYERDLG_H__BC7E7078_7E67_40B3_85A4_591E51BB1A4A__INCLUDED_)

熟悉MFC的小伙伴应该很懂:


//File:PlayerDlg.cpp 
/
#include "stdafx.h"
#include "Player.h"
#include "PlayerDlg.h"
#include "vkey.h"
#include "info.h"
#include "cutfile.h"
#include "HelpDlg.h"
#include "CConvertAVI.h"
#include "watermarkinfo.h"
#include "SetKeyDlg.h"
#include <stdio.h>

#define GET_YEAR(_time_)      (((_time_)>>26) + 2000) 
#define GET_MONTH(_time_)     (((_time_)>>22) & 15)   
#define GET_DAY(_time_)       (((_time_)>>17) & 31)   
#define GET_HOUR(_time_)      (((_time_)>>12) & 31)   
#define GET_MINUTE(_time_)    (((_time_)>>6)  & 63)
#define GET_SECOND(_time_)    (((_time_)>>0)  & 63)   
void RunInfo(char *szFormat, ...)
{	
	char szInfo[512];
	va_list	ArgumentList;
	
	va_start(ArgumentList, szFormat); 
	vsprintf(szInfo, szFormat, ArgumentList);
	va_end(ArgumentList);
	OutputDebugString(szInfo);
}
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


// class used to convert file to avi
CConvertAVI g_classAVI;

/************************************************************************/				
UINT	WM_FILE_END			= WM_USER +33;	 // User message. Be posted when the file is end.
UINT	WM_ENC_CHANGE		= WM_USER +100;  // User message. Be posted when the image size is changed.
UINT	PLAY_TIMER			= 1;			 // TIMER ID;
//UINT	m_lPort				= 0;			 // uesed port;can be from 0 to 15;
/************************************************************************/
LONG	m_lPort = -1;
WATERMARK_VER1_INFO m_strWaterMark;

/
// 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)
	virtual BOOL OnInitDialog();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

BOOL CAboutDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	// display the version information
	CString strVer;

	//海康解码SDK信息
	DWORD dwVer	   = NAME(PlayM4_GetSdkVersion)();
	DWORD dwVersion = dwVer & 0x0000ffff;
	DWORD dwBuild   = (dwVer >> 16) & 0x0000ffff;
#ifdef _FOR_HIKPLAYM4_DLL_
	strVer.Format("HikPlayer ver is %.1f\n\rHikPlayM4.dll ver is %04x build is %04x", APP_VERSION, dwVersion, dwBuild);
#else
	strVer.Format("Player ver is %.1f\n\rPlayM4.dll ver is %04x build is %04x", APP_VERSION, dwVersion, dwBuild);
#endif
	GetDlgItem(IDC_VER)->SetWindowText(strVer);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CPlayerDlg dialog

CPlayerDlg::CPlayerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPlayerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPlayerDlg)
	m_strPlayStateText       = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon	                  =	AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_hTestFile				  = INVALID_HANDLE_VALUE;	
	m_bInited				  = FALSE;
}

void CPlayerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPlayerDlg)
	DDX_Control(pDX, IDC_PLAYSTATETEXT, m_ctrlPlayText);
	DDX_Control(pDX, IDC_CAPPIC, m_ctrlBtnCapPic);
	DDX_Control(pDX, IDC_SOUND, m_ctrlBtnSound);
	DDX_Control(pDX, IDC_STEPBACK, m_ctrlStepBackward);
	DDX_Control(pDX, IDC_STEP, m_ctrlStepForward);
	DDX_Control(pDX, IDC_SLOW, m_ctrlBtnSlow);
	DDX_Control(pDX, IDC_FAST, m_ctrlBtnFast);
	DDX_Control(pDX, IDC_GOTOSTART, m_ctrlBtnGStart);
	DDX_Control(pDX, IDC_GOTOEND, m_ctrlBtnGEnd);
	DDX_Control(pDX, IDC_STOP, m_ctrlBtnStop);
	DDX_Control(pDX, IDC_PLAY, m_ctrlBtnPlay);
	DDX_Control(pDX, IDC_PAUSE, m_ctrlBtnPause);
	DDX_Control(pDX, IDC_SHOW, m_ctrlVideoPic);
	DDX_Text(pDX, IDC_PLAYSTATETEXT, m_strPlayStateText);
	DDX_Control(pDX, IDC_SOUND_SLIDER, m_SoundSlider);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPlayerDlg, CDialog)
	//{{AFX_MSG_MAP(CPlayerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_KEYDOWN()
	ON_WM_HSCROLL()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CLOSE()
	ON_WM_TIMER()
	ON_WM_SIZE()
	ON_WM_DROPFILES()
	ON_WM_MOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_GETMINMAXINFO()
	ON_WM_DESTROY()
	ON_WM_WINDOWPOSCHANGED()
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(IDM_VIEW_FULLSCREEN, IDM_BYTIME, OnMenuItem)
	ON_COMMAND_RANGE(IDC_PLAY, IDC_SOUND, OnButtonItem)
	ON_MESSAGE(WM_FILE_END, PlayMessage)
	ON_MESSAGE(WM_ENC_CHANGE,EncChangeMessage)
	ON_MESSAGE(WM_SEEKOK, SeekOk)
	ON_MESSAGE(WM_DISPLAY_OK, DisplayOk)
	ON_MESSAGE(WM_VIDEOCTRL_OK, VideoCtrlOK)
	ON_MESSAGE(WM_WATERMARK_OK, WatermarkOk)
	
END_MESSAGE_MAP()

/
// CPlayerDlg message handlers

BOOL CPlayerDlg::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
	m_pMainMenu = GetMenu();
	if(m_pMainMenu == NULL)
	{
		TRACE("GetMenu is Error!");
		return FALSE;
	}

	m_dwScreenWidth  = GetSystemMetrics(SM_CXSCREEN);
	m_dwScreenHeight = GetSystemMetrics(SM_CYSCREEN);

	m_rcScreen.left  = 0;
	m_rcScreen.right = m_dwScreenWidth;
	m_rcScreen.top   = 0;
	m_rcScreen.bottom= m_dwScreenHeight;

#if (WINVER > 0x0400)
	// If do not support multi monitor,may not call!
	HMONITOR hMonitor;
	char chDriverDesp[50];
	char chDriverName[50];

	NAME(PlayM4_InitDDrawDevice)();//初始化绘图设备!!!
	DWORD nVal=NAME(PlayM4_GetDDrawDeviceTotalNums)();
	if(nVal > 1)
	{
		nVal = min(nVal, MAX_DISPLAY_DEVICE);
		for(DWORD nCount = 0; nCount < nVal; nCount++) 
		{
			ZeroMemory(chDriverDesp, 50);
			NAME(PlayM4_GetDDrawDeviceInfo)(nCount, chDriverDesp, 50, chDriverName, 50, &hMonitor);
			m_pMainMenu->GetSubMenu(1)->InsertMenu(IDM_TEMP_DEVICE, MF_BYCOMMAND, IDM_DEVICE0 + nCount + 1, chDriverDesp);
		}
	}
	else
	{
		ZeroMemory(chDriverDesp, 50);
		NAME(PlayM4_GetDDrawDeviceInfo)(0, chDriverDesp, 50, chDriverName, 50, &hMonitor);
		m_pMainMenu->GetSubMenu(1)->InsertMenu(IDM_TEMP_DEVICE, MF_BYCOMMAND, IDM_DEVICE0, chDriverDesp);
	}

	m_pMainMenu->GetSubMenu(1)->RemoveMenu(IDM_TEMP_DEVICE, MF_BYCOMMAND);
	m_pMainMenu->CheckMenuItem(IDM_DEVICE0, MF_CHECKED);
	
	TestCapability(0);//测试本地PC的能力
#endif

	
	// Init Play Slider
	VERIFY(m_PlaySlider.CreateFromStatic(
		   SBS_HORZ|WS_CHILD|SS_LEFT|SS_NOTIFY|WS_VISIBLE,
		   this, IDC_PLAY_RECT_SLIDER, IDC_PLAY_SLIDER));

	m_PlaySlider.SetScrollRange(0, PLAYER_SLIDER_MAX);
	m_PlaySlider.EnableThumbColor(FALSE);
	m_PlaySlider.EnableThumbGripper(TRUE);
	m_PlaySlider.EnableChannelColor(FALSE);

	NAME(PlayM4_GetPort)(&m_lPort);//获取解码通道
	
	// Init Sound Slider
#ifdef _WAVE_ADJ
	m_SoundSlider.SetRangeMin(MIN_WAVE_COEF);
	m_SoundSlider.SetRangeMax(MAX_WAVE_COEF);
#else
	m_SoundSlider.SetRangeMin(0);
	m_SoundSlider.SetRangeMax(0xffff-1);
#endif

	m_SoundSlider.SetLineSize(1);
	m_SoundSlider.SetPageSize(5);

// 	

	// Init the parameters
	m_StartPoint.x		 =	0;
	m_StartPoint.y		 =	0;
	m_dwTotalFrames		 =	0;
	m_dwMaxFileTime		 =	0;
	m_dwDisplayHour		 =	0;
	m_dwDisplayMinute	 =	0;
	m_dwDisplaySecond	 =	0;
	m_dwImageSharpenLevel=  0;
	m_nPrePlayPos		 =  0;
	m_dwOldDeviceNum     =  0;

	m_npic_bmp			 =	0;
	m_npic_jpeg			 =	0;
	m_nCapPicType		 =	0;
	m_strCapPicPath		 =  _T("");

	m_bStartDraw         =	FALSE;
	m_bSound			 =	FALSE;
	m_bOpen			     =	FALSE;
	m_bFullScreen		 =	FALSE;
	m_bRepeatPlay		 =	FALSE;
	m_bStreamType		 =	FALSE;
	m_bConvertAVI		 =  FALSE;
	m_bPicQuality	     =  TRUE;
	m_bDeflash			 =  TRUE;
#ifdef _HIGH_FRUID
	m_bHighFluid		 =  TRUE;
#else
	m_bHighFluid		 =  FALSE;
#endif

	m_bFileRefCreated	 =  FALSE;

	m_strPlayStateText	 =	_T("Ready");
	m_ctrlPlayText.ShowText(m_strPlayStateText);
	m_strSaveAVIPath	 =  _T("");
	
	m_pQcifTempBuf		 =  NULL;

	// Init state text control
	m_ctrlPlayText.SetTextColor(RGB(255,255,255), FALSE);
	m_ctrlPlayText.SetBackgroundColor(RGB(0,0,0), FALSE);
	m_ctrlPlayText.SetBold(TRUE, FALSE);

	m_nWidth	= 352;
	m_nHeight   = 288;

	// init the sub dialogs
	m_pSeek				 =	new CSeek(this);
	m_pDisplayRegion	 =	new CDisplayRect(this);
	m_pVideoControl		 =  new CVideoCtrlDlg(this);

	// bitmap
	m_BlackBmp.LoadBitmap(IDB_BLACK);
	m_OverlayBmp.LoadBitmap(IDB_OVERLAY);
#ifdef _FOR_HIKPLAYM4_DLL_
	m_HikvisionBmp.LoadBitmap(IDB_HIKVISION);
	SetWindowText("Hikvision Player");
#else
	m_HikvisionBmp.LoadBitmap(IDB_BLACK);
	SetWindowText("Player");
#endif

	// init sub dlg
	m_pWatermarkDlg	     =  new CWatermarkDlg(this);
	
	// init state
	m_enumState = State_Close;
	SetState();

	// set the capture picture call back function; //这里设置音视频解码回调
//	NAME(PlayM4_SetDisplayCallBack)(m_lPort, DisplayCBFun);
	// set the wave audio call back funtion;
//	NAME(PlayM4_SetAudioCallBack)(m_lPort, WaveCBFun, (long)this);


	NAME(PlayM4_SetDDrawDevice)(m_lPort,0);//绑定解码通道到绘图设备
	// Test adapter Capability;

	
	// used for command line
	if(m_strPlayFileName.Compare(""))
	{
		Open();
		SetState();
	}

	UpdateData(FALSE);
	SortControl();
	NAME(PlayM4_SetVolume)(m_lPort,WORD(m_SoundSlider.GetPos()));//音量设备
	m_bInited = TRUE;

	return TRUE;  // return TRUE  unless you set the focus to a control
}


void CPlayerDlg::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 CPlayerDlg::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();
	}
	this->UpdateWindow();
	
	//刷新绘图画面
	NAME(PlayM4_RefreshPlay)(m_lPort);
	NAME(PlayM4_RefreshPlayEx)(m_lPort,0);
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPlayerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//
//Function: called when u drag a file to the playing window
//
void CPlayerDlg::OnDropFiles(HDROP hDropInfo) 
{
	// TODO: Add your message handler code here and/or call default
	
	DWORD nFileNameSize = DragQueryFile(hDropInfo, 0, NULL, 0);
	char * sFileName	= new char[nFileNameSize + 1];
	DragQueryFile(hDropInfo, 0, sFileName, nFileNameSize + 1);
	m_strPlayFileName   = sFileName;
	
	Open();
	SetState();

	delete []sFileName;
	CDialog::OnDropFiles(hDropInfo);
}


//
//Function: overload to handle keydown message
//
BOOL CPlayerDlg::PreTranslateMessage(MSG* lpmsg)
{
	
	switch (lpmsg->message)
	{
	case WM_KEYDOWN:
		OnKeyDown(lpmsg->wParam, LOWORD(lpmsg ->lParam), HIWORD(lpmsg->lParam));
		return TRUE;
		
	default:
		break;
	} 

	return CDialog::PreTranslateMessage(lpmsg); 
}


//
//Function: hot key
//
void CPlayerDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	UINT  nMenuState;

	if(nChar == VK_F2) 
		ViewFullScreen();


	if(GetKeyState(VK_CONTROL) & 0xFF00)
	{
		switch(nChar)
		{
		case VK_C:
			if(!m_bFullScreen)
			{
				nMenuState = m_pMainMenu->GetMenuState(IDM_FILE_CLOSE, MF_BYCOMMAND);
				if(nMenuState != MF_GRAYED)
				{
					Close();
					SetState();
				}
			}
			break;

		case VK_O:
			if(!m_bFullScreen)
			{
				nMenuState = m_pMainMenu->GetMenuState(IDM_FILE_OPEN, MF_BYCOMMAND);
				if(nMenuState != MF_GRAYED)		
				{
					if(BrowseFile(&m_strPlayFileName))
					{
						Open();
						SetState();
					}
				}
			}
			break;
		
		case VK_K:
			if (MF_GRAYED != m_pMainMenu->GetMenuState(IDM_SET_KEY, MF_BYCOMMAND))
			{
				SetSecretKey();
			}
			break;

/*		case VK_T:
			nMenuState = m_pMainMenu->GetMenuState(IDM_CUT_FILE, MF_BYCOMMAND);
			if(nMenuState != MF_GRAYED)
			{
				CutFile();
			}
			break;
*/
		case VK_L:
			Locate();
			break;

		case VK_LEFT:
			GotoStart();
			break;

		case VK_RIGHT:
			GotoEnd();
			break;
		
		case VK_ONE:
			if(m_enumState != State_Stop)
			{
				ViewZoom(IDM_VIEW_ZOOM_50);
			}
			break;

		case VK_TWO:
			if(m_enumState != State_Stop)
			{
				ViewZoom(IDM_VIEW_ZOOM_100);
			}
			break;

		case VK_THREE:
			if(m_enumState != State_Stop)
			{
				ViewZoom(IDM_VIEW_ZOOM_200);
			}
			break;

		default:
			break;
		}
	}

	else
	{
		switch(nChar)
		{
		case VK_ESCAPE:
			if(m_bFullScreen)
			{
				ViewFullScreen();
			}
			break;

		case VK_SPACE:
			if(m_enumState == State_Play)
			{
				Pause();
				SetState();
			}
			else if(m_enumState == State_Pause || m_enumState == State_Stop)
			{
				Play();
				SetState();
			}
			break;
		
		case VK_LEFT:
			if(m_enumState != State_Stop)
			{
				StepBackward();
				SetState();
			}
			break;

		case VK_RIGHT:
			if(m_enumState != State_Stop)
			{
				StepForward();
				SetState();
			}
			break;

		case VK_UP:
			AdjustSound(TRUE);
			break;

		case VK_DOWN:
			AdjustSound(FALSE);
			break;
		
		case VK_DOT:
			if(m_enumState != State_Close)
			{
				if(m_bFullScreen)
				{
					ViewFullScreen();
				}
				
				Stop();
				SetState();
			}
			break;

		default:
			break;
		}
	}

	CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}

///
//Function: Voluem and progress.
///
void CPlayerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	DWORD nTime;
	int   nPlayPos;
	switch(GetWindowLong(pScrollBar->m_hWnd, GWL_ID))
	{
	/
	//progress slider
	case IDC_PLAY_SLIDER:
		if(m_bStreamType)
		{
			break;
		}
		nPlayPos = m_PlaySlider.GetScrollPos();
		if( abs(nPlayPos - m_nPrePlayPos) < 3 )
		{
			break;
		}

#ifdef _FILE_POS
		NAME(PlayM4_SetPlayPos)(m_lPort, (float)nPlayPos/(float)PLAYER_SLIDER_MAX);
#else
 		nTime = nPlayPos * 1000 / PLAYER_SLIDER_MAX * m_dwMaxFileTime;
 		NAME(PlayM4_SetPlayedTimeEx)(m_lPort,nTime);
#endif
//		DrawStatus();
		break;

	///
	//sound slider;
	case IDC_SOUND_SLIDER:
#ifdef _WAVE_ADJ
		NAME(PlayM4_AdjustWaveAudio)(m_lPort, m_SoundSlider.GetPos());
#else
		NAME(PlayM4_SetVolume)(m_lPort, WORD(m_SoundSlider.GetPos()));
#endif
		break;

	default:
		break;
	}
	
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

/
//Called when u double click the left button
/
void CPlayerDlg::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CPoint dpoint;
	CRect  vwrect;
	GetCursorPos(&dpoint);	

	m_ctrlVideoPic.GetWindowRect(&vwrect);
	if( ( m_enumState == State_Play || m_enumState == State_Pause) && vwrect.PtInRect(dpoint))
	{
		ViewFullScreen();
	}
		
	CDialog::OnLButtonDblClk(nFlags, point);
}


/
//Timer funtion
/
void CPlayerDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if(nIDEvent==PLAY_TIMER)
	{
		DrawStatus();
	}
	CDialog::OnTimer(nIDEvent);
}




/
//Adjust control allign function
/
void CPlayerDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	// TODO: Add your message handler code here

	if(m_ctrlVideoPic.GetSafeHwnd())
	{
		SortControl();
	}
}


/
// Function: Limit the window size.
/
void CPlayerDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
{
	// TODO: Add your message handler code here and/or call default
	lpMMI->ptMinTrackSize.x = WIDTH/2 + m_dwDlgEdge * 2;				// width
	lpMMI->ptMinTrackSize.y = PANNEL_HEIGHT + m_dwDlgTopSize ;			// height

	CDialog::OnGetMinMaxInfo(lpMMI);
}


///
//Function:Redraw the image when move window.
///
void CPlayerDlg::OnMove(int x, int y) 
{
	CDialog::OnMove(x, y);
	
	if (!m_bInited)
	{
		return;
	}
	// TODO: Add your message handler code here
	NAME(PlayM4_RefreshPlay)(m_lPort);

	GetWindowRect(&m_rcWindow);
	DWORD dwNewDeviceNum;

	if(m_rcWindow.left < 0)
	{
		return;
	}
	
	if( (DWORD)m_rcWindow.right + (DWORD)m_rcWindow.left > 2 * m_dwScreenWidth )
	{
		if( (DWORD)m_rcWindow.top + (DWORD)m_rcWindow.bottom > 2 * m_dwScreenHeight)
		{
			dwNewDeviceNum = 3;
			m_rcScreen.left  = m_dwScreenWidth;
			m_rcScreen.right = m_dwScreenWidth  * 2;
			m_rcScreen.top   = m_dwScreenHeight;
			m_rcScreen.bottom= m_dwScreenHeight * 2;
		}
		else
		{
			dwNewDeviceNum = 1;
			m_rcScreen.left  = m_dwScreenWidth;
			m_rcScreen.right = m_dwScreenWidth  * 2;
			m_rcScreen.top   = 0;
			m_rcScreen.bottom= m_dwScreenHeight;
		}
	}
	else
	{
		if( (DWORD)m_rcWindow.top + (DWORD)m_rcWindow.bottom > 2 * m_dwScreenHeight)
		{
			dwNewDeviceNum = 2;
			m_rcScreen.left  = 0;
			m_rcScreen.right = m_dwScreenWidth;
			m_rcScreen.top   = m_dwScreenHeight;
			m_rcScreen.bottom= m_dwScreenHeight * 2;
		}
		else
		{
			dwNewDeviceNum = 0;
			m_rcScreen.left  = 0;
			m_rcScreen.right = m_dwScreenWidth;
			m_rcScreen.top   = 0;
			m_rcScreen.bottom= m_dwScreenHeight;
		}
	}
	
	if(dwNewDeviceNum != m_dwOldDeviceNum)
	{
		if(SetDevice(IDM_DEVICE0 + dwNewDeviceNum))
		{
			m_dwOldDeviceNum = dwNewDeviceNum;
		}
	}
}



///
//Function: Called when u click the left mouse button
///
void CPlayerDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
//	CRect rcShow;
//	m_ctrlVideoPic.GetWindowRect(rcShow);
//	ScreenToClient(rcShow);
//
//	if(rcShow.PtInRect(point))
//	{
//		m_StartPoint = point;
//		m_bStartDraw = TRUE;
//		InvalidateRect(m_rcDraw, TRUE);
//		ZeroMemory(&m_rcDraw, sizeof(m_rcDraw));
//	}

	CDialog::OnLButtonDown(nFlags, point);
}

void CPlayerDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
//	if(m_bStartDraw)
//	{
//		if(m_StartPoint != point)
//		{
//
//			CRect rcShow;
//			m_ctrlVideoPic.GetWindowRect(rcShow);
//			ScreenToClient(rcShow);
//			
//			if( rcShow.PtInRect(point) && (point.x >= m_StartPoint.x) && (point.y >= m_StartPoint.y))
//			{
//				m_rcDraw.left   = m_StartPoint.x;
//				m_rcDraw.top    = m_StartPoint.y;
//				m_rcDraw.right  = point.x;
//				m_rcDraw.bottom = point.y;
//				
//				CDC* pDC = GetDC();
//				pDC->DrawFocusRect(m_rcDraw);
//				ReleaseDC(pDC);
//			
//				LONG nPicWidth  = 352;
//				LONG nPicHeight = 288;
//				NAME(PlayM4_GetPictureSize)(m_lPort, &nPicWidth, &nPicHeight);
//				m_rcDisplay = GetOnPicRect(rcShow, m_rcDraw, nPicWidth, nPicHeight);
//
//				if(m_pDisplayRegion->m_hWnd)
//					m_pDisplayRegion->PostMessage(WM_DISPLAY_RECT, 0, (long)(&m_rcDisplay));
//			}
//
//		}
//		m_bStartDraw = FALSE;
//	}
	
	CDialog::OnLButtonUp(nFlags, point);
}


//
//Function: Close.
//
void CPlayerDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	NAME(PlayM4_Stop)(m_lPort);
	NAME(PlayM4_CloseFile)(m_lPort);
	NAME(PlayM4_RealeseDDraw)();

#if (WINVER > 0x0400)
	NAME(PlayM4_ReleaseDDrawDevice)();
#endif
	
	if(m_pSeek != NULL)
	{
		m_pSeek->DestroyWindow();
		delete m_pSeek;
		m_pSeek = NULL;
	}

	if(m_pDisplayRegion != NULL)
	{
		m_pDisplayRegion->DestroyWindow();
		delete m_pDisplayRegion;
		m_pDisplayRegion = NULL;
	}

	if(m_pVideoControl != NULL)
	{
		m_pVideoControl->DestroyWindow();
		delete m_pVideoControl;
		m_pVideoControl = NULL;
	}

	if(m_bConvertAVI)
	{
		g_classAVI.ReleaseResource();
		m_bConvertAVI = FALSE;
	}

	if(m_pWatermarkDlg != NULL)
	{
		m_pWatermarkDlg->DestroyWindow();
		delete m_pWatermarkDlg;
		m_pWatermarkDlg = NULL;
	}
	
	NAME(PlayM4_FreePort)(m_lPort);
	CDialog::OnClose();
}


/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  user defined message handle begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

// Function: process the received WM_FILE_END message.
// Para: wParam channel No. lParam reserved;
LRESULT CPlayerDlg::PlayMessage(WPARAM /*wParam*/, LPARAM lParam)
{
//	if(m_bFullScreen)
//		ViewFullScreen();
	
	//remove the same message.
	MSG msgVal;
	while(PeekMessage(&msgVal, m_hWnd, WM_FILE_END, WM_FILE_END, PM_REMOVE));
	
	if(m_bRepeatPlay)
	{
		TRACE("wptest:Process message %d\n", lParam);
		GotoStart();
	}
	
	if(m_bConvertAVI)
	{  
		Stop();
		SetState();
	}

	return S_OK;
}

// when enc changed got this message
LRESULT CPlayerDlg::EncChangeMessage(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	OutputDebugString("Get Message/n!");
	MSG msgVal;
	while(PeekMessage(&msgVal,m_hWnd,WM_ENC_CHANGE,WM_ENC_CHANGE,PM_REMOVE));

	if(m_bFullScreen)
	{
		ViewFullScreen();
	}

	SetWindowSize();
	
	if(m_pDisplayRegion)
	{
		if(m_pDisplayRegion->m_bValid)
		{
			m_pDisplayRegion->SetResolution(m_nHeight, m_nWidth);
			m_pDisplayRegion->InitShow();
			
			if(m_enumState == State_Pause)
			{
				NAME(PlayM4_OneByOne)(m_lPort);
			}
		}
	}

	Sleep(1);

	return S_OK;
}

LRESULT CPlayerDlg::VideoCtrlOK(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	m_pVideoControl->DestroyWindow();
	if(m_enumState == State_Pause || m_enumState == State_Play)
	{
		m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_ENABLED);
	}

	return S_OK;
}

// when u click the OK button on the seeking dialog, got this message
LRESULT CPlayerDlg::SeekOk(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	m_pSeek->DestroyWindow();
	if(m_enumState == State_Pause || m_enumState == State_Play)
	{
		m_pMainMenu->EnableMenuItem(IDM_SEEK,MF_ENABLED);
	}

	return S_OK;
}

// when u click the OK button on the display dialog, got this message
LRESULT CPlayerDlg::DisplayOk(WPARAM wParam, LPARAM /*lParam*/)
{
	if (wParam == 0) 
	{
		m_ctrlBtnCapPic.EnableWindow(TRUE);
		m_ctrlBtnSound.EnableWindow(TRUE);	
		m_ctrlBtnSlow.EnableWindow(TRUE);
		m_ctrlBtnFast.EnableWindow(TRUE);
		m_ctrlBtnGStart.EnableWindow(TRUE);
		m_ctrlBtnGEnd.EnableWindow(TRUE);
		m_ctrlBtnStop.EnableWindow(TRUE);
		m_ctrlBtnPlay.EnableWindow(TRUE);
		m_ctrlBtnPause.EnableWindow(TRUE);	
		m_ctrlStepBackward.EnableWindow(TRUE);
		m_ctrlStepForward.EnableWindow(TRUE);
 		m_pMainMenu->EnableMenuItem(2, MF_ENABLED|MF_BYPOSITION);
		Play();
		SetState();
	}
	if (wParam == 1) 
	{
		Pause();
		SetState();
	}

	return S_OK;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  user defined message handle over
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

void CALLBACK DecryptWatermark(LONG nPort, BYTE* pData, DWORD dwDataLen, DWORD dwUser)
{
	UNREFERENCED_PARAMETER(nPort);

	char* pBuf = (char*)pData;
	m_strWaterMark.global_time = *(DWORD*)pBuf;
	pBuf += sizeof(DWORD);
	m_strWaterMark.device_sn = *(DWORD*)pBuf;
	pBuf += sizeof(DWORD);
	for(int i = 0; i < 6; i ++)
	{
		m_strWaterMark.mac_addr[i] = *(unsigned char*)pBuf;
		pBuf += sizeof(unsigned char);
	}

	m_strWaterMark.device_type = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
	m_strWaterMark.device_info = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
	m_strWaterMark.channel_num = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
}

// Functon:Watermark call back function.
void CALLBACK funCheckWatermark(long /*nPort*/, WATERMARK_INFO *pFrameType, DWORD /*nUser*/)
{
//	CPlayerDlg* pOwner = (CPlayerDlg*)nUser;

	char* pBuf = (char*)pFrameType->pDataBuf;
	m_strWaterMark.global_time = *(DWORD*)pBuf;
	pBuf += sizeof(DWORD);
	m_strWaterMark.device_sn = *(DWORD*)pBuf;
	pBuf += sizeof(DWORD);
	for(int i = 0; i < 6; i ++)
	{
		m_strWaterMark.mac_addr[i] = *(unsigned char*)pBuf;
		pBuf += sizeof(unsigned char);
	}

	m_strWaterMark.device_type = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
	m_strWaterMark.device_info = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
	m_strWaterMark.channel_num = *(unsigned char*)pBuf;
	pBuf += sizeof(unsigned char);
}

/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  callback function begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/	

// Function:The call back funtion for capture image!
void CALLBACK DisplayCBFun(long /*nPort*/,\
						   char * pBuf,long /*nSize*/,\
						   long /*nWidth*/,long /*nHeight*/,\
						   long /*nStamp*/,long /*nType*/,long /*nReceaved*/)
{
	UNREFERENCED_PARAMETER(pBuf);
}

// Function: The dec call back funtion.
void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,
					   FRAME_INFO * pFrameInfo, 
					   long nReserved1,long /*nReserved2*/)
{
//	OutputDebugString("解码回调");
//	DWORD dwTime = PlayM4_GetSpecialData(nPort);
	TRACE("nPort=%d, TYPE=%d; Width=%d; Height=%d\n", nPort, pFrameInfo->nType, pFrameInfo->nWidth, pFrameInfo->nHeight);
//	TRACE("wptest==============Time: Year is %d, Month is %d, Day is %d, Hour is %d, %d, %d", GET_YEAR(dwTime),
//			GET_MONTH(dwTime), GET_DAY(dwTime), GET_HOUR(dwTime), GET_MINUTE(dwTime), GET_SECOND(dwTime));
/*	
	CPlayerDlg* pDlg = (CPlayerDlg *)nReserved1;

	if ( pFrameInfo->nType == T_YV12 ) 
	{   
		if(g_classAVI.IsWriteAVIHdr())
		{
			g_classAVI.SetFPS(pFrameInfo->nFrameRate);
			g_classAVI.WriteHeaders();
		}

		// ntsc qcif
		if(pFrameInfo->nHeight == 128)
		{
			if(pDlg->m_pQcifTempBuf == NULL)
			{
				pDlg->m_pQcifTempBuf = new BYTE[nSize];
			}
		
			int nPos = 0;		
			// Y 分量
			for(int i = 0; i < 4; i++)
			{
				CopyMemory(pDlg->m_pQcifTempBuf + i * pFrameInfo->nWidth, pBuf, pFrameInfo->nWidth);
			}

			CopyMemory(pDlg->m_pQcifTempBuf + 4 * pFrameInfo->nWidth, pBuf, pFrameInfo->nWidth * 120);
			for(i = 0; i < 4; i++)
			{
				CopyMemory(pDlg->m_pQcifTempBuf + (124 + i) * pFrameInfo->nWidth, pBuf + pFrameInfo->nWidth * 119, pFrameInfo->nWidth);
			}

			nPos += nSize*2/3;
			
			int w = pFrameInfo->nWidth/2; 
			// U/V分量
			for(int j = 0; j < 2; j++)
			{
				for(i = 0; i < 2; i++)
				{
					CopyMemory(pDlg->m_pQcifTempBuf + i * w + nPos,  pBuf + nPos, w);
				}
				CopyMemory(pDlg->m_pQcifTempBuf + w * 2 + nPos, pBuf + nPos, w * 60);
				for(i = 0; i < 2; i++)
				{
					CopyMemory(pDlg->m_pQcifTempBuf + w * (62 + i) + nPos, pBuf + w * 59 + nPos, w);
				}
				nPos += nSize*1/6;
			}

			g_classAVI.AddFileToAVI((char*)pDlg->m_pQcifTempBuf, nSize);
		}
		else
		{		
			g_classAVI.AddFileToAVI(pBuf, nSize);
		}

		if(g_classAVI.IsExceedMaxFileLen())
		{
			SendMessage(AfxGetApp()->GetMainWnd()->m_hWnd,WM_FILE_END,m_lPort,0);		   
		}	
	}
*/
//	Sleep(1);
}

// Funtion:The source buffer call back funtion.
void CALLBACK SourceBufFun(long nPort,DWORD nBufSize,DWORD dwUser,void*pContext)
{
	UNREFERENCED_PARAMETER(pContext);

	CPlayerDlg* pOwner = (CPlayerDlg*)dwUser;

	if( (pOwner->m_enumState == State_Close) || (pOwner->m_enumState == State_Stop) )
	{
		return ;
	}
	NAME(PlayM4_ResetSourceBufFlag)(nPort);
	if(pOwner->m_bFileEnd)
	{
		
		PostMessage(pOwner->m_hWnd, WM_FILE_END, m_lPort, 0);
		pOwner->m_bFileEnd = FALSE;
	}
	else
	{
		SetEvent(pOwner->m_hEventInput);
	}
}

// Functon:File reference call back function.
void CALLBACK FileRefDone(DWORD /*nReserved*/,DWORD nUser)
{
 	CPlayerDlg* pOwner = (CPlayerDlg*)nUser;
 	pOwner->m_bFileRefCreated = TRUE;
 //	pOwner->m_pMainMenu->EnableMenuItem(IDM_CUT_FILE,MF_ENABLED);
 	pOwner->m_pMainMenu->EnableMenuItem(IDM_SEEK,MF_ENABLED);
	TRACE("File reference created!\n");

//	DWORD dwIndex = 0;
//	NAME(PlayM4_GetRefValue)(m_lPort, NULL, &dwIndex);
//	BYTE* pIndex = new BYTE[dwIndex];
//	NAME(PlayM4_GetRefValue)(m_lPort, pIndex, &dwIndex);
//	HANDLE hFile = CreateFile("D:\\new.idx", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//	DWORD dw;
//	WriteFile(hFile, pIndex, dwIndex, &dw, NULL);
}

// Functon:File Verify call back function.
/*
void CALLBACK VerifyFun(long nPort, FRAME_POS * pFilePos, DWORD bIsVideo,  DWORD nUser)
{
//	TRACE("File have been changed at: pos = 0x%X; time(s) = %d, frameNum = %d; IsVideo = %d\n",
//		pFilePos->nFilePos, pFilePos->nFrameTime/1000, pFilePos->nFrameNum, bIsVideo);
	CString abstime;
	CString str;
	if (pFilePos->pErrorTime )
	{
		abstime.Format("%02d-%02d-%02d %02d:%02d:%02d",pFilePos->pErrorTime->wYear, pFilePos->pErrorTime->wMonth,
			pFilePos->pErrorTime->wDay, pFilePos->pErrorTime->wHour, pFilePos->pErrorTime->wMinute, pFilePos->pErrorTime->wSecond);
	}
	str.Format("file error at pos=0x%X, time(s) =%d,frameNum=%d,isVideo=%d, \
		errorframe at%d,lostframe=%d,lostdata=%d,time=%s\n",	\
		pFilePos->nFilePos, pFilePos->nFrameTime/1000, pFilePos->nFrameNum, bIsVideo,	\
		pFilePos->nErrorFrameNum, pFilePos->nErrorLostFrameNum, pFilePos->nErrorFrameSize, abstime);
	TRACE(str); 
}
*/

// Functon:Wave data call back function.
void CALLBACK WaveCBFun(long /*nPort*/, char * pAudioBuf, long /*nSize*/, long /*nStamp*/, long /*nType*/, long /*nUser*/)
{
	UNREFERENCED_PARAMETER(pAudioBuf);
	//TRACE("Wave data, nPort = %d, nSize = %d, nStamp = %d, nType = %d\n", nPort, nSize, nStamp, nType);
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  callback function begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

void CALLBACK EncChange(LONG lPort, LONG dwUser)
{
	CPlayerDlg* pOwner = (CPlayerDlg*)dwUser;
	pOwner->SetWindowSize();
}

///
// Function: input stream thread.

#define BUF_SIZE 3008
DWORD WINAPI InputStreamThread( LPVOID lpParameter)
{
	CPlayerDlg* pOwner = (CPlayerDlg*)lpParameter;
	HANDLE hMulEvents[2];
	hMulEvents[0] = pOwner->m_hEventKill;
	hMulEvents[1] = pOwner->m_hEventInput;
	BYTE pBuf[BUF_SIZE];
	DWORD nRealRead;
	BOOL bBufFull = FALSE;
    DWORD dwSize = BUF_SIZE;
	unsigned char chType;
	DWORD	dwDataLen = 0;

	while (WAIT_OBJECT_0 != WaitForMultipleObjects(2, hMulEvents, FALSE, INFINITE))
	{	
		if(!bBufFull)
		{
			// TRACE("Read file and put it input into the stream buffer.\n");
            if(pOwner->m_dwSysFormat != SYSTEM_RTP)
            {
				if(!(ReadFile(pOwner->m_hStreamFile, pBuf, dwSize, &nRealRead, NULL) && (nRealRead == dwSize)))
				{
					//File end;
					pOwner->m_bFileEnd = TRUE;
					bBufFull = FALSE;
					ResetEvent(pOwner->m_hEventInput);
				}
				dwDataLen = nRealRead;
            }
            else
            {
                //先读出4字节rtp包长

                if (!(ReadFile(pOwner->m_hStreamFile, pBuf, 4, &nRealRead, NULL) && (nRealRead == 4)))
                {
                    //File end;
					pOwner->m_bFileEnd = TRUE;
					bBufFull = FALSE;
					ResetEvent(pOwner->m_hEventInput);
                }

				dwSize = pBuf[0] + (pBuf[1] << 8) + (pBuf[2] << 16) + (pBuf[3] << 24);
		
                if (!(ReadFile(pOwner->m_hStreamFile, pBuf, dwSize, &nRealRead, NULL) && (nRealRead == dwSize)))
                {
                    //File end;
					pOwner->m_bFileEnd = TRUE;
					bBufFull = FALSE;
					ResetEvent(pOwner->m_hEventInput);
                }

                dwDataLen = nRealRead;
            }
			
			while ( !NAME(PlayM4_InputData)(m_lPort, pBuf, dwDataLen) )
			{
				if ( PlayM4_GetLastError(m_lPort) == PLAYM4_BUF_OVER )
				{
					Sleep(10);
					continue;
				}
					
				bBufFull = TRUE;
				ResetEvent(pOwner->m_hEventInput);
				break;
			}
		}
	}

	return 1;
}



/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  assistant operation begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
// open/close file or stream
// browse file and get the file path
BOOL CPlayerDlg::BrowseFile(CString *strFileName)
{
#ifdef _FOR_HIKPLAYM4_DLL_
		CFileDialog dlg(TRUE, 
						"mpg",
						NULL, 
						OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
						"Hikvision File(*.mp4;*.264)|*.mp4;*.264|All Files(*.*)|*.*||", this);
#else
		CFileDialog dlg(TRUE, 
						"mpg",
						NULL, 
						OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
						"File(*.mp4;*.264)|*.mp4;*.264|All Files(*.*)|*.*||", this);
#endif

	if(dlg.DoModal() == IDCANCEL)
	{
		return FALSE;
	}
	*strFileName = dlg.GetPathName();
	return TRUE;
}

// open file and play
void CPlayerDlg::OpenFile()
{
	CString strError;
	
	NAME(PlayM4_SetFileEndMsg)(m_lPort, m_hWnd, WM_FILE_END);

	NAME(PlayM4_SetFileRefCallBack)(m_lPort, FileRefDone, (DWORD)this);
//	NAME(PlayM4_SetVerifyCallBack)(m_lPort, 0, 0xffffffff, VerifyFun, (DWORD) this); // verify the whole file;
//	NAME(PlayM4_SetDecCallBackMend)(m_lPort, DecCBFun, (long)this);	
	NAME(PlayM4_SetDecCallBackEx)(m_lPort, DecCBFun, NULL, 0);	
	
//	BOOL bRelt = PlayM4_SetDecodeFrameType(m_lPort, 0);
	if(!NAME(PlayM4_OpenFile)(m_lPort, m_strPlayFileName.GetBuffer(m_strPlayFileName.GetLength())))
	{
		m_strPlayFileName = _T("");
		strError.Format("Open file failed(%s)", MyErrorToString(NAME(PlayM4_GetLastError)(m_lPort)));
		MessageBox(strError);
		throw 0;
	}

//	HANDLE hFile = CreateFile("D:\\F009-100726-142016.hik.idx", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//	DWORD dwIndex = GetFileSize(hFile, NULL);
//	BYTE* pIndex = new BYTE[dwIndex];
//	DWORD dw;
//	ReadFile(hFile, pIndex, dwIndex, &dw, NULL);
//	NAME(PlayM4_SetRefValue)(m_lPort, pIndex, dwIndex);

//	PlayM4_SetSecretKey(m_lPort, 1, "tyco_oem_ver", 12 * 8);

	NAME(PlayM4_SyncToAudio)(m_lPort, TRUE);
	
	// try overlay mode!
//	NAME(PlayM4_SetOverlayMode)(m_lPort, TRUE, RGB(255,0,255));
	// try flip overlay mode
//	NAME(PlayM4_SetOverlayFlipMode)(m_lPort, TRUE);

	m_dwMaxFileTime = NAME(PlayM4_GetFileTime)(m_lPort);
	if(!m_dwMaxFileTime)
	{
// 		strError.Format("File seconds is zero");
// 		MessageBox(strError);
// 		throw 0;
		m_dwMaxFileTime = 1;
	}

	m_dwDisplayHour		= m_dwMaxFileTime/3600;
	m_dwDisplayMinute   = (m_dwMaxFileTime % 3600) / 60;
	m_dwDisplaySecond   = m_dwMaxFileTime % 60;
	m_dwTotalFrames		= NAME(PlayM4_GetFileTotalFrames)(m_lPort);

	if(m_bConvertAVI)
	{
		AVI_CONVERT_PARA strParam;
		long dwHeight, dwWidth;
		NAME(PlayM4_GetPictureSize)(m_lPort, &dwWidth, &dwHeight);
		strParam.dwFrameWidth  = MOD16(dwWidth);
		strParam.dwFrameHeight = MOD16(dwHeight);
		strParam.dwFrameSize   = strParam.dwFrameWidth * strParam.dwFrameHeight *3/2;
		strParam.dwTotalFrames = m_dwTotalFrames;

		BOOL bInitAVI = g_classAVI.InitResource(&strParam, m_strSaveAVIPath);
		if(!bInitAVI)
		{
			strError.Format("Init AVI Resource failed!");
			MessageBox(strError);
			g_classAVI.ReleaseResource();
			m_bConvertAVI = FALSE;
		}
	}

	// If you want to change the display buffer. Do hear!
//	NAME(PlayM4_SetDisplayBuf)(m_lPort,50);
//	NAME(PlayM4_SetDisplayBufAddtionalLen)(m_lPort, 6);

	Play();
//	PlayM4_SetPlayedTimeEx(m_lPort, 3000000);
// 	BOOL b = NAME(PlayM4_SetDisplayType)(m_lPort, 3);
//	PlayM4_SetCurrentFrameNum(m_lPort, 10000);
//	PlayM4_SetPlayPos(m_lPort, 1.2);
// 	DWORD dw = PlayM4_GetLastError(m_lPort);
	SetWindowText((LPCTSTR) m_strPlayFileName);
}

// close file
void CPlayerDlg::CloseFile()
{
	if (m_pDisplayRegion->m_bValid) 
	{
		m_pDisplayRegion->DestroyWindow();
		m_pMainMenu->EnableMenuItem(2, MF_ENABLED|MF_BYPOSITION);
		m_pMainMenu->EnableMenuItem(IDM_SETDISPLAY, MF_ENABLED);
		
	}

	Stop();
	NAME(PlayM4_CloseFile)(m_lPort);
//	NAME(PlayM4_FreePort)(m_lPort);
	m_pMainMenu->GetSubMenu(3)->EnableMenuItem(10, MF_ENABLED|MF_BYPOSITION);
	m_enumState = State_Close;
	m_bOpen = FALSE;
	m_bFileRefCreated =	FALSE;	
}

// Funtion: Open the file by stream type and play it
void CPlayerDlg::OpenStream()
{
	m_dwDisplayHour		= 0;
	m_dwDisplayMinute   = 0;
	m_dwDisplaySecond   = 0;
	m_dwTotalFrames     = 0;
	m_bFileEnd          = FALSE;
	HIK_MEDIAINFO		stInfo;
	ZeroMemory(&stInfo,sizeof(HIK_MEDIAINFO));
	
	m_hStreamFile = CreateFile(m_strPlayFileName,
							   GENERIC_READ,
							   FILE_SHARE_READ,
							   NULL,
							   OPEN_EXISTING,
							   FILE_ATTRIBUTE_NORMAL,
							   NULL);
	if(m_hStreamFile == INVALID_HANDLE_VALUE)
	{
		MessageBox("Open file failed");
		throw 0;
	}
	m_dwMaxFileSize = ::GetFileSize(m_hStreamFile, NULL);
//	NAME(PlayM4_SetSourceBufCallBack)(m_lPort, 6000000, SourceBufFun, (DWORD)this, NULL);
	NAME(PlayM4_SetStreamOpenMode)(m_lPort, STREAME_FILE);
	m_dwHeadSize = NAME(PlayM4_GetFileHeadLength)();
	PBYTE pBuf = NULL;
	char csError[50];
	
	pBuf = new BYTE[m_dwHeadSize];
	if(!pBuf)
	{
		MessageBox("Alloc memory failed");
		throw 0;
	}
	DWORD nRealRead;
	SetFilePointer(m_hStreamFile, 0, 0, FILE_BEGIN);
	ReadFile(m_hStreamFile, pBuf, m_dwHeadSize, &nRealRead, NULL);
	if(nRealRead != m_dwHeadSize)
	{
		MessageBox("File is too small");
		delete []pBuf;
		pBuf = NULL;
		throw 0;
	}

	unsigned int g_strFileHdr[10] = { 0x484B4834, 0xd6d0b3fe, 0x20040308, 0x0, 0x10011001, 0x00101001, 0x3e80, 0x01200160, 0x1011, 0x4 };

//	NAME(PlayM4_OpenStream)(m_lPort, g_strFileHdr, 40,  6*1000*1024)
#ifdef SPLIT_INPUT
	if(!NAME(PlayM4_OpenStreamEx)(m_lPort, (BYTE*)&stInfo, m_dwHeadSize, 6*1000*1024))
	{
		sprintf(csError, "Open stream failed(%s)", MyErrorToString(NAME(PlayM4_GetLastError)(m_lPort)));
		MessageBox(csError);
		delete []pBuf;
		pBuf = NULL;
		throw 0;
	}
	PlayM4_SyncToAudio(m_lPort, FALSE);
#else defined MIX_INPUT	

	if(!NAME(PlayM4_OpenStream)(m_lPort, pBuf, sizeof(stInfo),  6*1000*1024))
	{
		sprintf(csError, "Open stream failed(%s)", MyErrorToString(NAME(PlayM4_GetLastError)(m_lPort)));
		MessageBox(csError);
		delete []pBuf;
		pBuf = NULL;
		throw 0;
	}
	NAME(PlayM4_SyncToAudio)(m_lPort, FALSE);
#endif

	delete []pBuf;
	pBuf = NULL;

	DWORD dw;
	m_hThread	  = NULL;
	m_hEventInput = NULL;
	m_hEventKill  = NULL;

	m_hThread	  =	CreateThread(NULL,0, LPTHREAD_START_ROUTINE (InputStreamThread),this,0,&dw);
	m_hEventInput =	CreateEvent(NULL,TRUE,FALSE,NULL);
	m_hEventKill  =	CreateEvent(NULL,FALSE,FALSE,NULL);
	if( !(m_hThread&&m_hEventInput&&m_hEventKill) )
	{
		MessageBox("Create thread failed");
		throw 0;
	}

	// try overlay mode!
//	NAME(PlayM4_SetOverlayMode)(m_lPort, TRUE, RGB(255,0,255));
	// try flip overlay mode
//	NAME(PlayM4_SetOverlayFlipMode)(m_lPort, TRUE);
	
	Play();
}


// Function:Close the stream.
void CPlayerDlg::CloseStream()
{
	Stop();
	NAME(PlayM4_CloseStream)(m_lPort);
	if(m_hStreamFile)
	{
		CloseHandle(m_hStreamFile);
		m_hStreamFile = NULL;
	}
	
	if(m_hThread)
	{
		SetEvent(m_hEventKill);
		DWORD dwStatus;
		for(int i = 0; i < 5; i++)
		{
			if(!::GetExitCodeThread(m_hThread, &dwStatus)|| (i == 4) )
			{
				TerminateThread(m_hThread, 0);
				TRACE("GetExitCode option error!-decodethread\n");
			}
			else
			{
				if(dwStatus == STILL_ACTIVE)
				{
					SetEvent(m_hEventKill);
					Sleep(2);
				}
				else
				{
					break;
				}
			}
		}
		CloseHandle(m_hThread);
		m_hThread = NULL;
	}

	if(m_hEventInput)
	{
		CloseHandle(m_hEventInput);
		m_hEventInput = NULL;
	}

	if(m_hEventKill)
	{
		CloseHandle(m_hEventKill);
		m_hEventKill = NULL;
	}
	
	m_enumState = State_Close;
	m_bOpen = FALSE;
	m_bFileRefCreated =	FALSE;		
}

// set play state
// Funtion: Draw the status .
void CPlayerDlg::DrawStatus()
{
	DWORD nCurrentTime = NAME(PlayM4_GetPlayedTime)(m_lPort);

	TRACE("hytest: play position = %f!\n", NAME(PlayM4_GetPlayPos)(m_lPort));
	
	//TRACE("Get time is:%d\n",nCurrentTime);			
	DWORD nHour   = (nCurrentTime / 3600) % 24;
	DWORD nMinute = (nCurrentTime % 3600) / 60;
	DWORD nSecond = nCurrentTime % 60;
	int nPos = 0;
	if(m_bStreamType)
	{
		DWORD nFilePos = SetFilePointer(m_hStreamFile, 0, 0, FILE_CURRENT);
		nPos = nFilePos * PLAYER_SLIDER_MAX / m_dwMaxFileSize;
	}
	else
	{
#ifdef _FILE_POS
	float fPos = NAME(PlayM4_GetPlayPos)(m_lPort);
	nPos = int(fPos * PLAYER_SLIDER_MAX);
	
#else
	nPos = nCurrentTime * PLAYER_SLIDER_MAX / m_dwMaxFileTime;
			
#endif
	}
	
	DWORD nCurrentFrame = NAME(PlayM4_GetCurrentFrameNum)(m_lPort);

	TRACE("nCurrentFrame %d----------nCurrentTime %d--------------\n", nCurrentFrame, nCurrentTime);
	if(m_nSpeed > 0)
	{
		m_strPlayStateText.Format("speed X %d            %d/%d  %02d:%02d:%02d/%02d:%02d:%02d", GetSpeedModulus(), nCurrentFrame, m_dwTotalFrames, nHour, nMinute, nSecond, m_dwDisplayHour,m_dwDisplayMinute,m_dwDisplaySecond);
	}
	else if(m_nSpeed == 0)
	{
		m_strPlayStateText.Format("speed normal          %d/%d  %02d:%02d:%02d/%02d:%02d:%02d", nCurrentFrame, m_dwTotalFrames, nHour, nMinute, nSecond, m_dwDisplayHour,m_dwDisplayMinute,m_dwDisplaySecond);
	}
	else
	{
		m_strPlayStateText.Format("speed / %d            %d/%d  %02d:%02d:%02d/%02d:%02d:%02d", GetSpeedModulus(), nCurrentFrame, m_dwTotalFrames, nHour, nMinute, nSecond, m_dwDisplayHour,m_dwDisplayMinute,m_dwDisplaySecond);
	}

	if(m_bConvertAVI)
	{
		m_strPlayStateText.Format("Converting……        %d/%d  %02d:%02d:%02d/%02d:%02d:%02d", nCurrentFrame, m_dwTotalFrames, nHour, nMinute, nSecond, m_dwDisplayHour, m_dwDisplayMinute, m_dwDisplaySecond);     
	}

	m_ctrlPlayText.ShowText(m_strPlayStateText);



	//adjust the slider.
//	INT nAdjust = (m_nPrePlayPos < nPos) ? 1 : 0;
	int nScrollPos = 0;
	if (m_dwTotalFrames != 1)
	{
		nScrollPos = nCurrentFrame * PLAYER_SLIDER_MAX / (m_dwTotalFrames - 1);
	}
	else
	{
		nScrollPos = 1;
	}
	
	if (m_nPrePlayPos == nScrollPos)
	{
		return;
	}
	m_PlaySlider.SetScrollPos(nScrollPos);
	m_nPrePlayPos = nScrollPos;

	// test
	// TRACE("Current frame rate:%d\n",NAME(PlayM4_GetCurrentFrameRate)(m_lPort));
	// TRACE("Current time use ms:%d\n",NAME(PlayM4_GetPlayedTimeEx)(m_lPort));
	
}

// set state
void CPlayerDlg::SetState()
{
	int i;
	switch(m_enumState)
	{
	case State_Close:
		
		// button state

		m_ctrlBtnPlay.SetIcon(IDI_PLAY_DISABLE);
		m_ctrlBtnPlay.EnableWindow(FALSE);
		m_ctrlBtnPlay.SetCheck(0);

		m_ctrlBtnPause.SetIcon(IDI_PAUSE_DISABLE);
		m_ctrlBtnPause.EnableWindow(FALSE);
		m_ctrlBtnPause.SetCheck(0);

		m_ctrlBtnStop.SetIcon(IDI_STOP_DISABLE);
		m_ctrlBtnStop.EnableWindow(FALSE);
		m_ctrlBtnStop.SetCheck(0);

		m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_DISABLE);
		m_ctrlBtnGStart.EnableWindow(FALSE);

		m_ctrlBtnSlow.SetIcon(IDI_FASTBACKWARD_DISABLE);
		m_ctrlBtnSlow.EnableWindow(FALSE);

		m_ctrlBtnFast.SetIcon(IDI_FASTFORWARD_DISABLE);
		m_ctrlBtnFast.EnableWindow(FALSE);

		m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_DISABLE);
		m_ctrlBtnGEnd.EnableWindow(FALSE);

		m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_DISABLE);
		m_ctrlStepBackward.EnableWindow(FALSE);

		m_ctrlStepForward.SetIcon(IDI_STEPFORWARD_DISABLE);
		m_ctrlStepForward.EnableWindow(FALSE);
		
		m_ctrlBtnCapPic.SetIcon(IDI_CAPPIC_DISABLE);
		m_ctrlBtnCapPic.EnableWindow(FALSE);
		
		m_ctrlBtnSound.SetIcon(IDI_SOUND_DISABLE);
		m_ctrlBtnSound.EnableWindow(FALSE);
		
		// menu state
		m_pMainMenu->EnableMenuItem(IDM_FILE_CLOSE, MF_GRAYED | MF_DISABLED);
//		m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_SET_KEY, MF_ENABLED);

		for(i = 0; i < 3; i++)
		{
			m_pMainMenu->CheckMenuItem(IDM_VIEW_ZOOM_50 + i, MF_UNCHECKED);
		}
		m_pMainMenu->CheckMenuItem(IDM_VIEW_ZOOM_100, MF_CHECKED);
		m_pMainMenu->GetSubMenu(1)->EnableMenuItem(1, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
		m_pMainMenu->EnableMenuItem(IDM_VIEW_FULLSCREEN, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_INFO, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_SETDISPLAY, MF_GRAYED | MF_DISABLED);

		m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_PLAY_PAUSE, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STOP, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_GOTOEND, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_GOTOSTART, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STEPBACKWARD, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STEPFORWARD, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_WATERMARK, MF_GRAYED | MF_DISABLED);

		m_pMainMenu->EnableMenuItem(IDM_PREVIEW50, MF_ENABLED);
		if(m_bHighFluid)
		{
			m_pMainMenu->CheckMenuItem(IDM_PREVIEW50, MF_CHECKED);
		}
		else
		{
			m_pMainMenu->CheckMenuItem(IDM_PREVIEW50, MF_UNCHECKED);
		}

		m_pMainMenu->EnableMenuItem(IDM_STREAM_TYPE, MF_ENABLED);
		for(i=0; i<2; i++)
		{
			m_pMainMenu->CheckMenuItem(IDM_TIMER1 + i, MF_UNCHECKED);
		}
		m_pMainMenu->CheckMenuItem(IDM_TIMER1, MF_CHECKED);
		m_pMainMenu->CheckMenuItem(IDM_BYRATE, MF_CHECKED);
		m_pMainMenu->GetSubMenu(3)->EnableMenuItem(10, MF_ENABLED|MF_BYPOSITION);

		
		// scroll state	
		m_PlaySlider.SetScrollPos(0);
		m_PlaySlider.EnableWindow(FALSE);

#ifdef _WAVE_ADJ
		m_SoundSlider.SetPos(0);
#else
		m_SoundSlider.SetPos(0xffff>>1);
#endif
		m_SoundSlider.EnableWindow(FALSE);

		if((HBITMAP)m_HikvisionBmp != m_ctrlVideoPic.GetBitmap())
		{
			m_ctrlVideoPic.SetBitmap(m_HikvisionBmp);
		}
		
		InitWindowSize(WIDTH,HEIGHT_PAL);

		break;

	case State_Play:
		m_ctrlBtnPlay.SetIcon(IDI_PLAY_CHECK);
		m_ctrlBtnPlay.EnableWindow(TRUE);
		m_ctrlBtnPlay.SetCheck(1);

		m_ctrlBtnPause.SetIcon(IDI_PAUSE_ENABLE);
		m_ctrlBtnPause.EnableWindow(TRUE);
		m_ctrlBtnPause.SetCheck(0);

		m_ctrlBtnStop.SetIcon(IDI_STOP_ENABLE);
		m_ctrlBtnStop.EnableWindow(TRUE);
		m_ctrlBtnStop.SetCheck(0);

		if(m_bStreamType)
		{
			m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_DISABLE);
			m_ctrlBtnGStart.EnableWindow(FALSE);

			m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_DISABLE);
			m_ctrlBtnGEnd.EnableWindow(FALSE);

			m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_DISABLE);
			m_ctrlStepBackward.EnableWindow(FALSE);
		}
		else
		{
			m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_ENABLE);
			m_ctrlBtnGStart.EnableWindow(TRUE);

			m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_ENABLE);
			m_ctrlBtnGEnd.EnableWindow(TRUE);

			m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_ENABLE);
			m_ctrlStepBackward.EnableWindow(TRUE);
		}
	

		m_ctrlBtnSlow.SetIcon(IDI_FASTBACKWARD_ENABLE);
		m_ctrlBtnSlow.EnableWindow(TRUE);

		m_ctrlBtnFast.SetIcon(IDI_FASTFORWARD_ENABLE);
		m_ctrlBtnFast.EnableWindow(TRUE);

		m_ctrlStepForward.SetIcon(IDI_STEPFORWARD_ENABLE);
		m_ctrlStepForward.EnableWindow(TRUE);

		m_ctrlBtnCapPic.SetIcon(IDI_CAPPIC_AT, IDI_CAPPIC_ENABLE);
		m_ctrlBtnCapPic.EnableWindow(TRUE);

		m_ctrlBtnSound.EnableWindow(TRUE);
		if(m_bSound)
		{
			m_ctrlBtnSound.SetIcon(IDI_SOUND_ENABLE);
		}
		else
		{
			m_ctrlBtnSound.SetIcon(IDI_SOUND_DISABLE);
		}

		// menu state
		m_pMainMenu->EnableMenuItem(IDM_FILE_CLOSE, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_SET_KEY, MF_GRAYED | MF_DISABLED);

		if(m_bFileRefCreated)
		{
//			m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_ENABLED);
			m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_ENABLED);
		}
		else
		{
//			m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_GRAYED | MF_DISABLED);
			m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_GRAYED | MF_DISABLED);
		}

		m_pMainMenu->GetSubMenu(1)->EnableMenuItem(1, MF_ENABLED | MF_BYPOSITION);
		m_pMainMenu->EnableMenuItem(IDM_VIEW_FULLSCREEN, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_INFO, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_SETDISPLAY, MF_ENABLED);
		
		m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_PLAY_PAUSE, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_STOP, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_STEPFORWARD, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_WATERMARK, MF_ENABLED);

		m_pMainMenu->EnableMenuItem(IDM_PREVIEW50, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STREAM_TYPE, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->GetSubMenu(3)->EnableMenuItem(10, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
	
		if(m_bStreamType)
		{
			m_pMainMenu->EnableMenuItem(IDM_GOTOEND, MF_GRAYED | MF_DISABLED);
			m_pMainMenu->EnableMenuItem(IDM_GOTOSTART, MF_GRAYED | MF_DISABLED);
			m_pMainMenu->EnableMenuItem(IDM_STEPBACKWARD, MF_GRAYED | MF_DISABLED);
		}
		else
		{
			m_pMainMenu->EnableMenuItem(IDM_GOTOEND, MF_ENABLED);
			m_pMainMenu->EnableMenuItem(IDM_GOTOSTART, MF_ENABLED);
			m_pMainMenu->EnableMenuItem(IDM_STEPBACKWARD, MF_ENABLED);
		}

		// scroll state			
		if(m_bStreamType)
		{
			m_PlaySlider.EnableWindow(FALSE);
		}
		else
		{
			m_PlaySlider.EnableWindow(TRUE);
		}
		m_SoundSlider.EnableWindow(TRUE);
	
		if((HBITMAP)m_OverlayBmp != m_ctrlVideoPic.GetBitmap())
		{
			m_ctrlVideoPic.SetBitmap(m_OverlayBmp);
		}

		break;

	case State_Pause:
	case State_Step:
		m_ctrlBtnPlay.SetIcon(IDI_PLAY_ENABLE);
		m_ctrlBtnPlay.EnableWindow(TRUE);
		m_ctrlBtnPlay.SetCheck(0);

		m_ctrlBtnPause.SetIcon(IDI_PAUSE_CHECK);
		m_ctrlBtnPause.EnableWindow(TRUE);
		m_ctrlBtnPause.SetCheck(1);

		m_ctrlBtnStop.SetIcon(IDI_STOP_ENABLE);
		m_ctrlBtnStop.EnableWindow(TRUE);
		m_ctrlBtnStop.SetCheck(0);

		if(m_bStreamType)
		{
			m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_DISABLE);
			m_ctrlBtnGStart.EnableWindow(FALSE);

			m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_DISABLE);
			m_ctrlBtnGEnd.EnableWindow(FALSE);

			m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_DISABLE);
			m_ctrlStepBackward.EnableWindow(FALSE);
		}
		else
		{
			m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_ENABLE);
			m_ctrlBtnGStart.EnableWindow(TRUE);

			m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_ENABLE);
			m_ctrlBtnGEnd.EnableWindow(TRUE);

			m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_ENABLE);
			m_ctrlStepBackward.EnableWindow(TRUE);
		}
	
		m_ctrlBtnSlow.SetIcon(IDI_FASTBACKWARD_ENABLE);
		m_ctrlBtnSlow.EnableWindow(TRUE);

		m_ctrlBtnFast.SetIcon(IDI_FASTFORWARD_ENABLE);
		m_ctrlBtnFast.EnableWindow(TRUE);

		m_ctrlStepForward.SetIcon(IDI_STEPFORWARD_ENABLE);
		m_ctrlStepForward.EnableWindow(TRUE);

		m_ctrlBtnCapPic.SetIcon(IDI_CAPPIC_AT, IDI_CAPPIC_ENABLE);
		m_ctrlBtnCapPic.EnableWindow(TRUE);
		
		break;

	case State_Stop:
		m_ctrlBtnPlay.SetIcon(IDI_PLAY_ENABLE);
		m_ctrlBtnPlay.EnableWindow(TRUE);
		m_ctrlBtnPlay.SetCheck(0);

		m_ctrlBtnPause.SetIcon(IDI_PAUSE_ENABLE);
		m_ctrlBtnPause.EnableWindow(TRUE);
		m_ctrlBtnPause.SetCheck(0);

		m_ctrlBtnStop.SetIcon(IDI_STOP_CHECK);
		m_ctrlBtnStop.EnableWindow(TRUE);
		m_ctrlBtnStop.SetCheck(1);

		m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_DISABLE);
		m_ctrlBtnGStart.EnableWindow(FALSE);

		m_ctrlBtnSlow.SetIcon(IDI_FASTBACKWARD_ENABLE);
		m_ctrlBtnSlow.EnableWindow(TRUE);

		m_ctrlBtnFast.SetIcon(IDI_FASTFORWARD_ENABLE);
		m_ctrlBtnFast.EnableWindow(TRUE);

		m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_DISABLE);
		m_ctrlBtnGEnd.EnableWindow(FALSE);

		m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_DISABLE);
		m_ctrlStepBackward.EnableWindow(FALSE);

		m_ctrlStepForward.SetIcon(IDI_STEPFORWARD_DISABLE);
		m_ctrlStepForward.EnableWindow(FALSE);
		
		m_ctrlBtnCapPic.SetIcon(IDI_CAPPIC_DISABLE);
		m_ctrlBtnCapPic.EnableWindow(FALSE);
		
		// menu state
		m_pMainMenu->EnableMenuItem(IDM_FILE_CLOSE, MF_ENABLED);

		if(m_bFileRefCreated)
		{
//			m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_ENABLED);
			m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_ENABLED);
		}
		else
		{
//			m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_DISABLED);
			m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_DISABLED);
		}

		m_pMainMenu->GetSubMenu(1)->EnableMenuItem(1, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);
		m_pMainMenu->EnableMenuItem(IDM_VIEW_FULLSCREEN, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_INFO, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_SETDISPLAY, MF_GRAYED | MF_DISABLED);

		m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_PLAY_PAUSE, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_STOP, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_GOTOEND, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_GOTOSTART, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STEPBACKWARD, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_STEPFORWARD, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->EnableMenuItem(IDM_WATERMARK, MF_GRAYED | MF_DISABLED);

		m_pMainMenu->EnableMenuItem(IDM_PREVIEW50, MF_ENABLED);
		m_pMainMenu->EnableMenuItem(IDM_STREAM_TYPE, MF_GRAYED | MF_DISABLED);
		m_pMainMenu->GetSubMenu(3)->EnableMenuItem(10, MF_DISABLED|MF_GRAYED|MF_BYPOSITION);

		// scroll state
		m_PlaySlider.SetScrollPos(0);
		m_PlaySlider.EnableWindow(FALSE);
		
#ifdef _WAVE_ADJ
		m_SoundSlider.SetPos(0);
#else
		m_SoundSlider.SetPos(0xffff>>1);
#endif
		m_SoundSlider.EnableWindow(FALSE);
		
		if((HBITMAP)m_HikvisionBmp != m_ctrlVideoPic.GetBitmap())
		{
			m_ctrlVideoPic.SetBitmap(m_HikvisionBmp);
		}

		break;
		
	default:
		break;
	}
	
	SortControl();
	
	UpdateData(FALSE);
	NAME(PlayM4_RefreshPlay)(m_lPort);
}

// set avi state
void CPlayerDlg::SetAVIState()
{
	// button state

	m_ctrlBtnPlay.SetIcon(IDI_PLAY_DISABLE);
	m_ctrlBtnPlay.EnableWindow(FALSE);
	m_ctrlBtnPlay.SetCheck(0);

	m_ctrlBtnPause.SetIcon(IDI_PAUSE_DISABLE);
	m_ctrlBtnPause.EnableWindow(FALSE);
	m_ctrlBtnPause.SetCheck(0);

	m_ctrlBtnStop.SetIcon(IDI_STOP_ENABLE);
	m_ctrlBtnStop.EnableWindow(TRUE);
	m_ctrlBtnStop.SetCheck(0);

	m_ctrlBtnGStart.SetIcon(IDI_GOTOSTART_DISABLE);
	m_ctrlBtnGStart.EnableWindow(FALSE);

	m_ctrlBtnSlow.SetIcon(IDI_FASTBACKWARD_DISABLE);
	m_ctrlBtnSlow.EnableWindow(FALSE);

	m_ctrlBtnFast.SetIcon(IDI_FASTFORWARD_DISABLE);
	m_ctrlBtnFast.EnableWindow(FALSE);

	m_ctrlBtnGEnd.SetIcon(IDI_GOTOEND_DISABLE);
	m_ctrlBtnGEnd.EnableWindow(FALSE);

	m_ctrlStepBackward.SetIcon(IDI_STEPBACKWARD_DISABLE);
	m_ctrlStepBackward.EnableWindow(FALSE);

	m_ctrlStepForward.SetIcon(IDI_STEPFORWARD_DISABLE);
	m_ctrlStepForward.EnableWindow(FALSE);
	
	m_ctrlBtnCapPic.SetIcon(IDI_CAPPIC_DISABLE);
	m_ctrlBtnCapPic.EnableWindow(FALSE);
	
	m_ctrlBtnSound.SetIcon(IDI_SOUND_DISABLE);
	m_ctrlBtnSound.EnableWindow(FALSE);
	
	// menu state
	m_pMainMenu->EnableMenuItem(IDM_FILE_CLOSE, MF_ENABLED);
//	m_pMainMenu->EnableMenuItem(IDM_CUT_FILE, MF_GRAYED | MF_DISABLED);

	m_pMainMenu->GetSubMenu(1)->EnableMenuItem(1, MF_DISABLED | MF_GRAYED | MF_BYPOSITION);
	m_pMainMenu->EnableMenuItem(IDM_VIEW_FULLSCREEN, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_INFO, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_SETDISPLAY, MF_GRAYED | MF_DISABLED);

	m_pMainMenu->EnableMenuItem(IDM_SEEK, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_PLAY_PAUSE, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_STOP, MF_ENABLED);
	m_pMainMenu->EnableMenuItem(IDM_GOTOEND, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_GOTOSTART, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_STEPBACKWARD, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_STEPFORWARD, MF_GRAYED | MF_DISABLED);

	m_pMainMenu->EnableMenuItem(IDM_PREVIEW50, MF_GRAYED | MF_DISABLED);
	m_pMainMenu->EnableMenuItem(IDM_STREAM_TYPE, MF_GRAYED | MF_DISABLED);	
	m_pMainMenu->GetSubMenu(3)->EnableMenuItem(10, MF_GRAYED | MF_DISABLED | MF_BYPOSITION);

	
	// scroll state	
	m_PlaySlider.SetScrollPos(0);
	m_PlaySlider.EnableWindow(FALSE);


	if((HBITMAP)m_OverlayBmp != m_ctrlVideoPic.GetBitmap())
	{
		m_ctrlVideoPic.SetBitmap(m_OverlayBmp);
	}
}

// get speed modulus to show int the static text control
DWORD CPlayerDlg::GetSpeedModulus()
{
	DWORD dwValue = 0;
	switch(m_nSpeed)
	{
	case 1:
	case -1:
		dwValue = 2;
		break;

	case 2:
	case -2:
		dwValue = 4;
		break;

	case 3:
	case -3:
		dwValue = 8;
		break;

	case 4:
	case -4:
		dwValue = 16;
		break;

	default:
		break;
	}

	return dwValue;
}

// resize the dialog
void CPlayerDlg::SetWindowSize()
{
	CRect rcWin, rcClient;
	GetWindowRect(&rcWin);
	GetClientRect(&rcClient);
	m_dwDlgEdge = (rcWin.Width() - rcClient.Width()) >> 1;
	ClientToScreen(&rcClient);
	m_dwDlgTopSize = rcClient.top - rcWin.top;

	TRACE("init window size!\n");
	NAME(PlayM4_GetPictureSize)(m_lPort, &m_nWidth, &m_nHeight);
	m_pDisplayRegion->SetResolution(m_nHeight, m_nWidth);
	TRACE("get window size ok\n");

	if (m_nWidth == 704 && (m_nHeight == 288 || m_nHeight == 240))
	{
		m_nHeight <<= 1;
	}
	
	DWORD nWindowHeight = m_nHeight + PANNEL_HEIGHT + m_dwDlgTopSize + m_dwDlgEdge + 10;
	DWORD nWindowWidth  = m_nWidth + (m_dwDlgEdge << 1);

	nWindowHeight = min(nWindowHeight, m_dwScreenHeight);
	nWindowWidth  = min(nWindowWidth,  m_dwScreenWidth);
	if (nWindowWidth < 200)
	{
		nWindowHeight += 20;
	}
	MoveWindow(
		(m_dwScreenWidth  -nWindowWidth)  / 2 + m_rcScreen.left,
		(m_dwScreenHeight -nWindowHeight) / 2 + m_rcScreen.top,
		nWindowWidth,
		nWindowHeight,
		TRUE);
	TRACE("exit window size\n");

}

// Funtion: sort the controls
void CPlayerDlg::SortControl()
{
	TRACE("init SORT\n");

	// if the dialog doesn't support resizing, return;
	if( !(GetStyle() & WS_SIZEBOX) )
	{
		return;
	}

	CRect rcClient, rcVideo;
	
	GetClientRect(&rcClient);
	DWORD x=LEFT_EDGE+10,y=rcClient.bottom-STATE_HEIGHT;
	
	//STATE 
	m_ctrlPlayText.MoveWindow(0,y,rcClient.Width()+1,STATE_HEIGHT,TRUE);


	x=LEFT_EDGE;
	y-=BUTTON_SIZE+STATE_UP;

	//BUTTON
	m_ctrlBtnPlay.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;
	m_ctrlBtnPause.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;
	m_ctrlBtnStop.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;

	x+=INTERVAL;
	GetDlgItem(IDC_INTER1)->MoveWindow(x,y,INTERVAL_SIZE,BUTTON_SIZE,TRUE);
	x+=INTERVAL_SIZE;
	x+=INTERVAL;

	m_ctrlBtnGStart.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;
	m_ctrlBtnSlow.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;
	m_ctrlBtnFast.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;
	m_ctrlBtnGEnd.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;

	x+=INTERVAL;
	GetDlgItem(IDC_INTER2)->MoveWindow(x,y,INTERVAL_SIZE,BUTTON_SIZE,TRUE);
	x+=INTERVAL_SIZE;
	x+=INTERVAL;

	m_ctrlStepBackward.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;

	m_ctrlStepForward.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;

	x+=INTERVAL;
	GetDlgItem(IDC_INTER3)->MoveWindow(x,y,INTERVAL_SIZE,BUTTON_SIZE,TRUE);
	x+=INTERVAL_SIZE;
	x+=INTERVAL;

	m_ctrlBtnCapPic.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);
	x+=BUTTON_SIZE;

	
	//SOUND
	x=rcClient.right-SOUND_SLIDER_WIDTH;
	m_SoundSlider.MoveWindow(x,y+BUTTON_SIZE-SOUND_SLIDER_HEIGHT,SOUND_SLIDER_WIDTH,SOUND_SLIDER_HEIGHT,TRUE);
	x-=BUTTON_SIZE;

	m_ctrlBtnSound.MoveWindow(x,y,BUTTON_SIZE,BUTTON_SIZE,TRUE);

	y-=BUTTON_SIZE+BUTTON_UP;
	//PLAY SLIDER
	x=0;
	GetDlgItem(IDC_PLAY_RECT_SLIDER)->MoveWindow(x,y,rcClient.Width(),PLAY_SLIDER_HEIGHT,TRUE);
	m_PlaySlider.MoveWindowEx(x,y,rcClient.Width(),PLAY_SLIDER_HEIGHT,TRUE);
	y-=PLAY_SLIDER_UP;

	//pic show
	m_ctrlVideoPic.MoveWindow(0,0,rcClient.Width(),y,TRUE);

	NAME(PlayM4_RefreshPlay)(m_lPort);

	// redraw whole the dialog rect except the video show rect
	m_ctrlVideoPic.GetClientRect(&rcVideo);
	CRect rect;
	rect.left   = rcClient.left;
	rect.top    = rcVideo.bottom;
	rect.right  = rcClient.right;
	rect.bottom = rcClient.bottom;
	InvalidateRect(&rect);
	TRACE("exit SORT\n");
}


// Funtion: Init window size.
void CPlayerDlg::InitWindowSize(DWORD cx,DWORD cy)
{
	TRACE("init window\n");
	CRect rcWin, rcClient;
	GetWindowRect(&rcWin);
	GetClientRect(&rcClient);
	m_dwDlgEdge = (rcWin.Width() - rcClient.Width()) >> 1;
	ClientToScreen(&rcClient);
	m_dwDlgTopSize = rcClient.top - rcWin.top;
	
	DWORD nWindowWidth  = cx + (m_dwDlgEdge << 1);
	DWORD nWindowHeight = cy + PANNEL_HEIGHT + m_dwDlgTopSize + m_dwDlgEdge + 10;
	
	nWindowHeight = min(nWindowHeight, m_dwScreenHeight);
	nWindowWidth  = min(nWindowWidth,  m_dwScreenWidth);

	MoveWindow(
		(m_dwScreenWidth  - nWindowWidth)/2 + m_rcScreen.left,
		(m_dwScreenHeight - nWindowHeight)/2+ m_rcScreen.top,
		nWindowWidth,
		nWindowHeight,
		TRUE);
	
	SortControl();

	//for the small picture size.The menu will be high. 
	GetWindowRect(&rcWin);
	GetClientRect(&rcClient);
	m_dwDlgEdge = (rcWin.Width() - rcClient.Width()) >> 1;
	ClientToScreen(&rcClient);
	DWORD nTopSize = rcClient.top - rcWin.top;
	if(nTopSize != m_dwDlgTopSize)
	{
		TRACE("re init window!!!!!!\n");
		m_dwDlgTopSize = nTopSize;
		nWindowHeight  = cy + PANNEL_HEIGHT + m_dwDlgTopSize + m_dwDlgEdge + 10;
		nWindowWidth   = cx + (m_dwDlgEdge << 1);

		nWindowHeight = min(nWindowHeight, m_dwScreenHeight);
		nWindowWidth  = min(nWindowWidth,  m_dwScreenWidth);

		MoveWindow(
				  (m_dwScreenWidth  - nWindowWidth)  / 2 + m_rcScreen.left,
				  (m_dwScreenHeight - nWindowHeight) / 2 + m_rcScreen.top,
				  nWindowWidth,
				  nWindowHeight,
				  TRUE);
		SortControl();
	}
}


// others
// geton pic rect
CRect CPlayerDlg::GetOnPicRect(CRect rcWnd, CRect rcOnWnd, LONG nPicWidth, LONG nPicHeight)
{
	CRect rcOnPic;
	//LONG nScaleX=rcWnd.Width()
	long nWndX = rcOnWnd.left - rcWnd.left;
	long nWndY = rcOnWnd.top  - rcWnd.top;
	if(nWndX < 0)
	{
		nWndX = 0;
	}

	if(nWndY < 0)
	{
		nWndY = 0;
	}

	rcOnPic.left   = nWndX * nPicWidth  / rcWnd.Width();
	rcOnPic.top    = nWndY * nPicHeight / rcWnd.Height();
	rcOnPic.right  = rcOnPic.left + rcOnWnd.Width()  * nPicWidth/rcWnd.Width();
	rcOnPic.bottom = rcOnPic.top  + rcOnWnd.Height() * nPicHeight/rcWnd.Height();
	
	if(rcOnPic.right > nPicWidth)
	{
		rcOnPic.right = nPicWidth;
	}

	if(rcOnPic.bottom > nPicHeight)
	{
		rcOnPic.bottom = nPicHeight;
	}
	
	return rcOnPic;
}
	
// Funtion: test the capability of your system.
void CPlayerDlg::TestCapability(DWORD nDeviceNum)
{
	CString csCap="";
#if (WINVER > 0x0400)
	int nFlag=NAME(PlayM4_GetCapsEx)(nDeviceNum);
#else
	int nFlag=NAME(PlayM4_GetCaps());
#endif

	if(!(nFlag&SUPPORT_SSE))
	{
		csCap+="Don't support SSE instruction set;\r\n";
	}

	if(!(nFlag&SUPPORT_DDRAW))
	{
		csCap+="Create DirectDraw faild;\r\n";
	}

	if(!(nFlag&SUPPORT_BLT))
	{
		csCap+="Error when blitting overlay or offscreen;Error when blitting overlay or offscreen;\r\n";
	}

	if(!(nFlag&SUPPORT_BLTFOURCC))
	{
		csCap+="Don't support color-space conversions;\r\n";
	}

	if(!(nFlag&SUPPORT_BLTSHRINKX))
	{
		csCap+="Don't support arbitrary shrinking of a surface along the x-axis\r\n";
	}

	if(!(nFlag&SUPPORT_BLTSHRINKY))
	{
		csCap+="Don't supports arbitrary shrinking of a surface along the y-axis (vertically);\r\n";
	}

	if(!(nFlag&SUPPORT_BLTSTRETCHX))
	{
		csCap+="Don't supports arbitrary stretching of a surface along the x-axis;\r\n";
	}

	if(!(nFlag&SUPPORT_BLTSTRETCHY))
	{
		csCap+="Don't supports arbitrary stretching of a surface along the y-axis;\r\n";
	}
	
	if(csCap.GetLength()>0)
	{
		csCap+="If your video adapter chip is made by nVidia,please update the new driver!\r\n";
		MessageBox(csCap,"Warning",MB_OK);
	}
}

void CPlayerDlg::SetDisplayRegion(RECT Rect)
{
	if (m_enumState != State_Step && m_enumState != State_Pause) 
	{
		return;
	}

	NAME(PlayM4_SetDisplayRegion)(m_lPort, 0, &Rect, GetDlgItem(IDC_SHOW)->m_hWnd, TRUE);
	UpdateWindow();
 	NAME(PlayM4_RefreshPlayEx)(m_lPort, 0);
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*  assistant operation over
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/




/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* button operation begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
// play / pause / stop
void CPlayerDlg::Play()
{
	if(m_enumState == State_Play)
	{
		return;
	}
	
	if(m_enumState == State_Pause)
	{
//		DWORD nPreSpeed = m_nSpeed;

		NAME(PlayM4_Pause)(m_lPort, FALSE);

		m_enumState = State_Play;

		// when u called this api, the speed is adjust to normal speed, so we must resume it.
//		NAME(PlayM4_Play)(m_lPort, m_ctrlVideoPic.GetSafeHwnd());
//		m_nSpeed = 0;
//		ThrowB(IDM_THROW0);
//		AdjustSpeed(nPreSpeed);
	}
	else if (m_enumState == State_Stop && m_bStreamType)
	{
		Open();
	}
	else if(m_enumState == State_Step)
	{
		NAME(PlayM4_Play)(m_lPort, m_ctrlVideoPic.GetSafeHwnd());
		m_nSpeed = 0;
		ThrowB(IDM_THROW0);

		m_enumState = State_Play;
	}
	else
	{
		ZeroMemory(&m_strWaterMark, sizeof(WATERMARK_VER1_INFO));
		NAME(PlayM4_SetCheckWatermarkCallBack)(m_lPort, funCheckWatermark, (DWORD)this);
		
		m_nSpeed = 0;
		ThrowB(IDM_THROW0);

		// set image sharpen level, default is 0
		NAME(PlayM4_SetImageSharpen)(m_lPort, m_dwImageSharpenLevel);
		// set play mode, high fluid
		NAME(PlayM4_SetPlayMode)(m_lPort, m_bHighFluid);
		
		// set decode type
		UINT nMenuState;
		for(int i = IDM_DECODE_NORMAL; i <= IDM_DECODE_NONE; i ++ )
		{
			nMenuState = m_pMainMenu->GetMenuState(i, MF_BYCOMMAND);
			if(nMenuState & MF_CHECKED)
			{
				NAME(PlayM4_SetDecodeFrameType)(m_lPort, i - IDM_DECODE_NORMAL);
				break;
			}
		}

		if(m_bConvertAVI)
		{
			NAME(PlayM4_SetDecCallBackMend)(m_lPort, DecCBFun, DWORD(this));
			m_bFileRefCreated = FALSE;
		}

		if(m_bStreamType)
		{
//			NAME(PlayM4_ResetSourceBuffer)(m_lPort);
			SetEvent(m_hEventInput);
		}

		if(NAME(PlayM4_Play)(m_lPort, m_ctrlVideoPic.m_hWnd))
		{
			m_enumState = State_Play;

			SetTimer(PLAY_TIMER, 500, NULL);

			NAME(PlayM4_RefreshPlay)(m_lPort);
		}

		m_bSound = NAME(PlayM4_PlaySound)(m_lPort);	
	}	

	if (m_pDisplayRegion->m_bValid) 
	{
		m_pDisplayRegion->Enable(FALSE);
 	}
}

void CPlayerDlg::Pause()
{
	if(m_enumState == State_Play)
	{
		NAME(PlayM4_Pause)(m_lPort, TRUE);
		m_enumState = State_Pause;
	}

	if (m_pDisplayRegion->m_bValid) 
	{
		Sleep(50);	
		m_pDisplayRegion->Enable(TRUE);
		m_pDisplayRegion->DrawRectangle();
	}
}

void CPlayerDlg::Stop()
{
	if(m_enumState == State_Stop)
	{
		return;
	}
	
	KillTimer(PLAY_TIMER);

	// stop sound
	if(NAME(PlayM4_StopSound)())
	{
		m_bSound = FALSE;
		m_ctrlBtnSound.SetIcon(IDI_SOUND_DISABLE);
	}
	
	// stop video
	if(NAME(PlayM4_Stop)(m_lPort))	
	{
		m_strPlayStateText = "Stop";
		m_ctrlPlayText.ShowText(m_strPlayStateText);
	
		if(m_bStreamType)
		{
			ResetEvent(m_hEventInput);
		}
	}	

	if(m_bConvertAVI)
	{
	   g_classAVI.ReleaseResource();
		
	   m_strSaveAVIPath = _T("");
	   m_bConvertAVI = FALSE;    
	}

	ZeroMemory(&m_strWaterMark, sizeof(WATERMARK_VER1_INFO));
	if(m_pWatermarkDlg->m_hWnd)
	{
		m_pWatermarkDlg->Clear();
	}

	m_enumState = State_Stop;
}

// gotostart / slow / fast / gotoend
void CPlayerDlg::GotoStart() 
{
	// TODO: Add your control notification handler code here

	if(m_bFileRefCreated)
	{
		NAME(PlayM4_SetPlayedTimeEx)(m_lPort, 0);
	}
	else
	{
		NAME(PlayM4_SetPlayPos)(m_lPort, 0);
	}
}

void CPlayerDlg::GotoEnd() 
{
	// TODO: Add your control notification handler code here
	
	if(m_bFileRefCreated)
	{
		//Note: May create many WM_FILE_END message. The best way is to synchronize the option;
		
//		int nEndFrame = m_dwTotalFrames;
//		int nCurFrame = NAME(PlayM4_GetCurrentFrameNum)(m_lPort);
		while( !NAME(PlayM4_SetPlayedTimeEx)(m_lPort, m_dwMaxFileTime * 1000 ) )
		{
			//TRACE("FrameNum is :%d\n",nEndFrame);
//			if(nEndFrame <= int(max(0, m_dwTotalFrames - 3)))
//			{
//				NAME(PlayM4_SetCurrentFrameNum)(m_lPort, nCurFrame);
//				break;
//			}
		}
	}
	else
	{
		NAME(PlayM4_SetPlayPos)(m_lPort, 1);
	}

}

void CPlayerDlg::Fast() 
{
	// TODO: Add your control notification handler code here

	// Throw B-Frame ,improve the performance;
	
	if(NAME(PlayM4_Fast)(m_lPort))
	{
		m_nSpeed ++;
		if(m_nSpeed > 0)
		{
			ThrowB(IDM_THROW2);	
		}
	}	
}

void CPlayerDlg::Slow() 
{
	// TODO: Add your control notification handler code here
	
	if(NAME(PlayM4_Slow)(m_lPort))
	{
		m_nSpeed --;
		if(m_nSpeed <= 0)
		{
			ThrowB(IDM_THROW0);
		}
	}
}

void CPlayerDlg::AdjustSpeed(int nSpeed)
{
	int nCyc = 0;
	while(m_nSpeed != nSpeed)
	{
		if(nSpeed > m_nSpeed)
		{
			Fast();	
		}
		else if(nSpeed < m_nSpeed)
		{
			Slow();
		}

		nCyc ++;
		if(nCyc >= 10)
		{
			break;
		}
	}
}

// stepback / stepfore / cap picture
void CPlayerDlg::StepBackward() 
{
	// TODO: Add your control notification handler code here

	if(m_bFileRefCreated)
	{
		NAME(PlayM4_OneByOneBack)(m_lPort);
		m_enumState = State_Step;
		if (m_pDisplayRegion->m_bValid) 
		{
			Sleep(50);	
			m_pDisplayRegion->Enable(TRUE);
			m_pDisplayRegion->DrawRectangle();
		}
	}
	else
	{
		MessageBox("File reference hasn't been created.", NULL, MB_OK);
	}
}

void CPlayerDlg::StepForward() 
{
	// TODO: Add your control notification handler code here
	
	// you can do it like the followed too.
	// DWORD nCurrentFrame = NAME(PlayM4_GetCurrentFrameNum)(m_lPort);
	// NAME(PlayM4_SetCurrentFrameNum)(m_lPort,nCurrentFrame+1);
	ThrowB(IDM_THROW0);          // when step forward one by one, don't throw B frame;
	NAME(PlayM4_OneByOne)(m_lPort);
	m_enumState = State_Step;
	if (m_pDisplayRegion->m_bValid) 
	{
		Sleep(50);	
		m_pDisplayRegion->Enable(TRUE);
		m_pDisplayRegion->DrawRectangle();
	}
}

void CPlayerDlg::GetPic(PBYTE pImage, DWORD nBufSize)
{
	CString sFilePath;
	CFile	clsFile;

	DWORD   pImageSize	= 0;
	
	if(m_nCapPicType == 1)
	{
		if( !NAME(PlayM4_GetJPEG)(m_lPort, pImage, nBufSize, &pImageSize) )
		{
			return;
		}

		if(m_strCapPicPath.Compare(""))
		{
			sFilePath.Format("%s\\capture%02d.jpeg", m_strCapPicPath, m_npic_jpeg);
		}
		else
		{
			sFilePath.Format("C:\\capture%02d.jpeg", m_npic_jpeg);
		}
	}
	else
	{
		if( !NAME(PlayM4_GetBMP)(m_lPort, pImage, nBufSize, &pImageSize) )
		{
			return;
		}

		if(m_strCapPicPath.Compare(""))
		{
			sFilePath.Format("%s\\capture%02d.bmp", m_strCapPicPath, m_npic_bmp);
		}
		else
		{
			sFilePath.Format("C:\\capture%02d.bmp", m_npic_bmp);
		}
	}
	
	if(!clsFile.Open(sFilePath,CFile::modeCreate|CFile::modeWrite))
	{
		return;
	}

	try							
	{
		clsFile.Write(pImage, pImageSize);
		clsFile.Close();

		if(m_nCapPicType == 0)
		{
			m_npic_bmp++;
		}
		else
		{
			m_npic_jpeg++;
		}
	}
	catch (CFileException* e) 
	{
		e->ReportError();
		e->Delete();
	}
}

void CPlayerDlg::Cappic() 
{
	// TODO: Add your control notification handler code here
	PBYTE	pImage		= NULL;
	DWORD   nBufSize	= m_nWidth * m_nHeight * 5;  // 保证足够大即可(不会小于一幅bmp或者jpeg图像大小)

	try
	{
		pImage = new BYTE[nBufSize];
		if(NULL == pImage)
		{
			throw 0;
		}
		
		GetPic(pImage, nBufSize);
	}
	catch(...)
	{
	}

	if(pImage != NULL)
	{
		delete []pImage;
		pImage = NULL;
	}
}

// close or open sound
void CPlayerDlg::Sound() 
{
	// TODO: Add your control notification handler code here
	if(m_bSound)
	{
		if(NAME(PlayM4_StopSound)())
		{
			m_bSound = FALSE;
			m_ctrlBtnSound.SetIcon(IDI_SOUND_DISABLE);
		}
	}
	else
	{
		if(NAME(PlayM4_PlaySound)(m_lPort))
		{
			m_ctrlBtnSound.SetIcon(IDI_SOUND_ENABLE);
			m_bSound = TRUE;
		}
	}
}

// adjust sound
void  CPlayerDlg::AdjustSound(BOOL bFlag)
{
	int nSoundPos = m_SoundSlider.GetPos();	

	if(bFlag)
	{
#ifdef _WAVE_ADJ
		nSoundPos += (MAX_WAVE_COEF - MIN_WAVE_COEF)/0xf;
		nSoundPos = min(nSoundPos, MAX_WAVE_COEF);
#else
		nSoundPos += 0xffff/0xf;
		nSoundPos = min(nSoundPos, 0xffff-1);
#endif
	}
	else
	{
#ifdef _WAVE_ADJ
		nSoundPos -= (MAX_WAVE_COEF - MIN_WAVE_COEF)/0xf;
		nSoundPos = max(nSoundPos, MIN_WAVE_COEF);
#else
		nSoundPos -= 0xffff/0xf;
		nSoundPos = max(nSoundPos, 0);
#endif
	}

#ifdef _WAVE_ADJ
		NAME(PlayM4_AdjustWaveAudio)(m_lPort, nSoundPos);
#else
		NAME(PlayM4_SetVolume)(m_lPort, WORD(nSoundPos));
#endif

	m_SoundSlider.SetPos(nSoundPos);
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* button operation over
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/




/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* menu operation begin
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
// file operation:
void CPlayerDlg::Open() 
{
	Close();
	SetState();

	if (m_lPort == -1)
	{
		PlayM4_GetPort(&m_lPort);
	}

	try
	{
		NAME(PlayM4_SetEncChangeMsg)(m_lPort, m_hWnd, WM_ENC_CHANGE);
		NAME(PlayM4_SetEncTypeChangeCallBack(m_lPort, EncChange, (long)this));

		if(m_bStreamType)
		{
			OpenStream();
		}
		else
		{
			OpenFile();
		}
		
		NAME(PlayM4_SetPicQuality)(m_lPort, m_bPicQuality);
		NAME(PlayM4_SetDeflash)(m_lPort, m_bDeflash);
//		NAME(PlayM4_SetPlayMode)(m_lPort, m_bHighFluid);

		m_bOpen = TRUE;
		
		NAME(PlayM4_GetPictureSize)(m_lPort, &m_nWidth, &m_nHeight);
		NAME(PlayM4_SetVolume)(m_lPort,WORD(m_SoundSlider.GetPos()));
		m_pDisplayRegion->SetResolution(m_nHeight, m_nWidth);
		m_pMainMenu->ModifyMenu(IDM_SETDISPLAY, MF_BYCOMMAND, IDM_SETDISPLAY, "Multi Display");
		// if video format is HCIF, then double the height
		if( (m_nWidth == WIDTH*2) && (m_nHeight <= HEIGHT_PAL) )
		{
			m_nHeight *= 2;
		}

		InitWindowSize(m_nWidth, m_nHeight);
	}
	catch(...)
	{
		Close();
	}
}


void CPlayerDlg::Close() 
{
	// TODO: Add your command handler code here
	if(m_bOpen)
	{
		if(m_bStreamType)
		{
			CloseStream();
		}
		else
		{
			CloseFile();	
		}

		if(m_pWatermarkDlg)
		{
			m_pWatermarkDlg->DestroyWindow();
		}

		m_nWidth = 352;
		m_nHeight = 288;

		
//		m_HikvisionBmp.LoadBitmap(IDB_HIKVISION);
// 		m_ctrlVideoPic.SetBitmap(m_HikvisionBmp);
// 		m_ctrlVideoPic.ShowWindow(SW_SHOW);
		SetWindowText("Player");
		m_ctrlVideoPic.Invalidate();
	}
}

void CPlayerDlg::CutFile() 
{
	// TODO: Add your command handler code here
	CCutFile cutDlg;
	if(cutDlg.SetFileName(m_strPlayFileName))
	{
		cutDlg.DoModal();
	}
}

void CPlayerDlg::SetSecretKey()
{
	CSetKeyDlg keyDlg(m_lPort);

	keyDlg.DoModal();
}

// view operation:
void CPlayerDlg::ViewFullScreen() 
{
	// TODO: Add your command handler code here
	m_bFullScreen = !m_bFullScreen;
	
	if(m_bFullScreen)
	{
		//Save the pre info;
		GetWindowPlacement(&m_OldWndpl);
		//Remove WS_SIZEBOX windows style. or not the window can't be full-creen.
		ModifyStyle(WS_SIZEBOX, 0, 0);
		
		CRect WindowRect, ClientRect;
		RECT  m_FullScreenRect;
		//ReDraw the window. Get the correct edge value.
//		GetWindowRect(&WindowRect);
//		WindowRect.left  += 1;
//		WindowRect.right += 1;
//		MoveWindow(CRect(0, 0, 352, 288), TRUE);
		
		GetWindowRect(&WindowRect);
		GetClientRect(&ClientRect);
		ClientToScreen(&ClientRect);
		
		//get the dest window rect.
		m_FullScreenRect.left   = WindowRect.left   - ClientRect.left + m_rcScreen.left;
		m_FullScreenRect.top    = WindowRect.top    - ClientRect.top  + m_rcScreen.top;
		m_FullScreenRect.right  = WindowRect.right  - ClientRect.right + m_rcScreen.right;
		m_FullScreenRect.bottom = WindowRect.bottom - ClientRect.bottom + m_rcScreen.bottom;
		//Move the main window to the dest rect.
		WINDOWPLACEMENT wndpl;
		wndpl.length  = sizeof(WINDOWPLACEMENT);
		wndpl.flags   = 0;
		wndpl.showCmd = SW_SHOWNORMAL;
		wndpl.rcNormalPosition = m_FullScreenRect;
		SetWindowPlacement(&wndpl);
		//Move the view winow to full-screen.
		RECT rc;
		GetClientRect(&rc);
		m_ctrlVideoPic.MoveWindow(&rc,TRUE);
	
		//Remove WS_VISIBLE window style.
		m_ctrlBtnPlay.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnPause.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnStop.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnFast.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnGEnd.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnSlow.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnGStart.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlStepBackward.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlStepForward.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnCapPic.ModifyStyle(WS_VISIBLE, 0, 0);
		m_ctrlBtnSound.ModifyStyle(WS_VISIBLE, 0, 0);

		GetDlgItem(IDC_INTER1)->ModifyStyle(WS_VISIBLE, 0, 0);
		GetDlgItem(IDC_INTER2)->ModifyStyle(WS_VISIBLE, 0, 0);
		GetDlgItem(IDC_INTER3)->ModifyStyle(WS_VISIBLE, 0, 0);

		m_SoundSlider.ModifyStyle(WS_VISIBLE,0,0);
		m_PlaySlider.ModifyStyle(WS_VISIBLE,0,0);

		m_ctrlPlayText.ModifyStyle(WS_VISIBLE,0,0);

	}
	else
	{
		//Visible the control.
		m_ctrlBtnPlay.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnPause.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnStop.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnFast.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnGEnd.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnSlow.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnGStart.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlStepForward.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlStepBackward.ModifyStyle(0, WS_VISIBLE, 0);
		m_ctrlBtnCapPic.ModifyStyle(0, WS_VISIBLE, 0);			
		m_ctrlBtnSound.ModifyStyle(0, WS_VISIBLE, 0);

		GetDlgItem(IDC_INTER1)->ModifyStyle(0, WS_VISIBLE, 0);
		GetDlgItem(IDC_INTER2)->ModifyStyle(0, WS_VISIBLE, 0);
		GetDlgItem(IDC_INTER3)->ModifyStyle(0, WS_VISIBLE, 0);

		m_PlaySlider.ModifyStyle(0,WS_VISIBLE,0);
		m_SoundSlider.ModifyStyle(0,WS_VISIBLE,0);

		m_ctrlPlayText.ModifyStyle(0,WS_VISIBLE,0);
		
		//make the window can be resize.
		ModifyStyle(0, WS_SIZEBOX, 0);
		//change the window pos to pre rect.
		SetWindowPlacement(&m_OldWndpl);

	}
	this->RedrawWindow();

	NAME(PlayM4_RefreshPlay)(m_lPort);
}

void CPlayerDlg::ViewZoom(UINT nID)
{
	if(m_bFullScreen)
	{
		ViewFullScreen();
	}

	for(int i = 0; i < 3; i++)
	{
		m_pMainMenu->CheckMenuItem(IDM_VIEW_ZOOM_50 + i, MF_UNCHECKED);
	}

	int nItem = nID - IDM_VIEW_ZOOM_100;

	switch(nItem)
	{
	case 0:
		InitWindowSize(m_nWidth, m_nHeight);
		break;

	case -1:
		InitWindowSize(m_nWidth >> 1, m_nHeight >> 1);
		break;

	case 1:
		InitWindowSize(m_nWidth << 1, m_nHeight << 1);
		break;

	default:
		break;
	}
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
}

void CPlayerDlg::Infomation() 
{
	// TODO: Add your command handler code here

	CInfo infoDlg;
	infoDlg.DoModal();
}

void CPlayerDlg::SetDisplay() 
{
	// TODO: Add your command handler code here

	RECT RectP;
	RECT RectS;

	if (!m_pDisplayRegion->m_bValid) 
	{	
		if(m_enumState == State_Play)
		{
			NAME(PlayM4_Pause)(m_lPort, TRUE);
			m_enumState = State_Pause;
			SetState();
		}
		
//		m_ctrlBtnCapPic.EnableWindow(FALSE);
//		m_ctrlBtnSound.EnableWindow(FALSE);	
//		m_ctrlBtnSlow.EnableWindow(FALSE);
//		m_ctrlBtnFast.EnableWindow(FALSE);
//		m_ctrlBtnGStart.EnableWindow(FALSE);
//		m_ctrlBtnGEnd.EnableWindow(FALSE);
//		m_ctrlBtnStop.EnableWindow(FALSE);
//		m_ctrlBtnPlay.EnableWindow(FALSE);
//		m_ctrlBtnPause.EnableWindow(FALSE);	
//		m_ctrlStepBackward.EnableWindow(FALSE);
//		m_ctrlStepForward.EnableWindow(FALSE);
// 		m_pMainMenu->EnableMenuItem(2, MF_GRAYED|MF_BYPOSITION|MF_DISABLED);
		m_pMainMenu->ModifyMenu(IDM_SETDISPLAY, MF_BYCOMMAND, IDM_SETDISPLAY, "Cancel Multi Display");
		
		m_pDisplayRegion->Create(IDD_RANGE);
		GetWindowRect(&RectP);
		
		m_pDisplayRegion->GetWindowRect(&RectS);
		
		RectS.right = RectS.right - RectS.left + RectP.right;
		RectS.left = RectP.right;
		RectS.bottom = RectS.bottom - RectS.top + RectP.top;
		RectS.top = RectP.top; 
		if (RectP.right + 10 > (int)m_dwScreenWidth) 
		{
			RectS.left = RectP.left - (RectS.right - RectS.left);
			RectS.right = RectP.left;
		}
		m_pDisplayRegion->MoveWindow(&RectS);
		
		
		m_pDisplayRegion->InitShow();
		ThrowB(IDM_THROW0);          // when step forward one by one, don't throw B frame;
//		NAME(PlayM4_OneByOne)(m_lPort);
//		m_enumState = State_Step;
		
		Sleep(50);
		m_pDisplayRegion->DrawRectangle();
	}
	else
	{
//		m_ctrlBtnCapPic.EnableWindow(TRUE);
//		m_ctrlBtnSound.EnableWindow(TRUE);	
//		m_ctrlBtnSlow.EnableWindow(TRUE);
//		m_ctrlBtnFast.EnableWindow(TRUE);
//		m_ctrlBtnGStart.EnableWindow(TRUE);
//		m_ctrlBtnGEnd.EnableWindow(TRUE);
//		m_ctrlBtnStop.EnableWindow(TRUE);
//		m_ctrlBtnPlay.EnableWindow(TRUE);
//		m_ctrlBtnPause.EnableWindow(TRUE);	
//		m_ctrlStepBackward.EnableWindow(TRUE);
//		m_ctrlStepForward.EnableWindow(TRUE);
// 		m_pMainMenu->EnableMenuItem(2, MF_ENABLED|MF_BYPOSITION);
		m_pMainMenu->ModifyMenu(IDM_SETDISPLAY, MF_BYCOMMAND, IDM_SETDISPLAY, "Multi Display"); 
		Play();
		SetState();
		m_pDisplayRegion->DestroyWindow();
	}
}

BOOL CPlayerDlg::SetDevice(UINT nID)
{
	BOOL bFunctionOK = FALSE;

#if (WINVER > 0x0400)
	DWORD nVal = NAME(PlayM4_GetDDrawDeviceTotalNums)();
	if(nVal >= 1)
	{
		UINT nDeviceSeq = nID - IDM_DEVICE0;
		for(int i = 0; i < MAX_DISPLAY_DEVICE; i++)
		{
			m_pMainMenu->CheckMenuItem(IDM_DEVICE0 + i, MF_UNCHECKED);
		}

		if(NAME(PlayM4_SetDDrawDevice)(m_lPort, nDeviceSeq + 1))
		{
			bFunctionOK = TRUE;
		}
		
		NAME(PlayM4_SetDDrawDeviceEx)(m_lPort, 1, nDeviceSeq + 1);
		m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
	}
#endif

	return bFunctionOK;
}

// control operation:
void CPlayerDlg::VideoControl()
{
	// TODO: Add your command handler code here

	m_pVideoControl->Create(IDD_VIDEOCTRL);
	m_pVideoControl->ShowWindow(SW_SHOW);
	m_pMainMenu->EnableMenuItem(IDM_VIDEO_CONTROL, MF_GRAYED | MF_DISABLED);
}

void CPlayerDlg::Repeat() 
{
	// TODO: Add your command handler code here

	m_bRepeatPlay = !m_bRepeatPlay;
	UINT nFlag = m_bRepeatPlay ? MF_CHECKED : MF_UNCHECKED;
	m_pMainMenu->CheckMenuItem(IDM_REPEAT, nFlag);
}

void CPlayerDlg::Locate() 
{
	// TODO: Add your command handler code here

	m_pSeek->Create(IDD_SEEK);
	m_pMainMenu->EnableMenuItem(IDM_SEEK,MF_GRAYED | MF_DISABLED);
}

// option operation:
void CPlayerDlg::StreamType() 
{
	// TODO: Add your command handler code here

	m_bStreamType = !m_bStreamType;
	UINT nFlag = m_bStreamType ? MF_CHECKED : MF_UNCHECKED;
	m_pMainMenu->CheckMenuItem(IDM_STREAM_TYPE, nFlag);
}

void CPlayerDlg::Deflash() 
{
	// TODO: Add your command handler code here

	m_bDeflash = !m_bDeflash;
	UINT nFlag = m_bDeflash ? MF_CHECKED : MF_UNCHECKED;
	m_pMainMenu->CheckMenuItem(IDM_DEFLASH, nFlag);

	NAME(PlayM4_SetDeflash)(m_lPort, m_bDeflash);
}

void CPlayerDlg::Quality() 
{
	// TODO: Add your command handler code here

	m_bPicQuality = !m_bPicQuality;
	UINT nFlag = m_bPicQuality ? MF_CHECKED : MF_UNCHECKED;
	m_pMainMenu->CheckMenuItem(IDM_QUALITY, nFlag);

	NAME(PlayM4_SetPicQuality)(m_lPort, m_bPicQuality);
}

void CPlayerDlg::HighFluid()
{
	// TODO: Add your command handler code here

	m_bHighFluid = !m_bHighFluid;
	UINT nFlag = m_bHighFluid ? MF_CHECKED : MF_UNCHECKED;
	m_pMainMenu->CheckMenuItem(IDM_PREVIEW50, nFlag);

	NAME(PlayM4_SetPlayMode)(m_lPort, m_bHighFluid);
}

void CPlayerDlg::ImageSharpenLevel(UINT nID)
{
	UINT nOldID = IDM_SHARPEN_NONE + m_dwImageSharpenLevel;
	m_dwImageSharpenLevel = nID - IDM_SHARPEN_NONE;

	NAME(PlayM4_SetImageSharpen)(m_lPort, m_dwImageSharpenLevel);
	
	m_pMainMenu->CheckMenuItem(nOldID, MF_UNCHECKED);
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
}

void CPlayerDlg::ThrowB(UINT nID)
{
	NAME(PlayM4_ThrowBFrameNum)(m_lPort, nID - IDM_THROW0);

	for(int i = IDM_THROW0; i <= IDM_THROW2; i++ )
	{
		m_pMainMenu->CheckMenuItem(i, MF_UNCHECKED);
	}
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
}

void CPlayerDlg::SetDecodeType(UINT nID)
{
	NAME(PlayM4_SetDecodeFrameType)(m_lPort, nID - IDM_DECODE_NORMAL);

	for(int i = IDM_DECODE_NORMAL; i <= IDM_DECODE_NONE; i++ )
	{
		m_pMainMenu->CheckMenuItem(i, MF_UNCHECKED);
	}
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
}

void CPlayerDlg::DisplayType(UINT nID)
{
	m_pMainMenu->CheckMenuItem(IDM_DISNORMAL,  MF_UNCHECKED);
	m_pMainMenu->CheckMenuItem(IDM_DISQUARTER, MF_UNCHECKED);
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);

	if(nID == IDM_DISNORMAL)
	{
		NAME(PlayM4_SetDisplayType)(m_lPort, DISPLAY_NORMAL);
	}
	else
	{
		NAME(PlayM4_SetDisplayType)(m_lPort, DISPLAY_QUARTER);
	}
}

void CPlayerDlg::SelectTimer(UINT nID)
{
	for (int i = IDM_TIMERNULL; i < IDM_TIMER2; i++)
	{
		m_pMainMenu->CheckMenuItem(i, MF_UNCHECKED);
	}
	
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);

	NAME(PlayM4_SetTimerType)(m_lPort, nID - IDM_TIMERNULL, 0);
}

void CPlayerDlg::ResetBuf() 
{
	// TODO: Add your command handler code here
	// Only test the interface. 
	NAME(PlayM4_ResetBuffer)(m_lPort, BUF_VIDEO_RENDER);
	NAME(PlayM4_ResetBuffer)(m_lPort, BUF_AUDIO_RENDER);
	NAME(PlayM4_ResetBuffer)(m_lPort, BUF_VIDEO_SRC);
	NAME(PlayM4_ResetBuffer)(m_lPort, BUF_AUDIO_SRC);
}

void CPlayerDlg::CapPicType(UINT nID)
{
	m_pMainMenu->CheckMenuItem(IDM_CAP_BMP,  MF_UNCHECKED);
	m_pMainMenu->CheckMenuItem(IDM_CAP_JPEG, MF_UNCHECKED);
	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);

	if(nID == IDM_CAP_BMP)
	{
		m_nCapPicType = 0;
	}
	else
	{
		m_nCapPicType = 1;
	}
}

void CPlayerDlg::CappicPath() 
{
	char	     szDir[MAX_PATH];
	BROWSEINFO   bi;
	ITEMIDLIST  *pidl;

	bi.hwndOwner	  = this->m_hWnd;
	bi.pidlRoot		  = NULL;
	bi.pszDisplayName = szDir;
	bi.lpszTitle	  = "请选择目录";
	bi.ulFlags		  = BIF_RETURNONLYFSDIRS;
	bi.lpfn			  = NULL;
	bi.lParam		  = 0;
	bi.iImage		  = 0;

	pidl = SHBrowseForFolder(&bi);
	if(NULL == pidl)
	{
		return;
	}

	if(!SHGetPathFromIDList(pidl, szDir)) 
	{
		return;
	}

	m_strCapPicPath.Format("%s",szDir);
}

void CPlayerDlg::ConvertToAVI() 
{
	// TODO: Add your command handler code here	
	int ReturnValue;
	CString str, m_csInfo;

	str.Format("Convert  to AVI File will be Failed to Play the MPEG4 File\n\n");
	m_csInfo += str;
	str.Format("The Converted AVI File can't be Larger than 2G!\n\n");
	m_csInfo += str;
	str.Format("Playing the Converted AVI File must Install the Divx!\n\n");
	m_csInfo += str;
	str.Format("if Continued,Click OK Button!\n");
    m_csInfo += str;
	ReturnValue = MessageBox((LPCTSTR)m_csInfo, NULL, MB_YESNO); 
	

	if(ReturnValue == IDYES)
	{
		Close();

		m_bConvertAVI = TRUE;
		str.Format("AVI Movie Files (*.avi)|*.avi||");
	   
		CFileDialog Filedlg(FALSE, "*.avi", "*.avi", OFN_LONGNAMES|OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT, str, this);
	   
		if(Filedlg.DoModal() == IDOK)
		{
			m_strSaveAVIPath = Filedlg.GetPathName();
		  
		    if(BrowseFile(&m_strPlayFileName))
			{
				Open();
			
				if(m_bConvertAVI)
				{
					SetAVIState();
				}
				else
				{
					SetState();
				}
				SortControl();
			}
			else
			{
				m_bConvertAVI = FALSE;
				SetState();
			}
		}
		else
		{
			m_bConvertAVI = FALSE;
			SetState();
		}
	}
}

void CPlayerDlg::AppAbout() 
{
	// TODO: Add your command handler code here
	CAboutDlg AboutDlg;
	AboutDlg.DoModal();
	
}

void CPlayerDlg::AppHelp()
{
	CHelpDlg HelpDlg;
	HelpDlg.DoModal();
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* menu operation over
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/



/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* when you click the menu item, you come here
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
void CPlayerDlg::OnMenuItem(UINT nID)
{
	switch(nID)
	{
	case IDM_FILE_OPEN:
		if(BrowseFile(&m_strPlayFileName)) 
		{
			Open();
			SetState();
		}
		break;
		
	case IDM_FILE_CLOSE:
		Close();
		SetState();
		break;
	
/*	case IDM_CUT_FILE:
		CutFile();
		break;
*/
	case IDM_SET_KEY:
		SetSecretKey();
		break;

	case IDM_APP_EXIT:
		SendMessage(WM_CLOSE);
		break;

	case IDM_VIEW_FULLSCREEN:
		ViewFullScreen();
		break;

	case IDM_VIEW_ZOOM_50:
	case IDM_VIEW_ZOOM_100:
	case IDM_VIEW_ZOOM_200:
		ViewZoom(nID);
		break;
	
	case IDM_INFO:
		Infomation();
		break;
	
	case IDM_SETDISPLAY:
		SetDisplay();
		break;
	
	case IDM_DEVICE0:
	case IDM_DEVICE1:
	case IDM_DEVICE2:
	case IDM_DEVICE3:
		SetDevice(nID);
		break;

	case IDM_WATERMARK:
		GetWatermark();
		break;

	case IDM_PLAY_PAUSE:
		if(m_enumState == State_Play)
		{
			Pause();
			SetState();
		}
		else if(m_enumState == State_Pause || m_enumState == State_Stop)
		{
			Play();
			SetState();
		}
		break;

	case IDM_STOP:
		if(m_enumState != State_Close)
		{
			Stop();
			SetState();
		}
		break;

	case IDM_STEPFORWARD:
		if(m_enumState != State_Stop)
		{
			StepForward();
			SetState();
		}
		break;
		
	case IDM_STEPBACKWARD:
		if(m_enumState != State_Stop)
		{
			StepBackward();
			SetState();
		}
		break;

	case IDM_GOTOSTART:
		GotoStart();
		break;

	case IDM_GOTOEND:
		GotoEnd();
		break;

	case IDM_SEEK:
		Locate();
		break;

	case IDM_VIDEO_CONTROL:
		VideoControl();
		break;

	case IDM_REPEAT:
		Repeat();
		break;
	
	case IDM_STREAM_TYPE:
		StreamType();
		break;
	
	case IDM_DEFLASH:
		Deflash();
		break;
		
	case IDM_QUALITY:
		Quality();
		break;
	
	case IDM_PREVIEW50:
		HighFluid();
		break;
		
	case IDM_SHARPEN_NONE:
	case IDM_SHARPEN_LEVEL1:
	case IDM_SHARPEN_LEVEL2:
	case IDM_SHARPEN_LEVEL3:
	case IDM_SHARPEN_LEVEL4:
	case IDM_SHARPEN_LEVEL5:
	case IDM_SHARPEN_LEVEL6:
		ImageSharpenLevel(nID);
		break;

	case IDM_THROW0:
	case IDM_THROW1:                      
	case IDM_THROW2:
		ThrowB(nID);
		break;

	case IDM_DECODE_NORMAL:
	case IDM_DECODE_I:
	case IDM_DECODE_NONE:
		SetDecodeType(nID);
		break;

	case IDM_DISNORMAL:                   
	case IDM_DISQUARTER:
		DisplayType(nID);
		break;

	case IDM_TIMER1:
	case IDM_TIMER2:
	case IDM_TIMERNULL:
		SelectTimer(nID);
		break;

	case IDM_RESET_BUF:
		ResetBuf();
		break;

	case IDM_CAP_BMP:
	case IDM_CAP_JPEG:
		CapPicType(nID);
		break;

	case IDM_CAPPIC_PATH:
		CappicPath();
		break;
		
/*	case IDM_CONVERT:
		ConvertToAVI();
		break;
*/	
	case IDM_APP_HELP:
		AppHelp();
		break;
		
	case IDM_APP_ABOUT:
		AppAbout();
		break;
	case IDM_BYRATE:
	case IDM_BYTIME:
		SetDiplayMode(nID);

	default:
		break;
	}
}

void CPlayerDlg::GetWatermark()
{
	// TODO: Add your command handler code here
//	WaterMarkDlg dlg;
//	dlg.DoModal();
	m_pWatermarkDlg->Create(IDD_WATERMARK);
	m_pMainMenu->EnableMenuItem(IDM_WATERMARK, MF_GRAYED);
}

//错误信息
char* CPlayerDlg::MyErrorToString(DWORD error)
{
	switch(error)
	{
	case 0:
		return "No error.\0";
    case 1:
      return "The parameter that user inputted is invalid.\0";
    case 2:
      return "The order of the function to be called is incorrect.\0";
    case 3:
      return "Failure when creating system multimedia clock.\0";
    case 4:
      return "Failure when decoding video data.\0";
    case 5:
      return "Failure when decoding audio data.\0";
    case 6:
      return "Failure when allocating memory.\0";
    case 7:
      return "File open failed when calling API Hik_PlayM4_OpenFile.\0";
	case 8:
      return "Failure when creating thread or event.\0";
	case 9:
      return "Failure when creating directdraw object.\0";
	case 10:
      return "Failure when creating off-screen surface.\0";
	case 11:
      return "The input source buffer has overflowed when calling API Hik_PlayM4_InputData.\0";
	case 12:
      return "Failure when creating audio device.\0";
	case 13:
      return "Failure when setting audio volume.\0";
	case 14:
      return "The function only supports playing a file.\0";
	case 15:
      return "The function only supports playing a stream.\0";
	case 16:
      return "Neither MMX nor SSE arithmetic is supported by system.\0";
	case 17:
      return "Unknown file header.\0";
	case 18:
      return "The version of video decoder and video encoder is not compatible.\0";
	case 19:
      return "Failure when initializing decoder.\0";
	case 20:
      return "The file data is unknown. No I-frame found.\0";
	case 21:
      return "Failure when initializing multimedia clock.\0";
	case 22:
      return "Failure when blitting overlay.\0";
	case 23:
      return "Failure when updating overlay or offscreen surface.\0";
	case 24:
      return "Open file error, streamtype is multi.\0";
	case 25:
      return "Openfile error, streamtype is video.\0";
	case 26:
      return "JPEG compression error when capturing jpeg file.\0";
	case 27:
      return "Version of this file not supported when extracting h264 video data.\0";
	case 28:
      return "Failure when extracting video data.\0";
   default:
      return "Unrecognized error value.\0";
	}
}


/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* when you click the button item, you come here
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
void CPlayerDlg::OnButtonItem(UINT nID)
{
	switch(nID)
	{
	case IDC_PLAY:
		Play();
		break;

	case IDC_PAUSE:
		Pause();
		break;

	case IDC_STOP:
		Stop();
		break;

	case IDC_GOTOSTART:
		GotoStart();
		break;

	case IDC_SLOW:
		Play();
		Slow();
		break;

	case IDC_FAST:
		Play();
		Fast();
		break;

	case IDC_GOTOEND:
		GotoEnd();
		break;

	case IDC_STEP:
		StepForward();
		break;
		
	case IDC_STEPBACK:
		StepBackward();
		break;
		
	case IDC_CAPPIC:
		Cappic();
		break;
		
	case IDC_SOUND:
		Sound();
		break;
	
	default:
		break;
	}

	SetState();
}

void CPlayerDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	PlayM4_ReleaseDDrawDevice();
	// TODO: Add your message handler code here
	if(m_pQcifTempBuf)
	{
		delete []m_pQcifTempBuf;
		m_pQcifTempBuf = NULL;
	}
}

LRESULT CPlayerDlg::WatermarkOk(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	m_pWatermarkDlg->DestroyWindow();
	if(m_enumState == State_Pause || m_enumState == State_Play)
	{
		m_pMainMenu->EnableMenuItem(IDM_WATERMARK, MF_ENABLED);
	}

	return S_OK;
}

BOOL CPlayerDlg::SetDiplayMode(int nID)
{
//	for (int i = IDM_BYRATE; i < IDM_BYTIME; i++)
//	{
//		m_pMainMenu->CheckMenuItem(i, MF_UNCHECKED);
//	}
//	
//	m_pMainMenu->CheckMenuItem(nID, MF_CHECKED);
//
//	return PlayM4_SetDisplayMode(m_lPort, nID - IDM_BYRATE);

	return FALSE;
}

我比较喜欢的是关于AVI的封装部分:

#ifndef _AVIFMT_H_
#define _AVIFMT_H_

//
//
//

#ifndef DWORD
#define DWORD unsigned long
#endif

#ifndef WORD
#define WORD unsigned short
#endif

#ifndef FOURCC
#define FOURCC unsigned long
#endif

//
//
//

//
// Flags for "avih" chunk
//
#define AVIF_HASINDEX		0x00000010	// Index at end of file
#define AVIF_MUSTUSEINDEX	0x00000020
#define AVIF_ISINTERLEAVED	0x00000100
#define AVIF_TRUSTCKTYPE	0x00000800	// Use CKType to find key frames
#define AVIF_WASCAPTUREFILE	0x00010000
#define AVIF_COPYRIGHTED	0x00020000

//
// Flags for "strh" chunk
//
#define AVISF_DISABLED				0x00000001
#define AVISF_VIDEO_PALCHANGES		0x00010000

//
// Flags for "idx1" chunk
//
#define AVIIF_LIST          0x00000001L // chunk is a 'LIST'
#define AVIIF_KEYFRAME      0x00000010L // this frame is a key frame.
#define AVIIF_NOTIME	    0x00000100L // this frame doesn't take any time
#define AVIIF_COMPUSE       0x0FFF0000L // these bits are for compressor use

//
//
//

typedef struct
{
    DWORD		dwMicroSecPerFrame;			// frame display rate (or 0L)
    DWORD		dwMaxBytesPerSec;			// max. transfer rate
    DWORD		dwPaddingGranularity;		// pad to multiples of this
                                            // size; normally 2K.
    DWORD		dwFlags;					// the ever-present flags
    DWORD		dwTotalFrames;				// # frames in file
    DWORD		dwInitialFrames;
    DWORD		dwStreams;
    DWORD		dwSuggestedBufferSize;

    DWORD		dwWidth;
    DWORD		dwHeight;

    DWORD		dwReserved[4];
} MainAVIHeader;

typedef struct {
    FOURCC		fccType;
    FOURCC		fccHandler;
    DWORD		dwFlags;					// Contains AVITF_* flags
    WORD		wPriority;
    WORD		wLanguage;
    DWORD		dwInitialFrames;
    DWORD		dwScale;	
    DWORD		dwRate;						// dwRate / dwScale == samples/second
    DWORD		dwStart;
    DWORD		dwLength;					// In units above...
    DWORD		dwSuggestedBufferSize;
    DWORD		dwQuality;
    DWORD		dwSampleSize;
	DWORD		dwTop;
	DWORD		dwLeft;
	DWORD		dwRight;
	DWORD		dwBottom;
} AVIStreamHeader;

typedef struct
{
    DWORD		ckid;
    DWORD		dwFlags;
    DWORD		dwChunkOffset;		// Position of chunk
    DWORD		dwChunkLength;		// Length of chunk
} AVIINDEXENTRY;

//
//
//


#endif _AVIFMT_H_

#ifndef _WRIFF_H_
#define _WRIFF_H_

//
//
//
// RIFF.H -- Interface for wrinting RIFF files
//
// By Nitzan Shaked
//
//
//

#include <stdio.h>
//#include "avifmt.h"
//
//
//

//
// Chunk types a riff file can contain
//
typedef enum riffSectionType
{
	RIFF_SECTION_LIST	= 0,					// "LIST" (size) "TYPE" (data)
	RIFF_SECTION_CHUNK	= 1						// "name" (size) (data)
};

//
// Structure used to hold information about a chunk
//
typedef struct _riffSection
{
	riffSectionType	type;				// LIST or CHUNK
	long			sizeOffset;			// Offset in file where size is to be written
	long			currentSize;		// Current size (including subchunks, if any)
} riffSection;

//
// Maximum nesting level for riff files
//
#define MAX_RIFF_NESTING_LEVEL 20

//
// Stack used to hold current structure of riff file
//
typedef riffSection riffStack[MAX_RIFF_NESTING_LEVEL];

//
// Information about one riff file
//
typedef struct _riffFile
{
	FILE		*f;						// The file handler
	riffStack	stack;
	long		stackTop;				// Stack top (-1 if empty)
} riffFile;

//
// Names and types of lists and chunks
//
typedef char *str4;

//
//
//

//
// Create a new riff file and return a pointer to a "riffFile"
//
// Return NULL if failure
//
riffFile *riffCreate( LPCTSTR filename );

//
// Close a riff file
//
bool riffClose( riffFile *f );

//
// Pads the file to WORD boundry (adds a 0 byte if necessary)
//
bool riffPadWord( riffFile *f );

//
// Pads the file to a given granularity from a given position
//
bool riffPadJunk(	riffFile	*f,
					long		granularity,
					long		from );

//
// Adds a LIST to a riff file
//
bool riffAddList(	riffFile	*f,
					str4		type,				// "LIST" or "RIFF"
					str4		name );

//
// Adds a CHUNK to a riff file
//
bool riffAddChunk(	riffFile	*f,
					str4		name );

//
// Writes data to the riff file
//
bool riffWriteData(	riffFile	*f,
					void		*buf,
					long		size );

//
// Returns the current position (size) of the riff file
//
long riffSize( riffFile *f );

//
// Closes last section in the riff file
//
bool riffCloseSection( riffFile *f );
bool riffCloseChunk( riffFile *f );
bool riffCloseList( riffFile *f );

//
//
//

#endif _WRIFF_H_

//
//
//
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <windows.h>
#include <mmsystem.h>
#include "avifmt.h"

#include "wriff.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//
//
//

//

riffFile *riffCreate( LPCTSTR filename )
{
	riffFile	*result;


	if ( (result = (riffFile*)malloc( sizeof(riffFile) )) == NULL )
	{
		//fprintf( stderr, "Error - riffCreate() - can't allocate memory for riffFile\n" );
		return NULL;
	}

	if ( (result->f = fopen( filename, "wb" )) == NULL )
	{
		//fprintf( stderr, "Error - riffCreate() - can't create <%s>\n", filename );
		free( result );
		return NULL;
	}

	result->stackTop = -1;

	return result;
}

//
//
//

bool riffClose( riffFile *f )
{
	while( f->stackTop > -1 )
	{
		riffCloseSection( f );
	}

	if ( fclose( f->f ) != 0 )
	{
	//	fprintf( stderr, "Error - riffClose() - can't close RIFF file\n" );
		return false;
	}

	//free( f );

	return true;
}

//
//
//

bool riffPadWord( riffFile *f )
{
	char	dummy = 0;


	if ( ftell( f->f ) % 2 == 1 )
	{
		fwrite( &dummy, 1, 1, f->f );
	}

	return true;
}

//
//
//

#define MAX_GRAN 2048

bool riffPadJunk(	riffFile	*f,
					long		granularity,
					long		from )
{
	long	currentSize;


	if ( granularity > MAX_GRAN )
	{
		//fprintf( stderr, "Error - riffPadJunk() - granularity greater than %d\n", MAX_GRAN );
		return false;
	}

	if ( f->stack[ f->stackTop ].type != RIFF_SECTION_LIST )
	{
		//fprintf( stderr, "Error - riffPadJunk() - current section type is not LIST\n" );
		return false;
	}
	
	currentSize = ( riffSize( f ) - from ) % granularity;
	if ( currentSize != 0 )
	{
		char	buf[MAX_GRAN];

		currentSize = ( currentSize + 8 ) % granularity;
		memset( buf, 0, granularity );

		riffAddChunk( f, "JUNK" );
		riffWriteData( f, buf, granularity-currentSize );
		riffCloseChunk( f );
	}

	return true;
}

//
//
//

bool riffAddList(	riffFile	*f,
					str4		type,				// "LIST" or "RIFF"
					str4		name )
{
	if ( f->stackTop == MAX_RIFF_NESTING_LEVEL )
	{
		//fprintf( stderr, "Error - riffAddList() - maximum nesting level reached\n" );
		return false;
	}

	if ( f->stackTop > -1 )
	{
		if ( f->stack[ f->stackTop ].type != RIFF_SECTION_LIST )
		{
			//fprintf( stderr, "Error - riffAddList() - current section type is not LIST\n" );
			return false;
		}
	}

	(f->stackTop)++;

	f->stack[ f->stackTop ].type		= RIFF_SECTION_LIST;
	f->stack[ f->stackTop ].sizeOffset	= ftell( f->f ) + 4;
	f->stack[ f->stackTop ].currentSize	= 0;

	fwrite( type, 1, 4, f->f );			// "LIST" or "RIFF"
	fwrite( "xxxx", 1, 4, f->f );		// reserve room for size
	fwrite( name, 1, 4, f->f );

	return true;
}

//
//
//

bool riffAddChunk(	riffFile	*f,
					str4		name )
{
	if ( f->stackTop == MAX_RIFF_NESTING_LEVEL )
	{
		//fprintf( stderr, "Error - riffAddChunk() - maximum nesting level reached\n" );
		return false;
	}

	if ( f->stack[ f->stackTop ].type != RIFF_SECTION_LIST )
	{
		//fprintf( stderr, "Error - riffAddChunk() - current section type is not LIST\n" );
		return false;
	}

	(f->stackTop)++;

	f->stack[ f->stackTop ].type		= RIFF_SECTION_CHUNK;
	f->stack[ f->stackTop ].sizeOffset	= ftell( f->f ) + 4;
	f->stack[ f->stackTop ].currentSize	= 0;

	fwrite( name, 1, 4, f->f );
	fwrite( "xxxx", 1, 4, f->f );		// reserve room for size

	return true;
}

//
//
//

bool riffWriteData(	riffFile	*f,
					void		*buf,
					long		size )
{
	if ( (long)fwrite( buf, 1, size, f->f ) != size )
	{
		//fprintf( stderr, "Error - riffWriteData() - fwrite() didn't return expected result\n" );
		return false;
	}

	f->stack[ f->stackTop ].currentSize += size;

	return true;
}

//
//
//

long riffSize( riffFile *f )
{
	return ftell( f->f );
}

//
//
//

bool riffCloseSection( riffFile *f )
{
	long	sizeToAdd;


	if ( f->stackTop == -1 )
	{
		//fprintf( stderr, "Error - riffCloseSection() - stack underflow\n" );
		return false;
	}

	if ( f->stack[ f->stackTop ].type == RIFF_SECTION_LIST )
	{
		f->stack[ f->stackTop ].currentSize += 4;
	}

	fseek( f->f, f->stack[ f->stackTop ].sizeOffset, SEEK_SET );
	fwrite( &(f->stack[ f->stackTop ].currentSize), 1, 4, f->f );
	fseek( f->f, 0, SEEK_END );

	switch ( f->stack[ f->stackTop ].type )
	{
	case RIFF_SECTION_LIST:
		sizeToAdd = 12;
		break;

	case RIFF_SECTION_CHUNK:
		sizeToAdd = 8;
		break;

	default:
		//fprintf( stderr, "Error - riffCloseSection() - unexpected section type\n" );
		sizeToAdd = 0;
	}

	if ( f->stack[ f->stackTop ].type == RIFF_SECTION_LIST )
	{
		f->stack[ f->stackTop ].currentSize -= 4;
	}

	if ( f->stackTop > 0 )
	{
		f->stack[ f->stackTop - 1 ].currentSize += ( f->stack[ f->stackTop ].currentSize + sizeToAdd );
	}

	(f->stackTop)--;

	return true;
}

//
//
//

bool riffCloseChunk( riffFile *f )
{
	return riffCloseSection( f );
}

//
//
//

bool riffCloseList( riffFile *f )
{
	return riffCloseSection( f );
}

//
//
//
/**/

#ifndef __CONVERT_TO_AVI__
#define __CONVERT_TO_AVI__

#include <mmsystem.h>
#include "AVIFMt.H"
#include "WRIFF.H"

#define WRITE_REC_LIST             // do write REC list?
#define WRITE_INDEX				   // do write index?
#define ALIGN_VIDEO_FRAMES	       // do align video frames?

#define MAX_FILE_LEN  2048000000   // the AVI file now can't exceed 2G

#define PADDING_GRANULARITY 2048   // padding size

typedef struct 
{
	DWORD				 dwFrameWidth;
	DWORD				 dwFrameHeight;
	DWORD				 dwFrameSize;
	DWORD				 dwFPS;
	DWORD				 dwTotalFrames; 
}AVI_CONVERT_PARA;


class CConvertAVI
{
public:
	CConvertAVI();
	virtual ~CConvertAVI();
	
public:
	
	DWORD                m_dwCurFrameNum;
	DWORD				 m_dwMaxFrames;
	BOOL				 m_bWriteHdr;
	riffFile			*m_pOutAVI;
	AVI_CONVERT_PARA     m_strAVIPara;
	
#ifdef WRITE_INDEX
	AVIINDEXENTRY*		 m_pIndexes;
	DWORD				 m_nMoviOffset;
#endif // WRITE_INDEX
	DWORD				 m_dwFirstFrameOffset;


public:
	BOOL WriteHeaders();
	BOOL AddFileToAVI(char* pBuf, DWORD nSize);
	BOOL CloseWriffFiles();

	BOOL InitResource(AVI_CONVERT_PARA* pParam, CString strAVIPath);
	void ReleaseResource();

	BOOL  IsWriteAVIHdr();
	BOOL  IsExceedMaxFileLen();
	DWORD GetCurFrameNum();
	void  SetFPS(DWORD nFps);
};

#endif

#include "StdAfx.h"
#include "CConvertAVI.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CConvertAVI::CConvertAVI()
{
	m_pOutAVI    = NULL;
	m_pIndexes   = NULL;
	m_dwMaxFrames = 0;
	ZeroMemory(&m_strAVIPara, sizeof(AVI_CONVERT_PARA));
}

CConvertAVI::~CConvertAVI()
{
}

BOOL CConvertAVI::InitResource(AVI_CONVERT_PARA* pParam, CString strAVIPath)
{
	m_dwCurFrameNum	    = 0;
	m_dwFirstFrameOffset = 0;
	m_bWriteHdr			= TRUE;

	CopyMemory(&m_strAVIPara, pParam, sizeof(AVI_CONVERT_PARA));
	
	m_dwMaxFrames = MAX_FILE_LEN/m_strAVIPara.dwTotalFrames;

#ifdef WRITE_INDEX
	m_pIndexes = new AVIINDEXENTRY[m_dwMaxFrames];
	if(NULL == m_pIndexes)
	{
		return FALSE;
	}
	ZeroMemory(m_pIndexes,  m_dwMaxFrames * sizeof(AVIINDEXENTRY));
	m_nMoviOffset = 0;
#endif 

	m_pOutAVI = riffCreate( LPCTSTR(strAVIPath) );
	if ( m_pOutAVI == NULL )
	{
		ReleaseResource();
		return FALSE;
	}

	return TRUE;
}

void CConvertAVI::ReleaseResource()
{
	if(m_pOutAVI != NULL)
	{
		TRACE("Close wriff files.\n");
		CloseWriffFiles();
		m_pOutAVI = NULL;
	}

#ifdef WRITE_INDEX
	if(m_pIndexes != NULL)
	{
		TRACE("Delete m_pIndexes.\n");
		delete [] m_pIndexes;
		m_pIndexes = NULL;
	}
#endif

	ZeroMemory(&m_strAVIPara, sizeof(AVI_CONVERT_PARA));
}

BOOL CConvertAVI::IsWriteAVIHdr()
{
	return m_bWriteHdr;
}

BOOL CConvertAVI::WriteHeaders()
{
	MainAVIHeader		 mainAviHeader;
	AVIStreamHeader		 aviStreamHeader;
	BITMAPINFOHEADER	 bitmapHeader;
	DWORD fcc;
	riffAddList( m_pOutAVI, "RIFF", "AVI " );
	//
	// Write hdr1 list
	//
	riffAddList( m_pOutAVI, "LIST", "hdrl" );
	mainAviHeader.dwMicroSecPerFrame		= 1000000 / (m_strAVIPara.dwFPS);
	mainAviHeader.dwMaxBytesPerSec			= m_strAVIPara.dwFrameSize + PADDING_GRANULARITY;	// Spare
	mainAviHeader.dwPaddingGranularity		= 0;
	mainAviHeader.dwFlags					= AVIF_HASINDEX;
	mainAviHeader.dwTotalFrames				= m_strAVIPara.dwTotalFrames;
	mainAviHeader.dwInitialFrames			= 0;
	mainAviHeader.dwStreams					= 1;
	mainAviHeader.dwSuggestedBufferSize		= m_strAVIPara.dwFrameSize + PADDING_GRANULARITY;	// Spare
	mainAviHeader.dwWidth					= m_strAVIPara.dwFrameWidth;
	mainAviHeader.dwHeight					= m_strAVIPara.dwFrameHeight;
	mainAviHeader.dwReserved[0]				= 0;
	mainAviHeader.dwReserved[1]				= 0;
	mainAviHeader.dwReserved[2]				= 0;
	mainAviHeader.dwReserved[3]				= 0; 

	riffAddChunk  ( m_pOutAVI, "avih" );
	riffWriteData ( m_pOutAVI, &mainAviHeader, sizeof( mainAviHeader ) );
	riffCloseChunk( m_pOutAVI );
	//
	// Write the "strl" video list
	//
	riffAddList( m_pOutAVI, "LIST", "strl" );
	//
	// Write the "strh" chunk	
	//
	fcc = mmioFOURCC( 'Y', 'V', '1', '2' );
	aviStreamHeader.fccType					= mmioFOURCC( 'v', 'i', 'd', 's' );
	aviStreamHeader.fccHandler				= 0;
	aviStreamHeader.dwFlags					= fcc;
	aviStreamHeader.wPriority				= 0;
	aviStreamHeader.wLanguage				= 0;
	aviStreamHeader.dwInitialFrames			= 0;
	aviStreamHeader.dwScale					= 1;
	aviStreamHeader.dwRate					= m_strAVIPara.dwFPS;
	aviStreamHeader.dwStart					= 0;
	aviStreamHeader.dwLength				= m_strAVIPara.dwTotalFrames;
	aviStreamHeader.dwSuggestedBufferSize	= m_strAVIPara.dwFrameSize + PADDING_GRANULARITY;
	aviStreamHeader.dwQuality				= 0xFFFFFFFF;				// -1
	aviStreamHeader.dwSampleSize			= 0;
	aviStreamHeader.dwTop					= 0;
	aviStreamHeader.dwLeft					= 0;
	aviStreamHeader.dwRight					= 0;
	aviStreamHeader.dwBottom				= 0;


	riffAddChunk  ( m_pOutAVI, "strh" );
	riffWriteData ( m_pOutAVI, &aviStreamHeader, sizeof( aviStreamHeader ) );
	riffCloseChunk( m_pOutAVI );
	//
	//
	// Write the "strf" chunk
	//
	bitmapHeader.biSize				= sizeof( bitmapHeader );
	bitmapHeader.biWidth			= m_strAVIPara.dwFrameWidth;
	bitmapHeader.biHeight			= m_strAVIPara.dwFrameHeight;
	bitmapHeader.biPlanes			= 1;
	bitmapHeader.biBitCount			= 12;
	bitmapHeader.biCompression		= fcc;
	bitmapHeader.biSizeImage		= m_strAVIPara.dwFrameSize;
    bitmapHeader.biXPelsPerMeter	= 0;
    bitmapHeader.biYPelsPerMeter	= 0;
	bitmapHeader.biClrUsed			= 0;
	bitmapHeader.biClrImportant		= 0;
    
	riffAddChunk  ( m_pOutAVI, "strf" );
	riffWriteData ( m_pOutAVI, &bitmapHeader, sizeof( bitmapHeader ) );
	riffCloseChunk( m_pOutAVI );      

	//
	// Close the strl list
	//
	riffCloseList( m_pOutAVI );

	//
	// Close the hdrl list
	//
	riffCloseList( m_pOutAVI );
	//
	// Write JUNK chunk
	//
	riffPadJunk( m_pOutAVI, PADDING_GRANULARITY, 0 );
	//
	// Write the "movi" list
	//
	riffAddList( m_pOutAVI, "LIST", "movi" );
	m_dwFirstFrameOffset = riffSize( m_pOutAVI );

#ifdef WRITE_INDEX
	m_nMoviOffset = m_dwFirstFrameOffset - 4;
#endif

	//
	// Return
	//

	m_bWriteHdr = FALSE;
	return TRUE;
}


DWORD CConvertAVI::GetCurFrameNum()
{
	return m_dwCurFrameNum;
}


BOOL CConvertAVI::AddFileToAVI(char* pBuf, DWORD /*nSize*/)
{

#ifdef WRITE_REC_LIST
	//
	// Write "rec " list
	//
	#ifdef WRITE_INDEX

	riffPadWord( m_pOutAVI );

	#endif // WRITE_INDEX

	riffAddList( m_pOutAVI, "LIST", "rec" );

#endif // WRITE_REC_LIST

	//
	// Write the "00dc" chunk
	//
#ifdef WRITE_INDEX

	riffPadWord( m_pOutAVI );

	m_pIndexes[m_dwCurFrameNum].ckid				= mmioFOURCC( '0', '0', 'd', 'c' );
	m_pIndexes[m_dwCurFrameNum].dwFlags			= AVIIF_KEYFRAME;
	m_pIndexes[m_dwCurFrameNum].dwChunkOffset	= riffSize( m_pOutAVI ) - m_nMoviOffset;
	m_pIndexes[m_dwCurFrameNum].dwChunkLength	= m_strAVIPara.dwFrameSize;
 
#endif // WRITE_INDEX

	//
	// Write the chunk
	//
	riffAddChunk  ( m_pOutAVI, "00dc" );
    riffWriteData ( m_pOutAVI, pBuf, m_strAVIPara.dwFrameSize );	
	riffCloseChunk( m_pOutAVI );

#ifdef WRITE_REC_LIST

	//
	// Close the "rec " list
	//
	riffCloseList( m_pOutAVI );

#endif // WRITE_REC_LIST

	//
	// Write JUNK chunk to align video frames
	//
#ifdef ALIGN_VIDEO_FRAMES

	riffPadJunk( m_pOutAVI, PADDING_GRANULARITY, m_dwFirstFrameOffset );

#endif // ALIGN_VIDEO_FRAMES

	m_dwCurFrameNum ++;
	
	return TRUE;
}


BOOL CConvertAVI::CloseWriffFiles()
{
	//
	// Close the "movi" list
	//
	riffCloseList( m_pOutAVI );
    
	//
	// Write the "idx1" chunk
	//
#ifdef WRITE_INDEX

	riffPadWord   ( m_pOutAVI );
	riffAddChunk  ( m_pOutAVI, "idx1" );
	riffWriteData ( m_pOutAVI, m_pIndexes, m_dwCurFrameNum*sizeof( AVIINDEXENTRY) );
	riffCloseChunk( m_pOutAVI );

#endif // WRITE_INDEX

	//
	// Close the "RIFF" LIST
	//
	riffCloseList( m_pOutAVI );
    
	//
	// Close the riff file
	//
	riffClose( m_pOutAVI );


	return TRUE;
}

void CConvertAVI::SetFPS(DWORD nFps)
{
	m_strAVIPara.dwFPS = nFps;
}

BOOL CConvertAVI::IsExceedMaxFileLen()
{
	return ( (m_dwCurFrameNum >= m_dwMaxFrames) ? TRUE : FALSE);
}


文件太多,完整的工程:

http://download.csdn.net/download/houwenbin1986/10127294

转载自原文链接, 如需删除请联系管理员。

原文链接:分享一下海康威视古老的播放器源码,转载请注明来源!

0