C# 视频监控系列(13):H264播放器——控制播放和截图
C# 視頻監控系列(13):H264播放器——控制播放和截圖
?
前言
?????本該把這部分和上一篇合成一篇的,無奈掙扎半天,還是想對稱起來,客戶端3篇、服務器端3篇——所有播放器也勉強湊3篇吧(封裝API的文章不算) : )
?
注意
?????本系列文章限于學習交流,注重過程,由于涉及公司,所以不提供源代碼下載,非常抱歉!!但是請大家放心,核心、實現以及其他能夠貼出來的代碼我都會貼出來,并且爭取盡所能的回答留言里的每一個問題,感謝大家關注,歡迎交流 :)
?
系列
?????1.?????C# 視頻監控系列(1):準備
?????2.?????C# 視頻監控系列(2):客戶端——封裝API
?????3.?????C# 視頻監控系列(3):客戶端——連接服務器
?????4.?????C# 視頻監控系列(4):客戶端——音頻接收和抓圖
?????5.?????C# 視頻監控系列(5):客戶端——給服務器端發送字符串和錄像(數據捕獲)
?????6.?????C# 視頻監控系列(6):服務器端——封裝API(上) [HikServer.dll]
?????7.?????C# 視頻監控系列(7):服務器端——封裝API(下) [DS40xxSDK.dll]
?????8.?????C# 視頻監控系列(8):服務器端——預覽和可被客戶端連接
?????9.?????C# 視頻監控系列(9):服務器端——數據捕獲(抓圖 + 錄像)
?????10.?? ??C# 視頻監控系列(10):服務器端——驗證、設置畫面質量、字幕疊加、板卡序列號
?????11.?????C# 視頻監控系列(11):H264播放器——封裝API[HikPlayM4.dll]
?????12.?????C# 視頻監控系列(12):H264播放器——播放錄像文件
?????13.?????C# 視頻監控系列(13):H264播放器——控制播放和截圖?
?
正文
?????一、控制播放
??????????1.1?????暫停/播放/停止
???????????????VC++ Code:
//////Funtion:Play?or?change?the?play?speed?to?normal;
///
void?CPlayerDlg::OnPlay()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????Play();
}
void?CPlayerDlg::Play()
{
????m_nSpeed=0;
????OnThrow0();
//#ifdef?_TEST_CALLBACK
????if(m_bConvert)???????
???????Hik_PlayM4_SetDecCallBack(PORT,DecCBFun);
????else
????????m_pMainMenu->EnableMenuItem(ID_FILE_CLOSE,?FALSE);
//#endif
????if(m_bPlaying)
????{
????????Hik_PlayM4_Play(PORT,GetDlgItem(IDC_SHOW)->m_hWnd);
????}
????else
????{
????????if(m_bStreamType)
????????{
????????????::SetFilePointer(m_hStreamFile,m_nHeadSize,0,FILE_BEGIN);
????????????Hik_PlayM4_ResetSourceBuffer(PORT);
????????????SetEvent(m_hEventInput);
????????}
????????m_bPlaying?=?Hik_PlayM4_Play(PORT,GetDlgItem(IDC_SHOW)->m_hWnd);
????????m_bSound=Hik_PlayM4_PlaySound(PORT);
????????if(m_bPlaying)
????????????SetTimer(PLAY_TIMER,500,NULL);
????????
????}
????if(m_bPlaying)
????????SetPlayState();
????else
????{
????????CString?csError;
????????csError.Format("Play?the?file?faild.(%d)",Hik_PlayM4_GetLastError(PORT));
????????AfxMessageBox(csError);
????}
????
}
//
//Funtion:pause.
//
void?CPlayerDlg::OnPause()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????if(m_bPlaying)
????{
????????m_bPause=!m_bPause;
????????Pause(m_bPause);
????}
}
void?CPlayerDlg::Pause(BOOL?bPause)
{
????if(m_bPaused?==?bPause)
????????return;
????m_bPaused=bPause;
????Hik_PlayM4_Pause(PORT,bPause);
????TRACE("PAUSE?%d\n",m_bPaused);
}
/////
//Function:?Stop
/////
void?CPlayerDlg::OnStop()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????
????if(m_bPlaying)
????{
????????Stop();
????}
????if(m_bConvert)
????{
???????if(outFile!=NULL)
??????????closeWriffFiles();????
???????if(yuvBuf!=NULL)
???????{
???????????free(yuvBuf);
???????????yuvBuf=NULL;
???????}
???????m_bConvert=0;????
???????//
????}
}
void?CPlayerDlg::Stop()
{
????CButton?*pButton;
????if(!m_bPlaying)
????????return;
????KillTimer(PLAY_TIMER);
????if(Hik_PlayM4_StopSound())
????{
????????m_bSound=FALSE;
????????pButton?=?(CButton?*)GetDlgItem(IDC_SOUND);
????????pButton->SetIcon(m_hSoundStopIcon);
????}
????//continue?before?stop.Add?by?lgl?at?9-19;
????m_bPause=FALSE;
????
????//stop
????m_bPlaying?=?!Hik_PlayM4_Stop(PORT);
????if(!m_bPlaying)????
????{
????????SetStopState();
????????if(m_bStreamType)
????????????ResetEvent(m_hEventInput);
????}
????
}
???????????????C#?????Code:
????????//是否暫停????????private?bool?isPause;
????????///?<summary>
????????///?播放
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnPlay_Click(object?sender,?EventArgs?e)
????????{
????????????if?(!string.IsNullOrEmpty(m_strPlayFileName))
????????????{
????????????????//是否暫停->播放
????????????????if?(isPause)
????????????????{
????????????????????HikPlayer.Hik_PlayM4_Pause(PORT,?false);
????????????????????isPause?=?false;
????????????????}
????????????????else
????????????????????OpenFile();
????????????}
????????}
????????///?<summary>
????????///?暫停
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnPause_Click(object?sender,?EventArgs?e)
????????{
????????????HikPlayer.Hik_PlayM4_Pause(PORT,?true);
????????????isPause?=?true;
????????}
????????///?<summary>
????????///?停止
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnStop_Click(object?sender,?EventArgs?e)
????????{
????????????HikPlayer.Hik_PlayM4_Stop(PORT);
????????????HikPlayer.Hik_PlayM4_CloseFile(PORT);
????????????HikPlayer.Hik_PlayM4_RealeseDDraw();
????????????pVideo.Invalidate(true);
????????}
???????????????代碼說明:
????????????????????1.?????關于變量PORT、m_strPlayFileName和方法OpenFile可以看上篇文章的代碼。
????????????????????2.?????注意Hik_PlayM4_Pause的第二個參數用法。
??????????1.2?????快進/慢進
???????????????VC++ Code:
////Funtion:?Fast
//
void?CPlayerDlg::OnFastForward()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????//Throw?B-Frame?,improve?the?performance;
????
????if(Hik_PlayM4_Fast(PORT))
????{
????????m_nSpeed++;
????????if(m_nSpeed>0)
????????????OnThrow2();
????????SetFastForwardState();????????
????}????
}
//
//Funtion:?Slow;
//
void?CPlayerDlg::OnFastBackward()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????if(Hik_PlayM4_Slow(PORT))
????{
????????m_nSpeed--;
????????if(m_nSpeed<=0)
????????????OnThrow0();
????????SetFastBackWardState();
????}
}
????????????????C#?????Code:
????????int?m_nSpeed;????????///?<summary>
????????///?快進
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnFastForward_Click(object?sender,?EventArgs?e)
????????{
????????????if?(HikPlayer.Hik_PlayM4_Fast(PORT))
????????????{
????????????????m_nSpeed++;
????????????????if?(m_nSpeed?>?0)
????????????????????OnThrow2();
????????????}
????????}
????????///?<summary>
????????///?慢放
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnFastBackward_Click(object?sender,?EventArgs?e)
????????{
????????????//慢速播放
????????????if?(HikPlayer.Hik_PlayM4_Slow(PORT))
????????????{
????????????????//timer1.Interval
????????????????m_nSpeed--;
????????????????if?(m_nSpeed?<=?0)
????????????????????OnThrow0();
????????????}
????????}
????????public?void?OnThrow0()
????????{
????????????HikPlayer.Hik_PlayM4_ThrowBFrameNum(PORT,?0);
????????}
????????public?void?OnThrow2()
????????{
????????????HikPlayer.Hik_PlayM4_ThrowBFrameNum(PORT,?2);
????????}
???????????????代碼說明:
????????????????????1.?????注意關于這兩個函數API的說明:
?????????????????????????Hik_PlayM4_Fast:快速播放,每次調用將使當前播放速度加快一倍,最多調用4次;要恢復正常播放調用Hik_PlayM4_Play(),從當前位置開始正常播放。
?????????????????????????Hik_PlayM4_Slow:慢速播放,每次調用將使當前播放速度慢一倍;最多調用4次;要恢復正常播放調用Hik_PlayM4_Play。
??????????1.3?????開始/末尾
???????????????VC++ Code:
/////Funtion:Locate?to?the?file?head.
//
void?CPlayerDlg::OnGotoStart()?
{
????//?TODO:?Add?your?control?notification?handler?code?here
????if(m_bFileRefCreated)
????????Hik_PlayM4_SetCurrentFrameNum(PORT,0);
????else
????????Hik_PlayM4_SetPlayPos(PORT,0);
}
///
//Funtion:Locate?to?the?end.
//
void?CPlayerDlg::OnGotoEnd()?
{
????//?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_nTotalFrames;
????????while(!Hik_PlayM4_SetCurrentFrameNum(PORT,nEndFrame--))
????????{
????????????//TRACE("FrameNum?is?:%d\n",nEndFrame);
????????????if(nEndFrame==0)
????????????????break;
????????}
????}
????else
????????Hik_PlayM4_SetPlayPos(PORT,1);
}
???????????????C#?????Code:
????????///?<summary>????????///?開始位置
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnGotoStart_Click(object?sender,?EventArgs?e)
????????{
????????????HikPlayer.Hik_PlayM4_SetPlayPos(PORT,?0);
????????}
????????///?<summary>
????????///?末尾位置
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnGotoEnd_Click(object?sender,?EventArgs?e)
????????{
????????????HikPlayer.Hik_PlayM4_SetPlayPos(PORT,?1);
????????}
???????????代碼說明:
???????????????1.?????注意Hik_PlayM4_SetPlayPos的第二個參數取值范圍是0-1之間,即可以理解0是開始位置,1是結束位置;但是有一點比較奇怪,每次都會延遲3秒,即到末尾后還播放3秒鐘!
?????二、截圖
???????????????VC++ Code:
////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)
{
????if(!g_bCapPic)
????????return;
????CString?csFile;
????csFile.Format("capture%02d.bmp",pic);
????/*????switch(nType)
????{
????case?T_UYVY:
????csFile="uyvy.bmp";
????break;
????case?T_YV12:
????csFile="yv12.bmp";
????break;
????case?T_RGB32:
????csFile="rgb.bmp";
????break;
????default:?
????return?;
}*/
????//Note:this?funtion?is?slow,so?if?you?want?to?save?as?a?.bmp?file,don't?call!?
????if(!Hik_PLayM4_ConvertToBmpFile(pBuf,nSize,nWidth,nHeight,nType,csFile.GetBuffer(csFile.GetLength())))
????{
????????CString?csErr;
????????csErr.Format("Convert?to?bmp?faild(%d).",Hik_PlayM4_GetLastError(nPort));
????????AfxMessageBox(csErr);
????}
????pic++;
????g_bCapPic=FALSE;
????
}
???????????????C#?????Code:
????????DisplayCBFun?DisCB;????????///?<summary>
????????///?截圖
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?btnCapImage_Click(object?sender,?EventArgs?e)
????????{
????????????DisCB?=?new?DisplayCBFun(DisplayCBFun);
????????????HikPlayer.Hik_PlayM4_SetDisplayCallBack(PORT,?DisCB);
????????}
????????///?<summary>
????????///?截圖回調函數
????????///?</summary>
????????///?<param?name="nPort"></param>
????????///?<param?name="pBuf"></param>
????????///?<param?name="nSize"></param>
????????///?<param?name="nWidth"></param>
????????///?<param?name="nHeight"></param>
????????///?<param?name="nStamp"></param>
????????///?<param?name="nType"></param>
????????///?<param?name="nReceaved"></param>
????????public?void?DisplayCBFun(int?nPort,?IntPtr?pBuf,?int?nSize,?int?nWidth,?int?nHeight,?int?nStamp,?int?nType,?int?nReceaved)
????????{
????????????if?(HikPlayer.Hik_PLayM4_ConvertToBmpFile(pBuf,?nSize,?nWidth,?nHeight,?nType,?string.Format("C:\\capture{0}.bmp",?nPort)))
????????????{
????????????????MessageBox.Show("轉換bmp失敗!");
????????????}
????????????//停止回調
????????????HikPlayer.Hik_PlayM4_SetDisplayCallBack(PORT,?null);
????????}
??????????代碼說明:
???????????????1.?????這里和源代碼有點出入,他用的是g_bCapPic變量來控制是否捕獲圖片,我用的是設置委托實例和null來達到。API說明:設置抓圖回調函數;注意要盡快返回,如果要停止回調,可以把回調函數指針DisplayCBFun設為NULL。
?
結束
?????現在在做語音部分,受阻中...轉載:http://www.cnblogs.com/over140/archive/2009/03/30/1421531.html
總結
以上是生活随笔為你收集整理的C# 视频监控系列(13):H264播放器——控制播放和截图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代理服务器的用途
- 下一篇: 套接字编程——基于UDP协议