Stream MJPEG containerized file over RTSP

Something I have had to do for work which took a while to figure out. Therefore this post is not only to remind me in the future but to help those poor souls who may have to do the same thing at some point.
I used gstreamer, but rather than gst-launch from the command line I used the gstrtspserver from within C code. This was tested within Visual Studio under Windows 7 x64.
The code is straightforward and stolen almost in its entirety from the gstrtspserver documentation examples.

Before getting to the code I will detail a few setup steps.

Download the following files, from here.

    gstreamer-1.0-x86_64-1.2.4.1.msi,
    gstreamer-1.0-devel-x86_64-1.2.4.1.msi,

Create an empty C++ project.

Set the following, by right-clicking on the project under the solution explorer,

    Project Property Pages->Configuration Properties->C/C++->;General->Additional Include Directories.

    $(GSTREAMER_1_0_ROOT_X86_64)libglib-2.0include
    $(GSTREAMER_1_0_ROOT_X86_64)includeglib-2.0
    $(GSTREAMER_1_0_ROOT_X86_64)includegstreamer-1.0
    $(GSTREAMER_1_0_ROOT_X86_64)include

Set the following, by right-clicking on the project under the solution explorer,

    Project Property Pages->Configuration Properties->Linker->General->Additional Library Directories.

    $(GSTREAMER_1_0_ROOT_X86_64)lib

Set the following, by right-clicking on the project under the solution explorer,

    Project Property Pages->Configuration Properties->Linker->Input->Additional Dependencies.

    glib-2.0.lib
    gobject-2.0.lib
    gstreamer-1.0.lib
    gstrtspserver-1.0.lib
    gstrtp-1.0.lib
    gstrtsp-1.0.lib

This should be the minimum development environment for Visual Studio to allow for testing. Anyway enough messing about here is the code.

#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>

gint 
main (gint argc, gchar *argv[])
{
    GMainLoop *loop;
    GstRTSPServer *server;
    GstRTSPMediaFactory *factory;
    GstRTSPMountPoints *mountpoint;

    gst_init (&argc, &argv);
    loop = g_main_loop_new (NULL, FALSE);
    server = gst_rtsp_server_new ();

    mountpoint = gst_rtsp_server_get_mount_points(server);
    factory = gst_rtsp_media_factory_new ();

    // if you wish to use the default gstreamer test video source.
    // gst_rtsp_media_factory_set_launch (factory,
    //     "( videotestsrc is-live=1 ! jpegenc ! rtpjpegpay name=pay0 pt=96 )");
    // the file TestMJPEG.avi is a custom made file and resides within 
    // the executable directory.
    gst_rtsp_media_factory_set_launch (factory,
        "( filesrc location=TestMJPEG.avi ! avidemux ! rtpjpegpay name=pay0 pt=96 )");

    gst_rtsp_media_factory_set_shared (factory, TRUE);
    gst_rtsp_mount_points_add_factory(mountpoint, "/test", factory);

    g_object_unref (mountpoint);
    if (gst_rtsp_server_attach (server, NULL) == 0)
        goto failed;

    g_print("stream ready at rtsp://127.0.0.1:8554/testn");
    g_main_loop_run (loop);

    return 0;

failed:
    {
        g_print("Failed to attach the server!n");
        return -1;
    }
}

To test the code, using VLC, do the following:

vlc rtsp://127.0.0.1:8554/test

If successful you should see a video file, or the default video source being streamed through vlc, use the codec info tool to check it is MJPEG.

The above code, if using a video file, will stream the file from start to finish. Ideally I want to have any video file looping forever, so this is on my To Do List.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s