Video Stream

Overview

This tutorial will show you how to send a video stream as a series of MJPEG frames. The technique used here is:

  • Serve the page as non-cacheable, and indicate content type is multipart/x-mixed-replace
  • Periodically send the content of a different JPEG file that replaces the former

Build and run

  • Follow the Build Tools tutorial to setup your development environment.

  • Start a terminal in the project directory; if you've not already done so, clone the Mongoose Library repo

    git clone https://github.com/cesanta/mongoose
    
  • Build and run the example

    cd mongoose/examples/video-stream
    make clean all
    
  • Go to http://localhost:8000 in your browser, you'll see an animation

  • If you have VLC media player installed, you can also get the frames from curl and pipe them to VLC, seeing the animation on a window

    curl localhost:8000/api/video1 | cvlc -
    

How it works

We'll concentrate here on those aspects related to sending the video stream, for the details of initializing and setting up an HTTP server please check the HTTP server tutorial.

  • When we get an HTTP request for the /api/video1 URI, we mark that connection and serve a header instructing the browser to avoid caching that content, and indicating that our response content type will be multipart/x-mixed-replace, then we set a fancy boundary marker that will serve to separate the frames
  • Then, periodically, we traverse all marked connections and send the boundary marker and a new image

Note the timer event handler gets a pointer to the event manager as its argument, we need it to traverse all connections and we configure that in the initialization section:

int main(void) {
  struct mg_mgr mgr;

  mg_mgr_init(&mgr);
  mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, timer_callback, &mgr);

The more frequently you update images, the more realistic the animation will look; set the timer and event manager poll time accordingly. Take a look at the timers tutorial for more details on how to initialize and use a timer.

Browse latest code