VideoCapture.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. using DirectShow;
  2. using DirectShow.BaseClasses;
  3. using Sonic;
  4. using System;
  5. using System.Drawing;
  6. using System.Drawing.Drawing2D;
  7. using System.Drawing.Imaging;
  8. using System.Drawing.Text;
  9. using System.Linq;
  10. using System.Runtime.InteropServices;
  11. using System.Windows.Forms;
  12. namespace VideoPlayLib
  13. {
  14. public class VideoCapture : IDisposable
  15. {
  16. //[ComVisible(true)]
  17. //[Guid("8AF6F710-1AF5-4952-AAFF-ACCD0DB2C9BB")]
  18. [AMovieSetup(true)]
  19. //[PropPageSetup(typeof(AboutForm))]
  20. private abstract class OsdFilter : TransformFilter
  21. {
  22. #region Constructor
  23. protected OsdFilter()
  24. : base("OSD Filter")
  25. {
  26. }
  27. #endregion Constructor
  28. #region Overridden Methods
  29. public override int CheckInputType(AMMediaType pmt)
  30. {
  31. if (pmt.majorType != MediaType.Video)
  32. {
  33. return VFW_E_TYPE_NOT_ACCEPTED;
  34. }
  35. if (pmt.subType != MediaSubType.RGB32)
  36. {
  37. return VFW_E_TYPE_NOT_ACCEPTED;
  38. }
  39. if (pmt.formatType != FormatType.VideoInfo)
  40. {
  41. return VFW_E_TYPE_NOT_ACCEPTED;
  42. }
  43. if (pmt.formatPtr == IntPtr.Zero)
  44. {
  45. return VFW_E_TYPE_NOT_ACCEPTED;
  46. }
  47. return NOERROR;
  48. }
  49. [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
  50. private static extern void CopyMemory(IntPtr dest, IntPtr src, int count);
  51. public override int Transform(ref IMediaSampleImpl input, ref IMediaSampleImpl sample)
  52. {
  53. var lDataLength = input.GetActualDataLength();
  54. sample.SetActualDataLength(lDataLength);
  55. IntPtr ptrIn;
  56. IntPtr ptrOut;
  57. input.GetPointer(out ptrIn);
  58. sample.GetPointer(out ptrOut);
  59. var bmiIn = (BitmapInfoHeader)Input.CurrentMediaType;
  60. var bmiOut = (BitmapInfoHeader)Output.CurrentMediaType;
  61. using (var bmpIn = new Bitmap(bmiIn.Width, bmiIn.Height, bmiIn.Width * 4, PixelFormat.Format32bppRgb, ptrIn))
  62. {
  63. bmpIn.RotateFlip(RotateFlipType.RotateNoneFlipY);
  64. BurnOsd(bmpIn);
  65. bmpIn.RotateFlip(RotateFlipType.RotateNoneFlipY);
  66. var data = bmpIn.LockBits(new Rectangle(Point.Empty, bmpIn.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
  67. CopyMemory(ptrOut, data.Scan0, bmiIn.Width * bmiIn.Height * 4);
  68. bmpIn.UnlockBits(data);
  69. bmpIn.Dispose();
  70. }
  71. return S_OK;
  72. }
  73. protected abstract void BurnOsd(Bitmap frame);
  74. public override int DecideBufferSize(ref IMemAllocatorImpl pAlloc, ref AllocatorProperties prop)
  75. {
  76. if (!Output.IsConnected) return VFW_E_NOT_CONNECTED;
  77. if (Output.CurrentMediaType.majorType != MediaType.Video) return VFW_E_INVALIDMEDIATYPE;
  78. var actual = new AllocatorProperties();
  79. var bmi = (BitmapInfoHeader)Output.CurrentMediaType;
  80. if (bmi == null) return VFW_E_INVALIDMEDIATYPE;
  81. prop.cbBuffer = bmi.GetBitmapSize();
  82. if (prop.cbBuffer < bmi.ImageSize)
  83. {
  84. prop.cbBuffer = bmi.ImageSize;
  85. }
  86. prop.cBuffers = 1;
  87. var hr = pAlloc.SetProperties(prop, actual);
  88. return hr;
  89. }
  90. public override int GetMediaType(int iPosition, ref AMMediaType pMediaType)
  91. {
  92. if (iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  93. if (pMediaType == null) return E_INVALIDARG;
  94. if (!Input.IsConnected) return VFW_E_NOT_CONNECTED;
  95. AMMediaType.Copy(Input.CurrentMediaType, ref pMediaType);
  96. return NOERROR;
  97. }
  98. public override int CheckTransform(AMMediaType mtIn, AMMediaType mtOut)
  99. {
  100. return AMMediaType.AreEquals(mtIn, mtOut) ? NOERROR : VFW_E_INVALIDMEDIATYPE;
  101. }
  102. #endregion Overridden Methods
  103. }
  104. private class TimeOsdFilter : OsdFilter
  105. {
  106. private readonly int _channel;
  107. private const bool VideoOsdHighQuality = true;
  108. private static readonly Font VideoOsdFont = new Font("微软雅黑", 20);
  109. public TimeOsdFilter(int channel)
  110. {
  111. _channel = channel;
  112. }
  113. protected override void BurnOsd(Bitmap frame)
  114. {
  115. var osdText = string.Format("{0:yyyy年MM月dd日 dddd HH:mm:ss.ff}{1}CAM#{2} - {3}", DateTime.Now, Environment.NewLine, _channel + 1, "");
  116. var loc = Point.Empty;
  117. var locT = new PointF(loc.X, loc.Y - 1);
  118. var locB = new PointF(loc.X, loc.Y + 1);
  119. var locL = new PointF(loc.X - 1, loc.Y);
  120. var locR = new PointF(loc.X + 1, loc.Y);
  121. using (Graphics dc = Graphics.FromImage(frame))
  122. {
  123. if (VideoOsdHighQuality)
  124. {
  125. dc.CompositingQuality = CompositingQuality.HighQuality;
  126. dc.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  127. dc.SmoothingMode = SmoothingMode.HighQuality;
  128. dc.InterpolationMode = InterpolationMode.HighQualityBicubic;
  129. }
  130. else
  131. {
  132. dc.CompositingQuality = CompositingQuality.HighSpeed;
  133. dc.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
  134. dc.SmoothingMode = SmoothingMode.HighSpeed;
  135. dc.InterpolationMode = InterpolationMode.NearestNeighbor;
  136. }
  137. dc.DrawString(osdText, VideoOsdFont, Brushes.Black, locT);
  138. dc.DrawString(osdText, VideoOsdFont, Brushes.Black, locB);
  139. dc.DrawString(osdText, VideoOsdFont, Brushes.Black, locL);
  140. dc.DrawString(osdText, VideoOsdFont, Brushes.Black, locR);
  141. dc.DrawString(osdText, VideoOsdFont, Brushes.White, loc);
  142. }
  143. }
  144. }
  145. private readonly int _deviceIndex;
  146. private readonly Control[] _displayContainer;
  147. public VideoCapture(int deviceIndex, params Control[] displayContainer)
  148. {
  149. _deviceIndex = deviceIndex;
  150. _displayContainer = displayContainer;
  151. }
  152. public bool IsRuning { get; private set; }
  153. public void Run()
  154. {
  155. var devices = new DSVideoCaptureCategory().Objects.OrderBy(p => p.Name).ToArray();
  156. var graph = new Graph();
  157. var cd = graph.AddDeviceFilter(devices[_deviceIndex]);
  158. var av = graph.AddFilter(new DSFilter(KnownGuid.Misc.AviDecompressor), "av");
  159. var to = graph.AddFilter(new DSFilter(new TimeOsdFilter(_deviceIndex)), "to");
  160. var vr = graph.AddFilter(new DSFilter(KnownGuid.VideoRender.VideoMixingRenderer7), "vr");
  161. graph.Connect(cd.OutputPin, av.InputPin);
  162. graph.Connect(av.OutputPin, to.InputPin);
  163. graph.Connect(to.OutputPin, vr.InputPin);
  164. _displayContainer.ToList().ForEach(p => new VideoInControl(graph, p));
  165. graph.Run();
  166. }
  167. public void Dispose()
  168. {
  169. throw new NotImplementedException();
  170. }
  171. }
  172. }