【转】C# 视频监控系列(13):H264播放器——控制播放和截图
本文原文地址:http://www.cnblogs.com/over140/archive/2009/03/30/1421531.html
阿里云栖社区也有相关的视频开发案例:https://yq.aliyun.com/articles/51182
注意
本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答留言里的每一个问题,感谢大家关注,欢迎交流 :)
系列
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。
结束
现在在做语音部分,受阻中...
【转】C# 视频监控系列(13):H264播放器——控制播放和截图的更多相关文章
- C# 视频监控系列:学习地址汇总
原文地址:http://www.cnblogs.com/over140/archive/2009/04/07/1429308.html 前言 对于视频监控系统大家应该是不陌生的,实施的路况信息.地铁. ...
- 【转】C# 视频监控系列(12):H264播放器——播放录像文件
原文地址:http://www.cnblogs.com/over140/archive/2009/03/23/1419643.html?spm=5176.100239.blogcont51182.16 ...
- 百度播放器SDK 播放MP4格式视频有声音无画面问题解决
此处为记录解决过程. 所链接使用的MP4格式视频为codec id是mp4v-20.使用手机自带播放器可以播放,使用百度云媒体播放器不能无画面.经调试,Android Baidu-Cloud-Play ...
- java调用本地播放器播放视频文件。调用本地播放器不能播放指定文件的说明。
public class OpenExe extends HttpServlet { //打开本地播放器并播放视频 public static void openExe(String file) { ...
- phongap开发中安卓平台上如何调用第三方播放器来播放HLS视频
前文曾经讲了关于在安卓平台上利用phonegap开发播放HLS的解决方案,其实最好的方案就是自己针对HLS视频开发自己的播放器,但是开发播放器是一个浩大的工程,必须对原生安卓开发非常熟悉,并且对视频播 ...
- iOS 多个播放器同时播放,双击全屏,单击退出全屏
前言:公司需求如下:点击一个按钮播放一个视频,最多同时播放4个:双击某视频让其全屏,单击再恢复原来的样子.IOS的播放器有两种,MPMoviePlayerController,AVAudioPlaye ...
- IOS 集成 Bilibili IJKPlayer播放器,播放rtmp视频流
因为公司项目需要,我一个连iPhone都没用过的人竟然跑去开发iOS APP.近一段时间一直忙于赶项目,到今天差不多了,所以记录一下当时遇到的各种坑,先从ios 集成 ijkplayer播放器说起! ...
- 利用Docker挂载Nginx-rtmp(服务器直播流分发)+FFmpeg(推流)+Vue.js结合Video.js(播放器流播放)来实现实时网络直播
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_75 众所周知,在视频直播领域,有不同的商家提供各种的商业解决方案,其中比较靠谱的服务商有阿里云直播,腾讯云直播,以及又拍云和网易云 ...
- 解决Ubuntu14.04下Clementine音乐播放器不能播放wma文件的问题
参考:Ubuntu 14.04 安装深度音乐的方法 问题描述:播放wma文件时提示"GStreamer插件未安装". 解决方法:安装gstreamer-ffmpeg插件即可解决问题 ...
随机推荐
- BZOJ 1123 [POI2008]BLO(Tarjan算法)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1123 [题目大意] Byteotia城市有n个towns,m条双向roads. 每条r ...
- 【Trie】【kd-tree】计蒜客17122 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 I. Barty's Computer
题意:2种操作:①往集合里添加一个串 ②给你四个小串a b c d,问你集合里有几个串S满足S=a+S1+b+c+S2+d的形式.S1 S2可以为空,并且a+S1+b=c+S2+d. 就搞四颗Trie ...
- 中间件和auth模块
中间件 1.什么是中间件 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出.因为改变的是全局,所以需要谨慎实用,用 ...
- 激活Debian 7 的桌面(把图标放在桌面上)
转:http://www.acyoo.com/archives/3017.html Debian 7的默认桌面是Gnome 3, 刚装好时无法在桌面进行任何操作,不过只需要设置一下就可以了: 左上角 ...
- ER TO SQL语句
ER TO SQL语句的转换,在数据库设计生命周期的位置如下所示. 一.转换的类别 从ER图转化得到关系数据库中的SQL表,一般可分为3类: 1)转化得到的SQL表与原始实体包含相同信息内容.该类转化 ...
- checkbox复选框居中
选项框居中 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- IIS_未能映射路径“/”。
解决方法: 使用托管管道默认是为[经典]的应用程序池
- !!! # @ --- ODATA 云驱动 --- 数据库发布 RESTFUL API
Cloud Drivers ODATA 云驱动 http://www.cdata.com/cloud/ Makes on-premise & cloud data sources ea ...
- Java9 modules (Jigsaw)模块化迁移
要点 通过模块化的方式开发应用程序,实现更好的设计,如关注点分离和封装性. 通过Java平台模块化系统(JPMS),开发者可以定义他们的应用程序模块,决定其他模块如何调用他们的模块,以及他们的模块如何 ...
- iOS:UIResponser控件的介绍(响应者)
UIResponser响应者控件 知识: 在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication,UIV ...