针对监控摄像机(海康、大华等)进行手动录像的录像文件播放器功能设计
生活随笔
收集整理的這篇文章主要介紹了
针对监控摄像机(海康、大华等)进行手动录像的录像文件播放器功能设计
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
參考上一篇:
針對監控攝像機(海康、大華等)進行手動錄像的功能設計
?
錄像后需要自定義一個播放器來播放錄像文件。
簡單設計界面如下:
?
打開文件,可暫停,可停止,可以拖動進度條。
?
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);#endregionInitVars();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;}elseif (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 = "暫停";}}?
轉載于:https://www.cnblogs.com/jhlong/p/6513956.html
總結
以上是生活随笔為你收集整理的针对监控摄像机(海康、大华等)进行手动录像的录像文件播放器功能设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 404.2错误解决方案
- 下一篇: SetWindowsHookEx