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

参考上一篇:

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

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

简单设计界面如下:

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

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 = "暂停";
            }
        }
时间: 2024-10-06 13:20:40

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

海康&amp;大华&amp;DSS视频拉流-RTSP转RTMP多媒体播放技术

海康&大华&DSS获取RTSP 实时流 海康:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username: 用户名.例如admin.password: 密码.例如12345.ip: 为设备IP.例如 192.0.0.64.port: 端口号默认为554,若为默认可不填写.codec:有h264.MPEG-4.mpeg4这几种.channel: 通道号,起始为1.例如通道1

海康/大华 IpCamera RTSP地址和格式

海康:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username: 用户名.例如admin.password: 密码.例如12345.ip: 为设备IP.例如 192.0.0.64.port: 端口号默认为554,若为默认可不填写.codec:有h264.MPEG-4.mpeg4这几种.channel: 通道号,起始为1.例如通道1,则为ch1.subtype: 码流类型,主码

海康大华RTSP格式

海康实时流:rtsp://admin:[email protected]:554/h264/ch4/main/av_stream海康回放流(模拟通道):rtsp://admin:[email protected]:554/Streaming/tracks/101?starttime=20120802t063812z&endtime=20120802t064816z海康回放流(IP通道):    rtsp://admin:[email protected]:554/Streaming/tracks

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

EasyNVR开发机是通过定制的硬件机器来运行对应的流媒体软件,因此硬件的授权是和开发机内部的软件相互绑定的,因此失去授权实际是软件授权出现了问题. 解决问题: 之前版本的授权方式是通过绑定机器的机器码来,设置对应的激活码来给对应的硬件设备上的软件进行授权,软件读取到对应的成功的激活码就进行成功授权. EasyNVR3.3.1版本正对软件版本授权有了优化,将之前的单纯的激活方式改为了Pem文件授权,更加方便了客户的授权,也提高了授权的安全性和稳定性.因此对应出现硬件授权不稳定的,可以联系相关技术

RTSP安防摄像头/海康大华硬盘录像机/NVR网页低延时播放流媒体服务器EasyNVR调取接口报Unauthorized如何解决?

随着雪亮工程.明厨亮灶.手机看店.智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网.微信直播,我们知道摄像头直播的春天了.将安防摄像头或NVR上的视频流转成互联网直播常用的RTMP.HTTP-FLV.HLS等流格式再分发给用户端进行直播,不管身处何地都可以通过移动通讯设备查看监控设备,这些功能是EasyNVR互联网直播系统研发和设计的初衷和基础功能.另外EasyNVR增值功能是可通过接口二次集成在自己的原有的web业务系统实现网页.H5无插件实时直播. EasyNVR调取接口报Unautho

海康大华摄像头高起播低延时RTSP网页无插件流媒体播放器EasyPlayer-RTSP-Win录像和抓图实现线程优化方案分享

EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件).Android.iOS三个平台,是由青犀TSINGSEE开放平台开发和维护的区别于市面上大部分的通用播放器,EasyPlayer-RTSP系列从2014年初发展至今得到了各行各业(尤其是安防行业)的广泛应用,其主要原因是EasyPlayer-RTSP更加精炼.更加专注,具备低延时和高RTSP协议兼容性. ? EasyPlayer-RTSP-Win录像和抓图实现线程优化 测试发现

RTSP安防网络摄像头/海康大华硬盘录像机网页无插件直播流媒体服务器EasyNVR之鉴权接口的调用配置说明

进入移动互联网时代以来,企业微信公众号已成为除官网以外非常重要的宣传渠道,当3.2亿直播用户与9亿微信用户的势能累加,在微信上开启直播已成为越来越多企业的必然选择. EasyNVR核心在于摄像机的音视频流的获取.转换.转码与高性能分发,同时同步完成对实时直播流的录像存储,在客户端(PC浏览器.Android.iOS.微信)进行录像文件的检索.回放和下载. EasyNVR鉴权配置说明 发现问题 在实际对接项目中,很多用户需要根据自身业务层的用户权限,来决定调用视频流具体资源,EasyNVR在设计时

Onvif/RTSP海康大华网络安防摄像机网页无插件直播方案EasyNVR中直播页面和视频列表页面的区别介绍

背景分析 随着平安城市.智慧城市.雪亮工程.智能交通等各项建设的持续开展,安防逐渐得到普及,面对如此广阔的市场,对安防企业来说不仅仅是机遇更多的是挑战.现今大多数摄像头一直没能摆脱人工监控的传统监控方式,由此导致了大量视频数据堆积占用存储资源.实时性差.检索困难等问题,海量摄像头带来的海量视频数据检索工作需要耗费大量警力. 为了解决这些问题,近年来,视频监控行业发展方向主要为:“高清化.网络化.智能化”.视频监控设备技术性极强,系统的创新升级同时也在引导市场需求的变化并创造了新的市场需求.因此,

如何实现多路海康大华等RTSP数据转RTMP推送

一个好的转发模块,首先要低延迟!其次足够稳定.灵活.有状态反馈机制.资源占用低,跨平台,最好以接口形式提供,便于第三方系统集成. 以Windows平台为例,我们的考虑的点如下 1. 拉流:通过RTSP直播播放SDK的数据回调接口,拿到音视频数据: 2. 转推:通过RTMP直播推送SDK的编码后数据输入接口,把回调上来的数据,传给RTMP直播推送模块,实现RTSP数据流到RTMP服务器的转发: 3. 录像:如果需要录像,借助RTSP直播播放SDK,拉到音视频数据后,直接存储MP4文件即可: 4.