我正在尝试创建一个MJPEG流,我有一系列jpeg,我想将它们组合成一个流,以便用户只需点击一个URL并获得一个mjpeg流。 过去几天我一直在努力让它发挥作用,而且可能是不可能的。我提起了空灵,并听取了网上某个轴摄像头的数据包,并试图模仿它。我最初尝试使用WCF,并返回“流”但后来发现我需要在该流上设置内容类型,因此我尝试了WCF REST api,但是这也遇到了同样的问题。所以我现在只是使用一个简单的HTTPListener,并处理事件。我更喜欢使用WCF,但我不确定它是否允许我返回具有正确内容类型的流。 所以这就是我对httpListener的所作所为。
在监听器回调的处理程序中,我将以下内容。
HttpListenerResponse response = context.Response;
response.ProtocolVersion = new System.Version(1, 0);
response.StatusCode = 200;
response.StatusDescription = "OK";
response.ContentType = "multipart/x-mixed-replace;boundary=" + BOUNDARY + "\r\n";
System.IO.Stream output = response.OutputStream;
Render(output);
Render方法看起来像这样
var writer = new StreamWriter(st);
writer.Write("--" + BOUNDARY + "\r\n");
while (true)
{
for (int i = 0; i < imageset.Length; i++)
{
var resource = Properties.Resources.ResourceManager.GetObject(imageset[i]) as Bitmap;
var memStream = new MemoryStream();
resource.Save(memStream,ImageFormat.Jpeg);
byte[] imgBinaryData = memStream.ToArray();
string s = Convert.ToBase64String(imgBinaryData);
writer.Write("Content-type: image/jpeg\r\n");
foreach (var s1 in imgBinaryData)
{
writer.Write((char)s1);
}
writer.Write("\n--" + BOUNDARY + "\n");
writer.Flush();
Thread.Sleep(500);
}
}
此时我刚刚在dll上添加了一些jpeg图像作为属性,并且正在迭代它们,最终这些将是动态图像,但是现在我只想让它工作。
根据我对MJPEG(规范)的理解,内容必须设置为multipart / x-mixed-replace和边界集。然后你只是通过边界消除流中的jpegs。
这似乎应该更简单然后我正在制作它,但我想知道我哪里出错了。如果我在IE或Firefox中加载此URL,它就会挂起。如果我尝试使用img标签创建一个存根html页面,其源代码是URL,那么我会得到一个损坏的图像。
任何想法,谢谢
约什
答案 0 :(得分:7)
嗯,据我所知,这是你的问题:
StreamWriter
不是正确的选择。使用常规流写入功能很好。这意味着,您应该用Byte数组而不是字符串来写数据。
您将图像的二进制数据转换为String64,浏览器不知道,仍然认为它是32位数据。
您的jpeg帧格式不正确。您还应该将Content-Length
添加到帧头,以便接收流的应用程序知道何时停止读取,而不必每次读取时检查下一个边界字符串。这将使读取数据的速度提高约4-5倍。你的新行字符也有不一致之处,有些是“\ r \ n”而有些则是“\ n”。
while循环是一个无限循环。
所以,这是解决方案。
注意:可能存在一些语法错误,但您可能会得到一般的想法。
private byte[] CreateHeader(int length)
{
string header =
"--" + BOUDARY + "\r\n" +
"Content-Type:image/jpeg\r\n" +
"Content-Length:" + length + "\r\n" +
+ "\r\n"; // there are always 2 new line character before the actual data
// using ascii encoder is fine since there is no international character used in this string.
return ASCIIEncoding.ASCII.GetBytes(header);
}
public byte[] CreateFooter()
{
return ASCIIEncoding.ASCII.GetBytes("\r\n");
}
private void WriteFrame(Stream st, Bitmap image)
{
// prepare image data
byte[] imageData = null;
// this is to make sure memory stream is disposed after using
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Jpeg);
imageData = ms.ToArray();
}
// prepare header
byte[] header = CreateHeader(imageData.Length);
// prepare footer
byte[] footer = CreateFooter();
// Start writing data
st.Write(header, 0, header.Length);
st.Write(imageData, 0, imageData.Length);
st.Write(footer, 0, footer.Length);
}
private void Render(Stream st)
{
for (int i = 0; i < imageset.Length; i++)
{
var resource = Properties.Resources.ResourceManager.GetObject(imageset[i]) as Bitmap;
WriteFrame(st, resource);
Thread.Sleep(500);
}
}
答案 1 :(得分:0)
还有一个实现@ https://net7mma.codeplex.com/SourceControl/latest库可以将Http转码为兼容的Rtp!