0%

复制代码

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 \= "暂停";
        }
    }

复制代码