Search code examples
c#httpvideostreamingpushstreamcontent

Web API streaming images from buffer


For some reason i cannot get the below piece of code to work. I am trying to stream images to a browser over HTTP.

    [Route("api/v1/camera/live/stream")]
    [HttpGet]
    public HttpResponseMessage GetStream()
    {
        logger.Trace($"GET api/v1/camera/live/stream called");

        var response = Request.CreateResponse();
        response.Content = new PushStreamContent(new Action<Stream, HttpContent, TransportContext>(
            async (stream, content, tansportContext) =>
            {
                try
                {
                    StreamWriter writer = new StreamWriter(stream);

                    while (HttpContext.Current.Response.IsClientConnected)
                    {

                        var image = databuffer.Get<CameraFrame>().LastOrDefault();
                        if (image != null)
                        {
                            MemoryStream ms = new MemoryStream();
                            ms.SetLength(0);
                            ms.WriteTo(BytesOf(databuffer.Get<CameraFrame>().Last().Image));

                            writer.WriteLine("--boundary");
                            writer.WriteLine("Content-Type: image/jpeg");
                            writer.WriteLine($"Content-length: {ms.Length}");
                            writer.WriteLine();
                            writer.Write(ms.GetBuffer());

                            writer.Flush();
                        }

                        await Task.Delay(33);
                    }
                }
                catch (Exception ex)
                {
                    logger.Error($"Streaming error", ex);
                    throw;
                }

                logger.Trace("streaming ended");

            }));
        response.Content.Headers.ContentType =
            MediaTypeHeaderValue.Parse("multipart/x-mixed-replace; boundary=--boundary");
        return response;
    }

    private MemoryStream BytesOf(Bitmap image)
    {
        MemoryStream ms = new MemoryStream();
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        return ms;
    }

The databuffer.Get() is constantly being filled by a camera with bitmap frames.

When i run the above code all compiles fine. But when i use chrome to navigate to the URL it does not show the images.


Solution

  • Ok i have solved it. Mainly i was not doing the stream correctly.

    [Route("api/v1/camera/live/stream")]
        [HttpGet]
        public HttpResponseMessage GetStream()
        {
            logger.Trace($"GET api/v1/camera/live/stream called");
    
            var response = Request.CreateResponse(HttpStatusCode.PartialContent);
            response.Content = new PushStreamContent(new Action<Stream, HttpContent, TransportContext>(async (stream, content, tansportContext) =>
            {
                EventHandler<AcquiredDataEventArgs<CameraFrame>> handler = (_, __) => { };
                try
                {
                    MjpegWriter writer = new MjpegWriter(stream);
                    handler = (s, e) => writer.Write(e.Data.Image.GetJpegStream());
    
                    camera.DataAcquired += handler;
                    while (HttpContext.Current.Response.IsClientConnected)
                    {
                        await Task.Delay(100);
                    }
                    camera.DataAcquired -= handler;
    
    
                }
                catch (Exception ex)
                {
                    logger.Error($"Streaming error", ex);
                    throw;
                }
                logger.Trace("streaming ended");
    
            }));
    
            response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/x-mixed-replace; boundary=--boundary");
    
            return response;
        }