你的位置:首页 > ASP.net教程

[ASP.net教程]C# 实现IP视频监控(摄像头)画面推送(简单的不能再简单的DEMO)

 

  最近继续在家休息,在完成上一个Python抓取某音乐网站爬虫后,琢磨着实现一个基于HTTP推送的 IP视频监控,比如外出的时候,在家里

开启一个监控端(摄像头+服务端),可以看到实时画面,如果再加上自动告警,就更好了。公网访问需要在 路由器上设置 花生壳+端口转发。

计划在退休的安卓手机上实现这IP视频监控软件,虽然应用市场一大堆别人写好的软件,不过我觉得吧,既然是程序员,自己敲代码实现的软件会

更有成就感。考虑到需要先验证下方案的可行性,我用比较熟悉的C# 控制台实现了一个DEMO。

 

设想的方案:

  1.实现一个简单HTTP服务器,用来接受请求并启动一个线程处理图片流的推送功能

  2.开发一个实时抓取图片的线程,并将图片交给HTTP推送线程

  3.HTTP的请求URL参数中 附带推送频率、图片高度和宽度

  4.使用一个IP摄像头监控端(或者Firefox浏览器),实时查看视频画面

  5.循环录制视频(未实现)

  6.对画面进行监控告警(未实现)

 

核心技术点:

  1.HttpListener (HTTP.SYS)

  2.HTTP :multipart/x-mixed-replace;

  3.线程同步、委托、事件

  4.摄像头驱动、图片抓取(Andrew Kirillov 写的)

  5.图片流解析,显示(Andrew Kirillov 写的,也可以直接在Firefox浏览器打开直接显示)

 

运行截图:

  1.视频监控端 (Andrew Kirillov 写的 视频源支持N种,当前配置推送频率50毫秒 w=240&h=120)

  

 

  2.视频服务端(我写的 简陋的DEMO 不过实现了功能 嘎嘎)

 

 

下面开始贴核心源码(最近右胳膊有石膏,左手写代码  凑合看吧!):

 

1.建立HTTP服务:

 1 using (HttpListener listerner = new HttpListener()) 2         { 3           listerner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;//指定身份验证 Anonymous匿名访问 4           listerner.Prefixes.Add("http://+:6666/"); 5            6           //listerner.Prefixes.Add("http://+/"); 7           //listerner.Prefixes.Add("http://+:8080/"); 8           //listerner.Prefixes.Add("http://+:6666/"); 9           //listerner.Prefixes.Add("http://+/video.cgi/");10           //listerner.Prefixes.Add("http://+:8080/video.cgi/");11 12           listerner.Start();13           Console.WriteLine("WebServer Start Successed.......");14           while (true)15           {16             try17             {18               //等待请求连接19               //没有请求则GetContext处于阻塞状态20               HttpListenerContext ctx = listerner.GetContext();21 22               SendImgService oService = new SendImgService();23               oService.Ctx = ctx;24               localsev.NewFrame += new CameraEventHandler(oService.camera_NewFrame);25               ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), oService);26 27               //Thread osThread = new Thread(new ThreadStart(oService.ServiceRun));28               //osThread.Start();29             }30             catch (Exception ex)31             {32               Console.WriteLine(ex);33             }34           }35           listerner.Stop();36           listerner.Close();37         }

View Code

2.启动本地视频头,并抓取图片

 1 public void ServiceRun() 2     { 3  4       FilterCollection filters = new FilterCollection(FilterCategory.VideoInputDevice); 5  6       if (filters.Count == 0) 7         throw new ApplicationException(); 8  9       // add all devices to combo10       foreach (Filter filter in filters)11       {12         Console.WriteLine(filter.Name + ":" + filter.MonikerString);13       }14       CaptureDevice localSource = new CaptureDevice();15       localSource.VideoSource = filters[0].MonikerString;16 17       // create camera18       camera = new Camera(localSource);19       // start camera20       camera.Start();21 22 23       // set event handlers24       camera.NewFrame += new CameraEventHandler(camera_NewFrame);25 26     }27 28     // On new frame ready29     private void camera_NewFrame(object sender, CameraEventArgs e)30     {31       if (seq == 999)32       {33         seq = 0;34       }35     //  Console.WriteLine("LocalCamService get camera_NewFrame ==> {0}", ++seq);36 37       // lock38       Monitor.Enter(this);39 40       if (camera != null)41       {42         camera.Lock();43 44         // dispose old frame45         if (lastFrame != null)46         {47           lastFrame.Dispose();48         }49         // draw frame50         if (camera.LastFrame != null)51         {52           lastFrame = (Bitmap)camera.LastFrame.Clone();53           // notify client54           if (NewFrame != null)55             NewFrame(this, new CameraEventArgs(lastFrame));56         }57 58 59         camera.Unlock();60       }61 62       // unlock63       Monitor.Exit(this);64     }65   }

View Code

3.图片推送

 1 public void ServiceRun() 2     { 3       remoteInfo = ctx.Request.RemoteEndPoint.ToString(); 4       string intervalstr = ctx.Request.QueryString["i"]; 5       string widthstr = ctx.Request.QueryString["w"]; 6       string heightstr = ctx.Request.QueryString["h"]; 7  8       if (!string.IsNullOrWhiteSpace(intervalstr)) 9       {10         interval = int.Parse(intervalstr);11       }12       if (!string.IsNullOrWhiteSpace(widthstr))13       {14         width = int.Parse(widthstr);15       }16       if (!string.IsNullOrWhiteSpace(heightstr))17       {18         height = int.Parse(heightstr);19       }20       Console.WriteLine("Accept one new request:{0},interval:[{1}]", remoteInfo, interval);21 22 23       ctx.Response.StatusCode = 200;//设置返回给客服端http状态代码24       ctx.Response.ContentType = "multipart/x-mixed-replace; boundary=--BoundaryString";25 26       string rspheard = "--BoundaryString\r\nContent-type: image/jpg\r\nContent-Length: {0}\r\n\r\n";27       string strrn = "\r\n";28 29       using (Stream stream = ctx.Response.OutputStream)30       {31         while (true)32         {33           Thread.Sleep(interval);34 35           try36           {37             // lock38             Monitor.Enter(this);39 40             if (newFrame == null)41             {42               continue;43             }44             //得到一个ms对象45             byte[] imageBuffer;46             using (MemoryStream ms = new MemoryStream())47             {48 49               //newFrame = (Bitmap)GetThumbnail(newFrame, width, height);50               //将图片保存至内存流51               newFrame.Save(ms, ImageFormat.Jpeg);52 53               rspheard = string.Format(rspheard, ms.Length);54 55               byte[] heardbuff = Encoding.ASCII.GetBytes(rspheard);56               stream.Write(heardbuff, 0, heardbuff.Length);57 58               imageBuffer = new byte[512];59               int c;60               ms.Position = 0;61               //通过内存流读取到imageBytes62               while ((c = ms.Read(imageBuffer, 0, 512)) > 0)63               {64                 stream.Write(imageBuffer, 0, c);65               }66               byte[] rnbuff = Encoding.ASCII.GetBytes(strrn);67               stream.Write(rnbuff, 0, rnbuff.Length);68 69               Console.WriteLine("[{0}] : SendImgService send NewFrame", remoteInfo);70 71             }72 73             // stream.Flush();74           }75           catch (Exception ex)76           {77             Console.WriteLine(ex);78 79             break;80           }81           finally82           {83             // unlock84             Monitor.Exit(this);85           }86         }87       }88       Console.WriteLine("[{0}] : 线程结束...", remoteInfo);89     }

View Code

 

附件:(刚会传文件,还不知道怎么插入链接,谁教我下?)

可运行程序:

http://files.cnblogs.com/files/ryhan/%E7%9B%91%E6%8E%A7%E5%8F%8A%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%8F%AF%E8%BF%90%E8%A1%8C%E7%A8%8B%E5%BA%8F.zip

 

监控端源码:

http://files.cnblogs.com/files/ryhan/%E7%9B%91%E6%8E%A7%E7%AB%AF%E6%BA%90%E7%A0%81.zip

 

服务端源码:

http://files.cnblogs.com/files/ryhan/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%BA%90%E7%A0%81%28%E5%8D%9A%E5%AE%A2%E4%B8%AD%E5%AE%9E%E7%8E%B0%29.zip

 

PS:

  1.建议用VS2010打开

  2.监控端cv_src目录下cv3.sln为监控客户端程序,用来看画面,cameras.config配置视频源

  3.HttpImageStream是本次实现的图片推送Demo 效率上估计有点问题。

  4.运行HttpImageStream时,建议电脑上有摄像头,不然估计会无法启动。