HttpWebResponse with MJPEG and multipart/x-mixed-replace; boundary=--myboundary response content type from security camera not working
Asked Answered
P

3

12

I have an ASP.NET application that I need to show a video feed from a security camera. The video feed has a content type of 'multipart/x-mixed-replace; boundary=--myboundary' with the image data between the boundaries. I need assistance with passing that stream of data through to my page so that the client side plugin I have can consume the stream just as it would if I browsed to the camera's web interface directly. The following code does not work:

//Get response data
byte[] data = HtmlParser.GetByteArrayFromStream(response.GetResponseStream());
if (data != null)
{
 HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
}
return;
Panegyric answered 13/1, 2010 at 22:59 Comment(0)
R
20

Well, if you want your client to see the mjpeg stream, you need to send the whole http response. HTTP client like browser or media player like VLC need a mjpeg stream that looks like :

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=myboundary

--myboundary
Content-Type: image/jpeg
Content-length: 12345

[image 1 encoded jpeg data]


--myboundary
Content-Type: image/jpeg
Content-length: 45678

[image 2 encoded jpeg data]

...

NOTE: As Ergousha said in an answer, you must have an empty line after the Content-length field.

By the way, why not redirect your client directly to the mjpeg stream ?

You can use http://ipcam/mjpg/video.mjpg AXIS IP cameras for example.

If you just need the image through HTTP, you have to set the correct header and the MIME content-type image/jpeg. To decode the image, you have to get the byte data and you will get jpeg encoding. Then you will have to decode jpeg to get an image in a specific format (something like yuv420p I think). I've check on my ip camera, and its stream is not base64 encoded I think.

Precise your needs, I will try to help more.

my2c

EDIT:

Well, I suppose you do something like :

client    : connect to proxy, 
            get example.com/camera1.mjpg,
            while not the end
                recv


yourproxy : wait connection
            connect to camera,
            get 10.0.0.123/camera1.mjpg
            while not the end
                recv buffer
                copy buffer
                send buffer to client

That to say that you must send the correct header to your client. To be sure use a tool like wireshark to spy on the packet and be sure that after your client has issued a HTTP GET you send to him the correct MJPEG stream (like the one I describe at the beginning of my post ...)

m2c

Recurve answered 9/2, 2010 at 14:28 Comment(4)
that is exactly what I want to do. I cannot redirect the user directly to the mjpeg stream as my application is functioning as a reverse proxy. So I need to receive the stream from the camera then send it out as a response to a URL in my application. So the HTTP client calls example.com/camera1.mjpg my server parses the request and calls camera1 at 10.1.1.240/mjpg/video.mjpg I then need to stream the response back to the client. So this is where I've been having difficulty figuring out how to stream the mjpg back to the client unmodified.Panegyric
Be more precise about your difficulties. Looking at your code snippet, it seems that you read only part of the response. With HTTP/MJPEG you have to continuously read TCP packets and resend them, hence the pseudo code in my answer. I suppose the GetByteArrayFromStream call partially read the data, so you send back to your client only partial data. You have to read on the TCP channel until it closes ! Check what you receive / what you send with wireshark, you will have ground truth. If I misunderstand your problem, precise it, please ...Recurve
Yes, I am pretty sure we will need to go a little deeper and use something less abstracted such as TcpClient. I am currently trying to do the same thing as @arri.me!Seth
It should be boundary=myboundary instead of boundary=--myboundary! The dashes should only be included in the message body, not in the header of a multipart message, see RFC 1341. When decoding such a stream one should be prepared for both (as I just learned the hard way).Johnette
B
7

Good explaination about how mjpeg stream looks like. I would like to add a tip that; there are always 2 new line character before the actual data. If you make it one line, it doesnt work.

        string header =
            "--myboundary\r\n" +
            "Content-Type:image/jpeg\r\n" +
            "Content-Length:" + length.ToString() + "\r\n\r\n";
Buehler answered 14/5, 2010 at 7:50 Comment(2)
How do you know this? I spent hours searching until I finally found the code snippet and it contained exactly the text you wrote. How did you know this? Can you introduce a resource for teaching these things?Grous
I was just experimenting.. Trial and error; looking and analysing the working streams.Buehler
S
1

What is the encoding of the image data? Is it Base64?

Basically you will have to parse out the image data from the response, Base64 decode it into bytes, and then send the image to the client.

Subscribe answered 14/1, 2010 at 21:31 Comment(1)
No, as the stream has to be forwarded as mjpeg to the client. no need to decode / encode :)Recurve

© 2022 - 2024 — McMap. All rights reserved.