C#实现MJPEG服务器
实现流写入,将图像作为mjpeg写入
public class MjpegWriter : IDisposable
{ private static byte[] CRLF = new byte[] { , };
private static byte[] EmptyLine = new byte[] { , , , }; private string _Boundary; public MjpegWriter(Stream stream)
: this(stream, "--boundary")
{ } public MjpegWriter(Stream stream, string boundary)
{ this.Stream = stream;
this.Boundary = boundary;
} public string Boundary { get; private set; }
public Stream Stream { get; private set; } public void WriteHeader()
{ Write(
"HTTP/1.1 200 OK\r\n" +
"Content-Type: multipart/x-mixed-replace; boundary=" +
this.Boundary +
"\r\n"
); this.Stream.Flush();
} public void Write(Image image)
{
MemoryStream ms = BytesOf(image);
this.Write(ms);
} public void Write(MemoryStream imageStream)
{ StringBuilder sb = new StringBuilder(); sb.AppendLine();
sb.AppendLine(this.Boundary);
sb.AppendLine("Content-Type: image/jpeg");
sb.AppendLine("Content-Length: " + imageStream.Length.ToString());
sb.AppendLine(); Write(sb.ToString());
imageStream.WriteTo(this.Stream);
Write("\r\n"); this.Stream.Flush(); } private void Write(byte[] data)
{
this.Stream.Write(data, , data.Length);
} private void Write(string text)
{
byte[] data = BytesOf(text);
this.Stream.Write(data, , data.Length);
} private static byte[] BytesOf(string text)
{
return Encoding.ASCII.GetBytes(text);
} private static MemoryStream BytesOf(Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms;
} public string ReadRequest(int length)
{ byte[] data = new byte[length];
int count = this.Stream.Read(data, , data.Length); if (count != )
return Encoding.ASCII.GetString(data, , count); return null;
} #region IDisposable Members public void Dispose()
{ try
{ if (this.Stream != null)
this.Stream.Dispose(); }
finally
{
this.Stream = null;
}
} #endregion
}
服务器实现:
public class ImageStreamingServer : IDisposable
{ private List<Socket> _Clients;
private Thread _Thread; public ImageStreamingServer() : this(IRImg.Snapshots())
{ } public ImageStreamingServer(IEnumerable<Image> imagesSource)
{ _Clients = new List<Socket>();
_Thread = null; this.ImagesSource = imagesSource;
this.Interval = ; } public IEnumerable<Image> ImagesSource { get; set; } public int Interval { get; set; } public IEnumerable<Socket> Clients { get { return _Clients; } } public bool IsRunning { get { return (_Thread != null && _Thread.IsAlive); } } public void Start(int port)
{ lock (this)
{
_Thread = new Thread(new ParameterizedThreadStart(ServerThread));
_Thread.IsBackground = true;
_Thread.Start(port);
} } public void Start()
{
this.Start();
} public void Stop()
{ if (this.IsRunning)
{
try
{
_Thread.Join();
_Thread.Abort();
}
finally
{ lock (_Clients)
{ foreach (var s in _Clients)
{
try
{
s.Close();
}
catch { }
}
_Clients.Clear(); } _Thread = null;
}
}
} private void ServerThread(object state)
{ try
{
Socket Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Server.Bind(new IPEndPoint(IPAddress.Any, (int)state));
Server.Listen(); System.Diagnostics.Debug.WriteLine(string.Format("Server started on port {0}.", state)); foreach (Socket client in Server.IncommingConnectoins())
ThreadPool.QueueUserWorkItem(new WaitCallback(ClientThread), client); }
catch { } this.Stop();
} private void ClientThread(object client)
{ Socket socket = (Socket)client;
lock (_Clients)
_Clients.Add(socket); try
{
using (MjpegWriter wr = new MjpegWriter(new NetworkStream(socket, true)))
{
wr.WriteHeader();
foreach (var imgStream in IRImg.Streams(this.ImagesSource))
{
if (this.Interval > )
Thread.Sleep(this.Interval); wr.Write(imgStream);
} }
}
catch { }
finally
{
lock (_Clients)
_Clients.Remove(socket);
}
} public void Dispose()
{
this.Stop();
}
} static class SocketExtensions
{ public static IEnumerable<Socket> IncommingConnectoins(this Socket server)
{
while (true)
yield return server.Accept();
} } static class IRImg
{
public static IEnumerable<Image> Snapshots()
{
while (true)
{
yield return IRCommon.Instance.GetBitmap();
}
} internal static IEnumerable<MemoryStream> Streams(this IEnumerable<Image> source)
{
MemoryStream ms = new MemoryStream(); foreach (var img in source)
{
ms.SetLength();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
yield return ms;
} ms.Close();
ms = null; yield break;
} }
将上面代码中的这行 IRCommon.Instance.GetBitmap();改为自己的bitmap来源即可实现mjpeg图像传输
浏览器可直接输入 127.0.0.1:8080访问,chrome没问题,但是ie下,会一直下载图片
C#客户端可以用afroge实现浏览,具体可参考:在WPF中使用AForge控件
本项目来源:Motion JPEG Streaming Server (codeproject)
C#实现MJPEG服务器的更多相关文章
- 适用于Windows和Linux的Yolo-v3和Yolo-v2(上)
适用于Windows和Linux的Yolo-v3和Yolo-v2(上) https://github.com/eric-erki/darknetAB (用于对象检测的神经网络)-Tensor Core ...
- C#开源实现MJPEG流传输
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 许久以前写了篇文章<基于.NET打造IP智能网络视频监控系统>,记录和介绍了自己几年来积 ...
- Web服务器部署浅析
企业内网站 中小型企业一般将企业宣传网站外包给第三方进行统一设计.部署和运维.大型企业因为访问量和数据量有所增加,部分网站可能具备在线咨询或订单的功能,此类Web服务器采用最通用的IU机架式服务器以降 ...
- 基于mjpg_streamer视频服务器移植【转】
本文转载自:http://blog.csdn.net/wavemcu/article/details/7539560 MJPG简介: MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名 ...
- M-JPEG和MPEG-4的区别 M-JPEG VS MPEG
http://blog.sina.com.cn/s/blog_4b357b300100gre9.html M-JPEG VS MPEG http://blog.csdn.net/bluesky_sun ...
- 网络摄像头Androi端显示(mjpeg)源码分析
main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and ...
- M-JPEG、MPEG4、H.264都有何区别
压缩方式是网络视频服务器和网络摄像机的核心技术,压缩方式很大程度上决定着图像的质量.压缩比.传输效率.传输速度等性能,它是评价网络视频服务器和网络摄像机性能优劣的重要一环.随着多媒体技术的发展,相继推 ...
- arm开发板6410/2440上mjpg-streamer网络视频服务器移植
摄像头移植 一.环境 主机环境 :ubuntu 10.10 目标板 :FS-S5PC100 主机工具链 :gcc-4.4.5 交叉工具链 :arm-unknown-li ...
- 基于mjpg-streamer网络视频服务器移植
MJPG简介: MJPG是MJPEG的缩写,但是MJPEG还可以表示文件格式扩展名. MJPEG 全名为 "Motion Joint Photographic Experts Group&q ...
随机推荐
- Image Processing and Computer Vision_Review:Recent Advances in Features Extraction and Description Algorithms: A Comprehensive Survey——2017.03
翻译 特征提取和描述算法的最新进展:全面的调查 摘要 - 计算机视觉是当今信息技术中最活跃的研究领域之一.让机器和机器人能够以视线的速度看到和理解周围的世界,创造出无穷无尽的潜在应用和机会.特征检测和 ...
- Django—admin系统:admin的使用及源码剖析
admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLE ...
- golang map多层嵌套使用及遍历方法汇总
原文:https://blog.csdn.net/boyhandsome7/article/details/79734847 ------------------------------------- ...
- R的数据结构--向量
向量:用于存储数值型.字符型或逻辑型数据的一维数组,只可以包含一种数据 向量的创建与运算 创建向量 # 创建简单向量 l <- c(2, 2, 1, 3, 8) # [1] 2 2 1 3 8 ...
- javascript代码模块化解决方案
我们用模块化的思想进行网页的编写是为了更好的管理我们的项目,模块与模块之间是独立存在的,每个模块可以独立的完成一个子功能. 一.服务器和桌面环境中的Javascript代码模块化:CommonJS M ...
- 洛谷P4983 忘情 (WQS二分+斜率优化)
题目链接 忘情水二分模板题,最优解对划分段数的导数满足单调性(原函数凸性)即可使用此方法. 详细题解洛谷里面就有,不啰嗦了. 二分的临界点让人有点头大... #include<bits/stdc ...
- 前端知识体系:JavaScript基础-原型和原型链-理解原型设计模式以及 JavaScript中的原型规则
理解原型设计模式以及 JavaScript中的原型规则(原文地址) 1.原型对象:我们创建的每一个函数(JavaScript中函数也是一个对象)都有一个原型属性 prototype,原型属性实质上是一 ...
- 基于STM32调试工具STM-STUDIO-STM32的使用
手上有stlink下载器,正好看到官网有这个工具,可以在运行中实时查看变量的数据.这一点和ucos的ucprobe很类似. 参考https://mp.weixin.qq.com/s?src=11&am ...
- Appium真机运行测试用例
- 排列组合C、A
排列组合是组合学最基本的概念.所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序.组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序. 排列组合定义及公式 排列的定义:从n个不同 ...