您的位置:首页 > 编程语言 > C#

【转】C# 视频监控系列(13):H264播放器——控制播放和截图

2018-01-09 09:27 495 查看
本文原文地址:http://www.cnblogs.com/over140/archive/2009/03/30/1421531.html

阿里云栖社区也有相关的视频开发案例:https://yq.aliyun.com/articles/51182

注意

本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答留言里的每一个问题,感谢大家关注,欢迎交流 :)

系列

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。

结束

现在在做语音部分,受阻中...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐