针对监控摄像机(海康大华等)进行手动录像的录像文件播放器功能设计

海龙的博客 海龙的博客     2022-08-23     331

关键词:

 

参考上一篇:

针对监控摄像机(海康、大华等)进行手动录像的功能设计

 

录像后需要自定义一个播放器来播放录像文件。

简单设计界面如下:

 

打开文件,可暂停,可停止,可以拖动进度条。

 

static int width = 1920, height = 1080;
        int videoWidth = 639, videoHeight = 479;
        int YUVWidth = 640, YUVHeight = 480;

        bool bPause = false;
        bool bPlayStop = false;

        ILog log = LogManager.GetLogger("ErrorLog");
        int fps = 15, fpsMain = 15, fpsBase = 15;
        int msPerFrameCamera = 66, msPerFrameCameraBase = 66, msPerFrameCameraMain = 66; //相机每一帧的时间,25帧即40毫秒

        public frmPlay()
        {
            InitializeComponent();

            #region 解码器相关初始化,一般在窗口load中进行初始化
            decAttr = new H264Dec.hiH264_DEC_ATTR_S();
            decAttr.uPictureFormat = 0;
            decAttr.uStreamInType = 0;
            decAttr.uPicWidthInMB = (uint)width;
            decAttr.uPicHeightInMB = (uint)height;
            decAttr.uBufNum = 8;
            decAttr.uWorkMode = 16;
            //创建、初始化解码器句柄
            _decHandle = H264Dec.Hi264DecCreate(ref decAttr);
            #endregion

            InitVars();

            frmPlay_Resize(null, null);
            this.Resize += new System.EventHandler(this.frmPlay_Resize);
        }

        long offsetPlay = 0;
        int iFramePlay = 0;
        Image<Bgr, Byte> imageYUV = new Image<Bgr, Byte>(640, 480);
        Image<Bgr, Byte> imgNowShow = new Image<Bgr, Byte>(640, 480);
        int iFontSize16 = 12, iFontSize20 = 15, iFontSize24 = 18;
        string fontname = "仿宋_GB2312";

        private delegate void SetPicVideo(Image<Bgr, Byte> val);//跨线程修改图片框
        private Thread SetPicVideoThread;

        FileStream fs = null;
        private delegate void SetProgressLabel(string val);
        Thread SetLabelThread;
        string labelValue = string.Empty;
        string sTotalTime = "";
        int iFrameCnt = 0;

        Thread showThread;

        void SetPic(Emgu.CV.Image<Bgr, Byte> val)
        {
            if (bPause || bPlayStop || bAbortPlayThread)
            {
                Graphics g = imgBox.CreateGraphics();
                g.Clear(Color.Black);
                imageVideoOverLay.Visible = true;
            }
            else
                if (imageVideoOverLay.Visible)
                {
                    imageVideoOverLay.Visible = false;
                }
            if (val != null && !bAbortPlayThread)
            {
                this.imgBox.Image = val;
                imgBox.Refresh();
            }
        }

        private void setPicVideo()
        {
            if (bPause || bPlayStop || bAbortPlayThread) return;
            if (imgBox.InvokeRequired)
            {
                SetPicVideo d = new SetPicVideo(SetPic);
                object[] arg = new object[] { imgNowShow };
                this.Invoke(d, arg);
            }
            else
            {
                SetPic(imgNowShow);
            }
        }


        List<BufferPlay> BufferPlayList = new List<BufferPlay>();
        private void DrawnShow()
        {
            iFramePlay = 0;
            while (!bAbortPlayThread)
            {
                if (BufferPlayList.Count > 0)
                {
                    DateTime dtStart = DateTime.Now;
                    realstaticinfo = BufferPlayList[0].info;
                    GCHandle handle = GCHandle.Alloc(BufferPlayList[0].yuvs, GCHandleType.Pinned);
                    using (Image<Bgr, Byte> yuv420p = new Image<Bgr, byte>(YUVWidth, (YUVHeight >> 1) * 3, YUVWidth, handle.AddrOfPinnedObject()))
                    {
                        CvInvoke.CvtColor(yuv420p, imageYUV, Emgu.CV.CvEnum.ColorConversion.Yuv420P2Bgr);
                    }

                    if (handle.IsAllocated)
                        handle.Free();
                    
                    if (imageYUV == null) continue;
                    Bitmap bmp = imageYUV.Bitmap;
                    if (bmp == null) continue;
                    lock (bmp)
                    {
                        if (bShowLine)
                        {
                            DrawInVideo(bmp);
                        }
                        
                        imageYUV.Bitmap = bmp;

                        imgNowShow = imageYUV;
                        SetPicVideoThread = new Thread(new ThreadStart(setPicVideo));
                        SetPicVideoThread.IsBackground = true;
                        SetPicVideoThread.Start();
                    }

                    if (BufferPlayList.Count > 0) BufferPlayList.RemoveAt(0);

                    iFramePlay++;
                    if (iFramePlay % fps == 0)
                    {
                        int seconds = (int)((double)iFramePlay / fps);
                        int h = (int)Math.Floor((double)seconds / 3600);
                        int m = (int)Math.Floor((double)(seconds - h * 3600) / 60);
                        int s = (int)Math.Floor((double)(seconds - h * 3600 - m * 60));

                        string sNowPlayTime = h.ToString().PadLeft(2, '0') + ":" + m.ToString().PadLeft(2, '0') + ":" + s.ToString().PadLeft(2, '0');

                        labelValue = sNowPlayTime + "/" + sTotalTime;

                        SetLabelThread = new Thread(new ThreadStart(setLableValue));
                        SetLabelThread.IsBackground = true;
                        SetLabelThread.Start();
                    }

                    DateTime timeStop2 = DateTime.Now;
                    TimeSpan ts2 = new TimeSpan();
                    ts2 = timeStop2 - dtStart;
                    if (ts2.TotalMilliseconds < msPerFrameCamera)
                    {
                        Thread.Sleep((int)(msPerFrameCamera - ts2.TotalMilliseconds));
                    }
                }
            }
        }

        private void Play(object ofs)
        {
            FileStream fsTmp = ofs as FileStream;

            try
            {
                offsetPlay = 0;
                DateTime timeStart = DateTime.Now;
                DateTime timeStop = DateTime.Now;
                
                while (!bAbortPlayThread && fsTmp.Length > offsetPlay + 4 + 378 + 174)
                {
                    try
                    {
                        if (bPause)
                        {
                            Thread.Sleep(msPerFrameCamera);
                            continue;
                        }
                        
                        timeStart = DateTime.Now;

                        byte[] intdata = new byte[4];

                        fsTmp.Read(intdata, 0, 4);
                        offsetPlay = offsetPlay + 4;
                        fsTmp.Seek(offsetPlay, SeekOrigin.Begin);
                        int frameLen = (int)FVD.Common.Common.bytes2uintNoRe(intdata, 0, 4);

                        byte[] buffer = new byte[frameLen];
                        fsTmp.Read(buffer, 0, frameLen);
                        offsetPlay = offsetPlay + frameLen;
                        fsTmp.Seek(offsetPlay, SeekOrigin.Begin);
                        GCHandle hObject2 = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                        IntPtr pStreamData = hObject2.AddrOfPinnedObject();

                        if (fsTmp.Length > offsetPlay + 500)
                        {
                            byte[] datas= new byte[500];  //获取叠加数据
                            fsTmp.Read(datas, 0, 500);
                            Getdatas(datas);
                        }

                        if (H264Dec.Hi264DecAU(_decHandle, pStreamData, (uint)frameLen, 0, ref _decodeFrame, 0) == 0)
                        {
                            int yLength = (int)(_decodeFrame.uHeight * _decodeFrame.uYStride);
                            int uLength = (int)(_decodeFrame.uHeight * _decodeFrame.uUVStride / 2);
                            IntPtr y = _decodeFrame.pY;
                            IntPtr v = _decodeFrame.pV;
                            IntPtr u = _decodeFrame.pU;
                            byte[] ys = new byte[yLength];
                            Marshal.Copy(y, ys, 0, yLength);
                            byte[] vs = new byte[uLength];
                            Marshal.Copy(v, vs, 0, uLength);
                            byte[] us = new byte[uLength];
                            Marshal.Copy(u, us, 0, uLength);

                            byte[] yuvs = new byte[ys.Length + vs.Length + us.Length];

                            ys.CopyTo(yuvs, 0);
                            vs.CopyTo(yuvs, ys.Length);
                            us.CopyTo(yuvs, ys.Length + vs.Length);

                            BufferPlay bp;
                            bp.info = realstaticinfoTmp;
                            bp.yuvs = yuvs;
                            BufferPlayList.Add(bp);
                        }

                        if (hObject2.IsAllocated)
                            hObject2.Free();

                        pStreamData = IntPtr.Zero;

                        if (BufferPlayList.Count > 0)
                        {
                            Thread.Sleep((int)((BufferPlayList.Count - 1) * msPerFrameCamera));
                        }
                    }
                    catch (System.Exception ex)
                    {
                        log.ErrorFormat("播放出错:" + ex.Message);
                        continue;
                    }
                }
            }
            catch (System.Exception ex)
            {
                log.ErrorFormat("播放出错:" + ex.Message);
                MessageBox.Show("播放出错:" + ex.Message);
            }

            while (BufferPlayList.Count > 0)
            {
                Thread.Sleep(msPerFrameCamera);
            }

            if (bLoopPlay) //循环播放,重新初始化
            {
                if (bAbortPlayThread) return;

                bPlayStop = true;
                bAbortPlayThread = true;

                Thread.Sleep(500);

                bPlayStop = false;
                bAbortPlayThread = false;

                labelValue = "00:00:00/" + sTotalTime;
                SetLabelThread = new Thread(new ThreadStart(setLableValue));
                SetLabelThread.IsBackground = true;
                SetLabelThread.Start();

                fsTmp.Seek(0, SeekOrigin.Begin);
                playThread = new Thread(new ParameterizedThreadStart(Play));
                playThread.IsBackground = true;
                playThread.Start(fsTmp);
                showThread = new Thread(new ThreadStart(DrawnShow));
                showThread.IsBackground = true;
                showThread.Start();
            }
            else
            {
                fsTmp.Close();
                fsTmp.Dispose();

                bPlayStop = true;
                labelValue = "00:00:00/00:00:00";
                SetLabelThread = new Thread(new ThreadStart(setLableValue));
                SetLabelThread.IsBackground = true;
                SetLabelThread.Start();
            }
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(sTotalTime) && fs != null && btnStop.Enabled == true && fs.CanRead && iFrameCnt > 0)
            {
                bPause = true;
                Thread.Sleep(msPerFrameCamera);
                int iNowFrame = (int)((double)trackBar1.Value / trackBar1.Maximum * (double)iFrameCnt);
                if (iNowFrame <= 0)
                {
                    iNowFrame = 1;
                }

                BufferPlayList.Clear();

                fs.Seek(0, SeekOrigin.Begin);

                long offsetTmp = 0;
                int iFrame = 0;
                byte[] intdata = new byte[4];
                while (fs.Length > offsetTmp + 504)
                {
                    fs.Read(intdata, 0, 4);
                    int frameLen = (int)(intdata[0] | intdata[1] << 8 | intdata[2] << 16 | intdata[3] << 24);
                    offsetTmp = offsetTmp + frameLen + 504; //504 = 4 + 500
                    fs.Seek(offsetTmp, SeekOrigin.Begin);
                    iFrame++;
                    if (iFrame == iNowFrame)
                    {
                        offsetPlay = offsetTmp;
                        iFramePlay = iNowFrame;

                        break;
                    }
                }

                bPause = false;
            }
        }

        void SetStatuslabel(string val)
        {
            if (bPlayStop) //自动播放完成,跨线程修改状态
            {
                btnStop.Enabled = false;
                btnPause.Enabled = false;
                this.Text = "视频播放";

                trackBar1.ValueChanged -= new System.EventHandler(trackBar1_ValueChanged);
                trackBar1.Value = 0;
                trackBar1.ValueChanged += new System.EventHandler(trackBar1_ValueChanged);
                trackBar1.Enabled = false;

                iFramePlay = 0;
                imageVideoOverLay.Visible = true;
                bPlayStop = false;
            }

            if (bPause || bPlayStop || bAbortPlayThread) return;
            this.labelProgress.Text = val;

            if (iFrameCnt > 0 && iFramePlay > 0 && iFramePlay <= iFrameCnt)
            {
                trackBar1.ValueChanged -= new System.EventHandler(trackBar1_ValueChanged);
                trackBar1.Value = (int)((double)iFramePlay / (double)iFrameCnt * trackBar1.Maximum);
                trackBar1.ValueChanged += new System.EventHandler(trackBar1_ValueChanged);
            }
        }

        private void setLableValue()
        {
            if (bPause || bAbortPlayThread) return;
            if (labelProgress.InvokeRequired)
            {
                SetProgressLabel d = new SetProgressLabel(SetStatuslabel);
                object[] arg = new object[] { labelValue };//要传入的参数值
                this.Invoke(d, arg);
            }
            else
            {
                SetStatuslabel(labelValue);
            }
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (rbMainVideo.Checked)
            {
                YUVWidth = width;
                YUVHeight = height;
                msPerFrameCamera = msPerFrameCameraMain;
                fps = fpsMain;
            }
            else
            {
                YUVWidth = videoWidth + 1;
                YUVHeight = videoHeight + 1;
                msPerFrameCamera = msPerFrameCameraBase;
                fps = fpsBase;
            }

            transX = YUVWidth / (videoWidth + 1);
            transY = YUVHeight / (videoHeight + 1);

            frmPlay_Resize(null, null);

            openFileDialog1.Filter = "Zenith视频文件(*.dat)|*.dat";
            openFileDialog1.FileName = "";
            openFileDialog1.Multiselect = false;
            openFileDialog1.InitialDirectory = Application.StartupPath;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.labelProgress.Text = "00:00:00/00:00:00";
                bAbortPlayThread = true;
                
                Thread.Sleep(200);

                if (playThread != null && playThread.IsAlive)
                {
                    playThread.Abort();
                }

                string filename = openFileDialog1.FileName;

                fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read);
                if (fs.Length <= 512)
                {
                    MessageBox.Show("请确认文件是否有效!" + filename);
                    return;
                }
                if (!fs.CanRead || !fs.CanSeek)
                {
                    MessageBox.Show("文件不可读,请确认!" + filename);
                    return;
                }

                imageYUV = new Image<Bgr, Byte>(YUVWidth, YUVHeight);
                
                this.Cursor = Cursors.WaitCursor;
                try
                {
                    this.Text = "视频播放   " + filename;
                    log.ErrorFormat("视频播放   " + filename);
                    if (bPause)
                    {
                        bPause = false;
                        btnPause.Text = "暂停";
                    }

                    bPlayStop = false;
                    bAbortPlayThread = false;
                    btnStop.Enabled = true;
                    btnPause.Enabled = true;
                    trackBar1.ValueChanged -= new System.EventHandler(trackBar1_ValueChanged);
                    trackBar1.Value = 0;
                    trackBar1.ValueChanged += new System.EventHandler(trackBar1_ValueChanged);
                    trackBar1.Enabled = true;

                    fs.Seek(0, SeekOrigin.Begin);
//获取文件长度
                    long offset = 0;
                    iFrameCnt = 0;
                    byte[] intdata = new byte[4];
                    while (fs.Length > offset + 556)
                    {
                        fs.Read(intdata, 0, 4);
                        int frameLen = (int)(intdata[0] | intdata[1] << 8 | intdata[2] << 16 | intdata[3] << 24);
                        offset = offset + frameLen + 556; //556 = 4 + 378 + 174
                        fs.Seek(offset, SeekOrigin.Begin);
                        iFrameCnt++;
                    }

                    int seconds = (int)((double)iFrameCnt / fps);
                    int h = (int)Math.Floor((double)seconds / 3600);
                    int m = (int)Math.Floor((double)(seconds - h * 3600) / 60);
                    int s = (int)Math.Floor((double)(seconds - h * 3600 - m * 60));

                    sTotalTime = h.ToString().PadLeft(2, '0') + ":" + m.ToString().PadLeft(2, '0') + ":" + s.ToString().PadLeft(2, '0');
                    this.labelProgress.Text = "00:00:00/" + sTotalTime;

                    fs.Seek(0, SeekOrigin.Begin);
                    playThread = new Thread(new ParameterizedThreadStart(Play));
                    playThread.IsBackground = true;
                    playThread.Start(fs);
                    showThread = new Thread(new ThreadStart(DrawnShow));
                    showThread.IsBackground = true;
                    showThread.Start();
                }
                catch (System.Exception ex)
                {
                    log.ErrorFormat("视频初始化错误!" + ex.Message);
                    MessageBox.Show("视频初始化错误!");
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                }
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            labelValue = "00:00:00/00:00:00";
            SetLabelThread = new Thread(new ThreadStart(setLableValue));
            SetLabelThread.IsBackground = true;
            SetLabelThread.Start();

            this.Text = "视频播放";

            trackBar1.ValueChanged -= new System.EventHandler(trackBar1_ValueChanged);
            trackBar1.Value = 0;
            trackBar1.ValueChanged += new System.EventHandler(trackBar1_ValueChanged);
            trackBar1.Enabled = false;

            if (fs != null )
            {
                fs.Close();
                fs.Dispose();
            }
            bAbortPlayThread = true;
            btnStop.Enabled = false;
            btnPause.Enabled = false;

            if (bPause)
            {
                bPause = false;
                btnPause.Text = "暂停";
            }
        }

 

大华摄像机怎样添加海康录像机?

要保证前后端软件版本支持onvif协议,不支持的联系技术支持升级,海康大华都支持这个,再就是添加的问题,在nvr通道管理里面选择自定义添加,协议选择onvif标准协议(只能选这个通用协议),用户名密码端口选用大华设备... 查看详情

监控系统怎么解锁

...:1、先删除被锁定通道;更改录像机ip地址;自定义添加摄像机输入正确密码。2、摄像机物理断电重启。锁定的摄像机,一般需20分钟后自动解锁。当然也有快速的方法:对此摄像机进行断电重启,迅速解除锁定状态;重新以正... 查看详情

大华监控出现了等待登录返回超时

...的回答对你有帮助! 参考技术C1升级硬盘录像机,或者是摄像机软件2把摄像机的IP改大一些。3交换机换成千兆。 参考技术D我已解决,减少交换机级连,缩短网线距离。 查看详情

大华录像机无访问权限设置方法

...情况下,大华录像机设置有三个部分:录像主机配置、电脑监控软件安装和手机远程软件安装,简单的介绍一下,希望对你有所帮助。一、大华录像主机配置1.设备连接:录像机和摄像头一般通过交换机做局域网连接,若要外网访问的话... 查看详情

我是海康威视的监控录像机,然后公司通过购买海康威视的秘钥,能后台接入我的录像机,我怎么防止?

...,被监视的感觉真的不好。我怎么才能防止这样的接入?监控得用,还得联网,只是不想让别人看着参考技术A一般单位里的所有相机的安装位置角度朝向都是和单位内的负责人确认的,所有相机都会接入到综合管控的软件里,... 查看详情

海康网络录像机上网设置

...出月/日/年/星期/时/分/秒/录像模式,还能在图像上示出摄像机与报警器的编号与报警方式。3、使用自动录像周期设定功能,可以对一星期内每一天的录像模式进行编程。当收到报警信号后,录像机便自动进入连续录像状态,在... 查看详情

大华录像机怎么设置手机上的远程监控?

大华录像机设置手机上的远程监控的详细步骤如下。一、硬盘录像机网络设置。1、硬盘录像机主界面右键,打开主菜单,选择网络。2、设置静态网络,所有设置完成后先点击应用再点击确定,刷新后硬盘录像机使其联网成功。3... 查看详情

大华硬盘录像机的录像用啥播放器可以在电脑上播放

大华硬盘录像机备份出来的录像文件是dav格式的文件,普通播放器不能播放,可以选择大华官方网站上面的“大华播放器”,下载安装播放。具体方法如下:1、登录大华官方网站:大华官网,依次点击“服务支持”,“大华工... 查看详情

浏览器低延时播放rtsp安防摄像头/海康大华硬盘录像机/nvr/流媒体服务器硬件开发机设备失去授权如何解决?

...诉求越来越多,互联网思维、架构和技术引入进传统监控行业里,成为新形势下全终端监控的基础需求。​​​​​​​​​​​​​​关于EasyNVREasyNVR是一款拥有完整、自主、可控知识产权,同时又能够具备软硬一... 查看详情

海康威视手机远程监控设置教程

...:1、首先在手机上下载安装一个“萤石云视频”(远程监控查看录像的软件),进入登录页面进行注册登录;2、然后扫描海康威视摄像头所带的二维码,使APP和摄像头设备连接成功;3、接着找到“我的设备”并点击下面的”添... 查看详情

大华录像机视频格式是啥

参考技术A目前大华生产的硬盘录像机大部分是H.264的压缩格式但播放这个文件还是需要使用他们的客户端软件播放再有他们的播放软件转成电脑播放软件支持的格式(如:avi)本回答被提问者采纳 查看详情

海康威视硬盘录像机回登录界面

海康威视硬盘录像机回登录界面的操作方法:海康威视的硬盘录像机返回到登录界面非常简单,在菜单的任何界面,一直点击鼠标右键,就会一级一级的返回上级菜单,一直到退出菜单到登录界面。海康威视网络硬盘录像机操作... 查看详情

海康威视的摄像头如何连接宇视的录像机?

首先要用电脑把海康的摄像头激活。然后给摄像头分配IP地址。输入摄像头IP地址进入摄像头后台。打开集成onvif协议。然后录像机里面手动添加摄像头就可以了参考技术A通过onvif协议可以连接 查看详情

大华硬盘录像机网络摄像机网络硬盘录像机外网远程设置ddns方法

1、为了便于解释在下文介绍中,硬盘录像机、网络摄像机、网络硬盘录像机统一称为“大华设备”2、外网最好是电信。如果不是,那必须要确认客户的外网IP是唯一的,不是与其他用户共用的。3、首先确保“大华设... 查看详情

家用监控录像机挑选(代码片段)

目标:选购家用便宜的4路数字录像机 一、硬件相关1.需要h.265压缩方式,相对于h.264的压缩效率高一半,h.265压缩后占更小的硬盘2.录像机支持的摄像头分辨率越多越好:海康威DS-7804NB-K1/C为代表:5MP/3MP/1080P/UXGA/960P/720P/VGA/4CIF/... 查看详情

大华摄像头录像视频,可以使用potplayer剪切

  最近买了个高档监控摄像头,又加了个64G卡,白天录像。  昨晚复制录像之后,就想剪切其中的精彩片段。找了几个剪切软件,连格式都识别不了!这如何是好?  吾是使用PotPlayer加速回放的。Pot... 查看详情

海康威视录像机登录账号有啥功能

...海康威视录像机登录账号的功能是可以通过网络远程观看监控画面并对话海康威视于2012年11月29日在中国商标网申请创建,是杭州海康威视数字技术股份有限公司旗下品牌。海康威视有USB闪存盘,报警器,便携式媒体播放器,便... 查看详情

大华海康nvr录像java下载及web播放(代码片段)

...一、视频下载  视频下载比较简单,厂商都提供了针对JAVA集成SDK的DEMO,照着抄一抄就可以。JAVA调用C库的SDK,一般使用JNA技术。一些细节问题  1.下载的文件名要唯一,避免相互覆盖,可以用GUID随机生成... 查看详情