创建我自己的MJPEG流 [英] creating my own MJPEG stream

查看:169
本文介绍了创建我自己的MJPEG流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个MJPEG流,我有一系列jpeg,我想将它们组合成一个流,以便用户只需点击一个URL并获得一个mjpeg流。
过去几天我一直在努力让这个工作起来,而这可能是不可能的。我带来了空灵,并在网络上听到来自网络上的轴摄像头的数据包,并试图模仿它。我最初尝试使用WCF,并返回一个流但后来发现我需要在该流上设置内容类型,因此我尝试了WCF REST api,但是这也遇到了同样的问题。所以我现在只是使用一个简单的HTTPListener,并处理该事件。我更喜欢使用WCF,但我不确定它是否允许我返回具有正确内容类型的流。
所以这就是我对httpListener所拥有的。

I'm trying to create an MJPEG stream, I have a series of jpegs that I want to put together into a stream so that a user can just hit a URL and get an mjpeg stream. I've been trying for the last few days to get this to work, and it may just not be possible. I've brought up ethereal and listened to the packets coming from an axis camera on the net somewhere, and tried to mimmick it. I originally tried using WCF, and returning a "stream" but then later found out that I would need to set the content type on that stream, so I then tried the WCF REST api, but that suffers from the same problem. so I am now just using a bare bones HTTPListener, and handling the event. I would greatly prefer to use WCF, but I'm not sure that it will allow me to return a stream with the right content type. so here's what I have for the httpListener .

在监听器回调的处理程序中我把以下内容。

in the handler of the listener call back I put the following.

        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方法如下所示

the Render method looks like this

        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);
            }
        }

此时我刚添加了几个jpeg作为dll上的属性的图像,我正在迭代它们,最终这些将是动态图像,但是现在我只想让这个东西起作用。

At this point I've just added a few jpeg images as properties on the dll, and am iterating over them, eventually these will be dynamic images, but for now I just want to get the thing to work.

从什么我理解MJPEG(规范)是必须将内容设置为multipart / x-mixed-replace和边界集。然后你只是通过边界消除流中的jpegs。

From what I understand about the MJPEG (spec) is that the content must be set to multipart/x-mixed-replace and a boundary set. and then you just deliminate the jpegs within the stream by the boundary.

这似乎应该更简单然后我正在制作它,但我想知道我在哪里我出错了。如果我在IE或Firefox中加载此URL,它就会挂起。如果我尝试使用img标签创建一个存根html页面,其源代码是URL,那么我会得到一个损坏的图像。

This seems like it should be simpler then I'm making it, but I'm wondering where I'm going wrong. if I load this URL up in IE or Firefox, it just hangs. if I try to make a stub html page with an img tag, whose source is the URL then I get a broken image.

任何想法,谢谢

Josh

推荐答案

嗯,据我所知,这是你的问题:

Well, as far as I can tell, here are your issues:


  1. StreamWriter 不是正确的选择。使用常规流写入功能很好。意思是,你应该用Byte数组而不是字符串来写数据。

  1. The StreamWriter is not a correct choice. Use a regular stream write function is fine. Meaning, you should write data in Byte array instead of string.

你将图像的二进制数据转换为String64,浏览器不知道,仍然认为它是32位数据。

You convert the Binary data of the image to String64, the browser does not known that, still thinking it is 32bit data.

您的jpeg帧格式不正确。您还应该将 Content-Length 添加到帧头,以便接收流的应用程序知道何时停止读取,而不必每次读取时检查下一个边界字符串。这将使读取数据的速度提高约4-5倍。你的新行字符也有不一致之处,有些是\\ n,而有些则是\ n。

Your jpeg frame format is not correct. You should also add Content-Length to the frame header so that the application that receive the stream know when to stop reading rather than having to check for the next boundary string every read. This will result in about 4-5 times faster in reading data. And there are also inconsistency in your new line character, some are "\r\n" while some others are "\n".

虽然循环是一个无限循环。

While loop is a infinite loop.

所以,这是解决方案。

So, here is the solution.

注意:可能存在一些语法错误,但您可能会有一般性的想法。

Note: There might be some syntax errors but you probably get the general idea.

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);
    }
}

这篇关于创建我自己的MJPEG流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆