DEV Community

Cover image for Streaming Webcam To RTMP Using GStreamer
Ethan
Ethan

Posted on • Originally published at ethan-dev.com

Streaming Webcam To RTMP Using GStreamer

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>
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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; 
}
Enter fullscreen mode Exit fullscreen mode

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

gst_element_set_state(pipeline, GST_STATE_PLAYING);
Enter fullscreen mode Exit fullscreen mode

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));
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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})
Enter fullscreen mode Exit fullscreen mode

This links our project with the GStreamer library files.

To build the project run the following commands:

mkdir build
cd build
cmake ..
make
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Running The Example

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

This can be done via:

./rtmpcam
Enter fullscreen mode Exit fullscreen mode

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

Top comments (1)

Collapse
 
mozzis profile image
Morris Maynard

The parameter list for the call to gst_bin_add_many has several uninitialized pointers. Is this not a problem?