Streaming Webcam To RTMP Using GStreamer

Streaming Webcam To RTMP Using GStreamer

ยท

4 min read

Introduction

Hello! ๐Ÿ˜Ž

In this tutorial I will show you how you can stream your webcam to an RTMP server using C++ and GStreamer.


Requirements

  • Basic knowledge of C++

  • Basic knowledge of GStreamer

  • A webcam


Creating The Source

First we need to actually write the code that will enable us to stream the webcam to a RTMP server. ๐Ÿ‘€

Open a file called "main.cpp" and add the following header:

#include<gst/gst.h>

Next write/copy the following main function:

int main(int argc, char *argv[])
{
  GstElement *pipeline, *source, *videoconvert, *videoscale, *capsfilter, *queue, *encoder, *muxer, *sink;
  GstCaps *caps;
  GstBus *bus;
  GstMessage *message;

  // Initialize GStreamer
  gst_init(&argc, &argv);

  // Set properties
  g_object_set(encoder, "bitrate", 5000, NULL);
  g_object_set(muxer, "streamable", TRUE, NULL);
  g_object_set(sink, "location", "rtmp://localhost/stream", NULL);

  caps = gst_caps_new_simple("video/x-raw",
      "width", G_TYPE_INT, 3840,
      "height", G_TYPE_INT, 2160,
      NULL);

  g_object_set(capsfilter, "caps", caps, NULL);
  gst_caps_unref(caps);

  pipeline = gst_pipeline_new("rtmpcam");

  gst_bin_add_many(GST_BIN(pipeline), source, videoconvert, videoscale, capsfilter, queue, encoder, muxer, sink, NULL);

  if (!gst_element_link_many(source, videoconvert, videoscale, capsfilter, queue, encoder, muxer, sink, NULL))
  {
    g_error("Failed to link elements");

    return -1; 
  }

  gst_element_set_state(pipeline, GST_STATE_PLAYING);

  bus = gst_element_get_bus(pipeline);
  message = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, static_cast<GstMessageType>(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

  if (message != NULL)
  {
    gst_message_unref(message);
  }

  gst_object_unref(bus);
  gst_element_set_state(pipeline, GST_STATE_NULL);
  gst_object_unref(pipeline);

  return 0;
}

Now I will explain what each section is doing. ๐Ÿ‘

First we create the variables and initialize GStreamer with the following:

GstElement *pipeline, *source, *videoconvert, *videoscale, *capsfilter, *queue, *encoder, *muxer, *sink;
GstCaps *caps;
GstBus *bus;
GstMessage *message;

// Initialize GStreamer
gst_init(&argc, &argv);

Then we set a couple of properties for the elements.

// Set properties
g_object_set(encoder, "bitrate", 5000, NULL);
g_object_set(muxer, "streamable", TRUE, NULL);
g_object_set(sink, "location", "rtmp://localhost/stream", NULL);

Here we set the encoding bitrate to 5000, make the muxer streamable and set the RTMP url to the location we want to stream to.

Next we set the caps for the video, here we are setting it to 4K resolution but if this is too much for your case feel free to adjust the numbers. ๐Ÿ˜ƒ

caps = gst_caps_new_simple("video/x-raw",
    "width", G_TYPE_INT, 3840,
    "height", G_TYPE_INT, 2160,
    NULL);

g_object_set(capsfilter, "caps", caps, NULL);
gst_caps_unref(caps);

Next we need to add and link the elements together, which is done via the following:

gst_bin_add_many(GST_BIN(pipeline), source, videoconvert, videoscale, capsfilter, queue, encoder, muxer, sink, NULL);

if (!gst_element_link_many(source, videoconvert, videoscale, capsfilter, queue, encoder, muxer, sink, NULL))
{
    g_error("Failed to link elements");

    return -1; 
}

Next we set the state of the pipeline to playing to actually start the stream.

gst_element_set_state(pipeline, GST_STATE_PLAYING);

Any errors or EOS signals are picked up with the following:

bus = gst_element_get_bus(pipeline);
message = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, static_cast<GstMessageType>(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

Finally we need to clean up any resources.

if (message != NULL)
{
    gst_message_unref(message);
}

gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);

return 0;

Done! ๐Ÿ˜† Finally we need to create a script so we can actually build the example.


Create The CMakeLists File

Next we will prepare a CMakeLists file to build the above source code. Create a "CmakeLists.txt" file and populate it with the following:

cmake_minimum_required(VERSION 3.10)
project(rtmpcam)

set(CMAKE_CXX_STANDARD 14) 

find_package(PkgConfig REQUIRED)
pkg_check_modules(GST REQUIRED gstreamer-1.0)

include_directories(${GST_INCLUDE_DIRS})

add_executable(rtmpcam main.cpp)
target_link_libraries(rtmpcam ${GST_LIBRARIES})

This links our project with the GStreamer library files.

To build the project run the following commands:

mkdir build
cd build
cmake ..
make

The above should build the source code and you should now see a "rtmpcam" executable.

Now before we can use the executable we need an RTMP server. I will be using MediaMTX (https://github.com/aler9/mediamtx) but feel free to use whatever RTMP server you wish.

If you are using mediamtx you can run it easily via the following docker command:

docker run --rm -it -e MTX_PROTOCOLS=tcp -p 8554:8554 -p 1935:1935 -p 8888:8888 -p 8889:8889 aler9/rtsp-simple-server

Running The Example

Now we can finally try out the executable ๐Ÿ™‚

This can be done via:

./rtmpcam

Now if you open up VLC and try and play the URL (rtmp://localhost:1935/stream), you should be able to see your webcam footage. ๐Ÿ˜

I'm actually thinking of experimenting with MediaMTX.


Conclusion

In this tutorial I have shown how you can use C++ and GStreamer to stream your webcam to a RTMP server.

I hope this helped you as much as I had fun writing it.

The repo can be found at: https://github.com/ethand91/gstreamer-rtmp-sample

Happy Coding! ๐Ÿ˜Ž


Like me work? I post about a variety of topics, if you would like to see more please like and follow me. Also I love coffee.

โ€œBuy Me A Coffeeโ€

If you are looking to learn Algorithm Patterns to ace the coding interview I recommend the following course

Did you find this article valuable?

Support Ethan by becoming a sponsor. Any amount is appreciated!

ย