zoukankan      html  css  js  c++  java
  • 针对监控摄像机(海康、大华等)进行手动录像的录像文件播放器功能设计

    参考上一篇:

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

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

    简单设计界面如下:

     

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

    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 = "暂停";
                }
            }
  • 相关阅读:
    ios存储 plist 偏好设置 自定义对象存储
    Spring中Bean的生命中期与InitializingBean和DisposableBean接口
    Spring中BeanPostProcessor
    cxf
    ios快捷键
    UIPickerView
    ios通知-kvo
    7.python 装饰器
    5.python内置函数
    4.python 深拷贝 浅拷贝 函数 匿名函数lambda
  • 原文地址:https://www.cnblogs.com/jhlong/p/6513956.html
Copyright © 2011-2022 走看看