针对上一篇的数据流的录制,相应的有数据流的回放,回放包括:显示,暂停,快进快退,循环播放等功能。
一、录制二进制流:
这个主要是快进快退以及循环播放比较麻烦,因为得控制好文件流的当前位置,通过seek函数合理设定。主要是根据PixelDataLength属性值来进行调整,因为这个值记录了数据流的byte数,下面是代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using Microsoft.Kinect; 7 using System.IO; 8 using System.Drawing; 9 using System.Drawing.Imaging; 10 using System.Runtime.InteropServices; 11 12 namespace HARS_WFmApp.Replay 13 { 14 class ColorStreamBinaryReplay:ColorStreamReplay 15 { 16 private BinaryReader reader; 17 private Stream replayStream; 18 private string _path; 19 private long _beginStream; 20 21 public int PixelDataLength { get; set; } 22 public int FrameWidth { get; set; } 23 public int FrameHeight { get; set; } 24 private long streamPosition; 25 26 internal ColorStreamBinaryReplay(string path) 27 { 28 _path = Path.Combine(path, "Color.replay"); 29 replayStream = File.OpenRead(_path); 30 reader = new BinaryReader(replayStream); 31 _beginStream = replayStream.Seek(0, SeekOrigin.Begin); 32 } 33 34 public override Bitmap Replay() 35 { 36 if (reader.BaseStream.Position >= reader.BaseStream.Length) 37 { 38 if (GlobalVar.CyclePlay) 39 { 40 replayStream = File.OpenRead(_path); 41 reader = new BinaryReader(replayStream); 42 } 43 else 44 { 45 replayStream.Seek(-PixelDataLength - 12, SeekOrigin.End); 46 } 47 } 48 FrameWidth = reader.ReadInt32(); 49 FrameHeight = reader.ReadInt32(); 50 PixelDataLength = reader.ReadInt32(); 51 52 //CopyPixelData 53 byte[] pixelData = new byte[PixelDataLength]; 54 replayStream.Read(pixelData, 0, PixelDataLength); 55 56 //Convert To Bitmap 57 var bitmapImage = new Bitmap(FrameWidth, FrameHeight, PixelFormat.Format32bppRgb); 58 59 BitmapData bmapdata = bitmapImage.LockBits( 60 new Rectangle(0, 0, 61 FrameWidth, FrameHeight), 62 ImageLockMode.WriteOnly, 63 bitmapImage.PixelFormat); 64 var ptr = bmapdata.Scan0; 65 Marshal.Copy(pixelData, 0, ptr, 66 PixelDataLength); 67 bitmapImage.UnlockBits(bmapdata); 68 69 //return 70 return bitmapImage; 71 } 72 73 public override void Stop() 74 { 75 if (reader != null) 76 { 77 reader.Close(); 78 reader.Dispose(); 79 } 80 if (replayStream != null) 81 { 82 replayStream.Dispose(); 83 replayStream = null; 84 } 85 } 86 87 public override void Next() 88 { 89 if (reader.BaseStream.Position >= reader.BaseStream.Length) 90 { 91 if (GlobalVar.CyclePlay) 92 { 93 replayStream = File.OpenRead(_path); 94 reader = new BinaryReader(replayStream); 95 } 96 } 97 else 98 { 99 FrameWidth = reader.ReadInt32(); 100 FrameHeight = reader.ReadInt32(); 101 PixelDataLength = reader.ReadInt32(); 102 replayStream.Seek(PixelDataLength, SeekOrigin.Current); 103 } 104 } 105 106 public override void Prev() 107 { 108 if (reader.BaseStream.Position <= _beginStream) 109 { 110 reader.BaseStream.Position = _beginStream; 111 } 112 else 113 { 114 replayStream.Seek(-PixelDataLength - 12, SeekOrigin.Current); 115 FrameWidth = reader.ReadInt32(); 116 FrameHeight = reader.ReadInt32(); 117 PixelDataLength = reader.ReadInt32(); 118 replayStream.Seek(-12, SeekOrigin.Current); 119 } 120 } 121 } 122 }
二、视频文件回放
这里是通过emgucv的videoreader来进行的,同时在实现快进快退的时候,是通过设置文件的Position属性来完成
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using HARS_WFmApp.Extensions; 7 using System.IO; 8 using Emgu.CV; 9 using Emgu.CV.VideoSurveillance; 10 using Emgu.CV.Structure; 11 using Emgu.CV.CvEnum; 12 using System.Runtime.InteropServices; 13 namespace HARS_WFmApp.Replay 14 { 15 class ColorStreamAVIReplay:ColorStreamReplay 16 { 17 string _path; 18 IntPtr _capture; 19 int totalFrames; 20 int curFrame; 21 22 internal ColorStreamAVIReplay(string path) 23 { 24 _path = Path.Combine(path, "Color.avi"); 25 _capture = CvInvoke.cvCreateFileCapture(_path); 26 totalFrames = (int)CvInvoke.cvGetCaptureProperty(_capture, CAP_PROP.CV_CAP_PROP_FRAME_COUNT); 27 curFrame = 0; 28 } 29 30 public override System.Drawing.Bitmap Replay() 31 { 32 if (curFrame >= totalFrames) 33 { 34 if (GlobalVar.CyclePlay) 35 { 36 curFrame = 0; 37 } 38 else 39 curFrame = totalFrames -1; 40 } 41 if (curFrame < 0) 42 { 43 if (GlobalVar.CyclePlay) 44 { 45 curFrame = totalFrames - 1; 46 } 47 else 48 curFrame = 0; 49 } 50 CvInvoke.cvSetCaptureProperty(_capture, CAP_PROP.CV_CAP_PROP_POS_FRAMES, curFrame++); 51 IntPtr iplImage = CvInvoke.cvQueryFrame(_capture); 52 return ConvertIntPtrToBitmap(iplImage); 53 } 54 55 public static System.Drawing.Bitmap ConvertIntPtrToBitmap(IntPtr ptrImage) 56 { 57 MIplImage mi = (MIplImage)Marshal.PtrToStructure(ptrImage, typeof(MIplImage)); 58 Image<Rgb, Byte> image = new Image<Rgb, Byte>(mi.width, mi.height, mi.widthStep, mi.imageData); 59 return image.ToBitmap(); 60 } 61 62 public override void Stop() 63 { 64 65 } 66 67 public override void Next() 68 { 69 if (curFrame >= totalFrames) 70 { 71 if (GlobalVar.CyclePlay) 72 { 73 curFrame = 0; 74 } 75 else 76 curFrame = totalFrames - 1; 77 } 78 else 79 curFrame = curFrame + 1; 80 } 81 82 public override void Prev() 83 { 84 if (curFrame <= 0) 85 { 86 if (GlobalVar.CyclePlay) 87 { 88 curFrame = totalFrames - 1; 89 } 90 else 91 curFrame = 0; 92 } 93 else 94 curFrame = curFrame - 1; 95 } 96 } 97 }
三、图片文件回放
这个比较简单,因为在存的时候文件名是以id号命名,这样的话就直接控制好文件名相关信息就行
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using System.IO; 7 using System.Drawing; 8 9 namespace HARS_WFmApp.Replay 10 { 11 class ColorStreamJPGReplay:ColorStreamReplay 12 { 13 private string _path; 14 //private int frameID; 15 16 internal ColorStreamJPGReplay(string path) 17 { 18 _path = Path.Combine(path, "Color"); 19 //frameID = 1; 20 } 21 22 public override Bitmap Replay() 23 { 24 string pathtmp = Path.Combine(_path, GlobalVar.ReplayFrameID.ToString() + ".jpg"); 25 //frameID++; 26 return new Bitmap(pathtmp); 27 } 28 29 public override void Stop() 30 { 31 32 } 33 34 public override void Next() 35 { 36 //throw new NotImplementedException(); 37 } 38 39 public override void Prev() 40 { 41 //throw new NotImplementedException(); 42 } 43 } 44 }