views:

1399

answers:

3

Hello Guys, I 've a stream of Jpegs images and I'm trying to stream them with HTTP to VLC

The code if the following:

 public HttpListenerResponse StartListening(String where)
    {
        listener = new HttpListener();
        listener.Start();
        Console.WriteLine("listening on " + where);
        listener.Prefixes.Add(where);
        HttpListenerContext context = listener.GetContext();
        HttpListenerRequest request = context.Request;
        // Obtain a response object.
        HttpListenerResponse response = context.Response;
        return response;
    }
public void StartStream()
    {
        HttpListenerResponse response = StartListening("http://localhost:8080/");
        MemoryStream mem = null;

        for (;;)
        {
            Bitmap b = generateBitmap();
            //pictureBox1.Image = frm.GetFormImage();
            byte[] ar = BitmapToArray(b);


            // Construct a response.
            byte[] buffer = ar;
            response.ContentType = "multipart/x-mixed-replace; boundary=--testboundary";
            ASCIIEncoding ae = new ASCIIEncoding();
            byte[] boundary = ae.GetBytes("\r\n--testboundary\r\nContent-Type: image/jpeg\r\nContent-Length:" + buffer.Length + "\r\n\r\n");
            mem = new MemoryStream(boundary);
            mem.WriteTo(response.OutputStream);
            mem = new MemoryStream(buffer);
            mem.WriteTo(response.OutputStream);
        }   
        mem.Close();
        listener.Stop();    

    }

For some reason, If i try to open the stream in firefox it comes back all black, If i try to open it with VLC i get "Unable to open stream"

If i only stream 1 image, firefox has no problem dealing with it.

Tks in advance, Jose

A: 

Still not solved

could you provide some details about how you solved your problem?
Nathan Koop
what was the fix?
Erich Mirabal
Actually I still need some help, it's working without a problem in firefox, I just can't open it in VLC....The problem before was with the images and not with the streaming although I still can't open them in VLCAny ideas ?
A: 

Set your prefixes, then call Start().

From what I've seen in the code and elsewhere, you can't stream data using HttpListener. You might have to forward the request to another local TCP socket that writes the data back.

Erich Mirabal
That doesn't work either
+2  A: 

You may give a multi-part range request a try. VLC may be requesting the data in 'chunks' but your HTTPHandler isn't providing that functionality. Here's some (lengthy) example code below. I had a similar problem when trying to stream music to my iPod Touch. Worked like a charm in brower, but didn't work with the Touch. Turns out, the iPod was requesting byte[] chunks via multiple requests to my handler, but the handler didn't implement the functionality it needed.

I got some of my own library classes mingled in here, but you'll get the picture well enough.

public abstract class MultipartRangeHandler : IHttpHandler
{
    protected const String HEADER_RANGE = "range";
    protected const String HEADER_CONTENT_TYPE = "Content-Type";
    protected const String HEADER_CONTENT_LENGTH = "Content-Length: ";
    protected const String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
    protected const String HEADER_CONTENT_RANGE = "Content-Range";
    protected const String HEADER_BOUNDARY_DELIMETER = "--";
    protected const String HEADER_STATUS_PARTIAL_CONTENT = "Partial Content";

    private const char COMMA = ',';
    private const char EQUALS = '=';
    private const char NEW_LINE = '\n';

    protected const String QS_OBJECT_ID = "cid";

    public void ProcessRequest(HttpContext context)
    {
        if (StringUtils.isNullOrEmpty(context.Request.QueryString[QS_OBJECT_ID]))
        {
            sendResponse(400, "400 Bad Request", "No resource was specified in the query string to retrieve.", context);
        }
        else
        {
            ContentItem contentItem = getContentItem(context.Request.QueryString[QS_OBJECT_ID]);

            if (contentItem != null)
            {
                context.Response.Clear();
                context.Response.ClearHeaders();
                context.Response.ClearContent();

                if (context.Request.Headers[HEADER_RANGE] != null)
                {

                    string range = context.Request.Headers[HEADER_RANGE];
                    range = range.Substring(range.LastIndexOf(EQUALS) + 1);
                    bool isMultipartRange = range.Contains(COMMA.ToString());

                    if (!isMultipartRange)
                    {
                        addHeader(context.Response, HEADER_CONTENT_TYPE, contentItem.MimeType);
                        addHeader(context.Response, HEADER_CONTENT_DISPOSITION, "inline; filename=\"" + contentItem.Filename + "\"");

                        string[] startEnd = range.Split('-');

                        long startPos;

                        long.TryParse(startEnd[0], out startPos);

                        long endPos;
                        int fileSize = contentItem.FileBytes.Length;

                        if (startEnd.GetUpperBound(0) >= 1 && startEnd[1] != String.Empty)
                        {
                            long.TryParse(startEnd[1], out endPos);
                        }
                        else
                        {
                            endPos = fileSize - startPos;
                        }

                        if (endPos > fileSize)
                        {
                            endPos = fileSize - startPos;
                        }

                        context.Response.StatusCode = 206;
                        context.Response.StatusDescription = HEADER_STATUS_PARTIAL_CONTENT;
                        addHeader(context.Response, HEADER_CONTENT_RANGE, "bytes " + startPos + "-" + endPos + "/" + fileSize);

                        context.Response.BinaryWrite(ByteUtils.subByte(contentItem.FileBytes, (int)startPos, (int)(endPos - startPos) + 1));
                    }
                    else
                    {

                        string boundary = "waynehartmanansmach";
                        addHeader(context.Response, HEADER_CONTENT_TYPE, "multipart/byteranges; boundary=" + boundary);

                        List<string[]> ranges = new List<string[]>();
                        string[] multiRange = range.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (string mr in multiRange)
                        {
                            ranges.Add(mr.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries));
                        }

                        //  process the list of ranges
                        foreach (string[] rangeArray in ranges.ToArray())
                        {
                            context.Response.Write(HEADER_BOUNDARY_DELIMETER + boundary + NEW_LINE);
                            context.Response.Write(HEADER_CONTENT_TYPE + ": " + contentItem.MimeType + NEW_LINE);
                            context.Response.Write(HEADER_CONTENT_RANGE + ": bytes " + rangeArray[0] + "-" + rangeArray[1] + "/" + contentItem.FileBytes + NEW_LINE + NEW_LINE);
                            long startPos = long.Parse(rangeArray[0]);
                            long endPos = long.Parse(rangeArray[1]);

                            context.Response.BinaryWrite(ByteUtils.subByte(contentItem.FileBytes, (int)startPos, (int)(endPos - startPos) + 1));

                            context.Response.Write(NEW_LINE);
                            context.Response.Flush();
                        }

                        context.Response.Write(HEADER_BOUNDARY_DELIMETER + boundary + HEADER_BOUNDARY_DELIMETER + NEW_LINE + NEW_LINE);
                    }
                }
                else
                {
                    context.Response.ContentType = contentItem.MimeType;
                    addHeader(context.Response, HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + contentItem.Filename + "\"");
                    addHeader(context.Response, HEADER_CONTENT_LENGTH, contentItem.FileBytes.Length.ToString());

                    context.Response.OutputStream.Write(contentItem.FileBytes, 0, contentItem.FileBytes.Length);
                }
            }
            else
            {
                sendResponse(404, "404 Not Found", "The resource requested does not exist.", context);                    
            }
        }
    }

    private void sendResponse(int statusCode, String status, String statusMessage, HttpContext context)
    {
        System.Text.StringBuilder data = new System.Text.StringBuilder();

        data.AppendLine("<html><body>");
        data.AppendLine("<h1>"+status+"</h1>");
        data.AppendLine("<p>"+statusMessage+"</p>");
        data.AppendLine("</body></html>");

        byte[] headerData = System.Text.Encoding.ASCII.GetBytes(data.ToString());

        context.Response.ContentType = "text/html";
        context.Response.StatusCode = statusCode;
        context.Response.Status = status;

        addHeader(context.Response, HEADER_CONTENT_LENGTH, headerData.Length.ToString());

        //context.Response.AddHeader("Content-Length: ", headerData.Length.ToString());
        context.Response.OutputStream.Write(headerData, 0, headerData.Length);
        context.Response.End();
    }

    protected void addHeader(HttpResponse response, String key, String value)
    {
        response.AddHeader(key, value);
    }

    protected abstract com.waynehartman.util.web.handlers.multipartrange.ContentItem getContentItem(String objectID);

    public bool IsReusable
    {
        get { return true; }
    }
}
Wayne Hartman