C Application Example

From RidgeRun Developer Wiki


Previous: Examples/Using Gstd Index Next: Contact Us






The following example shows how to insert binary metadata and extract it with a GStreamer signal through a C application.

Application Walk-through

This a quick walk-trough to help understand the process to create the pipeline, inject binary metadata and extract the signal.

First is to create the binary array to inject to the AV1 video stream. The example below shows a "Hello World!!" message, note that this could be any array of bytes.

static guint8 binary_metadata[] = {
    /*This is "Hello World!!" in hexadecimal*/
    0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21,
};

Next is to create the callback for handle the metadata receive by the signal. In this example we will only print the received metadata.

static void new_metadata_callback(GstElement * object, guint size, gpointer metadata_ptr, gpointer user_data) {
    g_print("Received new-metadata signal\n");
    g_print("Metadata: %s\n", metadata_ptr);
    // Handle metadata here
}

In the main function, the pipeline is created. With the obuinject element we can inject the metadata to the video stream. The obuextract signal-new-metadata property will allow the signal to be emitted.

int main(int argc, char *argv[]) {
    GstElement *pipeline, *src, *obuinject, *obuextract, *sink;
    GstBus *bus;
    GMainLoop *loop;
    GByteArray *barray = NULL;

    gst_init(&argc, &argv);

    loop = g_main_loop_new(NULL, FALSE);

    // Create the GStreamer pipeline
    pipeline = gst_parse_launch("videotestsrc is-live=true num-buffers=10 ! av1enc cpu-used=8 ! obuinject name=inject ! obuextract signal-new-metadata=true name=extract ! av1dec ! xvimagesink sync=false async=true", NULL);
    g_assert(pipeline != NULL);

With the pipeline created obtain the obuinject element and set the binary metadata with its respective size.

    // Get the source pad of the obuinject element
    obuinject = gst_bin_get_by_name(GST_BIN(pipeline), "inject");
    g_assert(obuinject != NULL);

    // Set binary metadata
    barray = g_byte_array_new_take(binary_metadata, sizeof(binary_metadata));
    g_object_set(obuinject, "metadata-binary", barray, NULL);
    g_boxed_free(G_TYPE_BYTE_ARRAY, barray);

With the pipeline created obtain the obuextract element and connect with the new-metadata signal.

    // Get the source pad of the obuextract element
    obuextract = gst_bin_get_by_name(GST_BIN(pipeline), "extract");
    g_assert(obuextract != NULL);

    // Connect to the new-metadata signal using g_signal_connect
    g_signal_connect(G_OBJECT(obuextract), "new-metadata", G_CALLBACK(new_metadata_callback), NULL);

Finally set the pipeline state to play.

    // Start the pipeline
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    // Run the GMainLoop
    g_main_loop_run(loop);

Building and running the application

In order to build the appication, copy the example into a file called main.c and build using the following command:

gcc -Wall main.c -o main `pkg-config --cflags --libs gstreamer-1.0`

After this you will end up with a binary called main.

Execute the application with the following command:

./main

The expected output should look like:

Received new-metadata signal
Metadata: Hello World!!

Example code

The complete application should look like:

#include <gst/gst.h>
#include <glib.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static guint8 binary_metadata[] = {
    /*This is "Hello World!!" in hexadecimal*/
    0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21,
};

static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer user_data) {
    GMainLoop *loop = (GMainLoop *)user_data;

    switch (GST_MESSAGE_TYPE(message)) {
        case GST_MESSAGE_ERROR: {
            GError *err;
            gchar *debug_info;

            gst_message_parse_error(message, &err, &debug_info);
            g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message);
            g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
            g_clear_error(&err);
            g_free(debug_info);

            g_main_loop_quit(loop);
            break;
        }
        case GST_MESSAGE_EOS:
            g_print("End of stream\n");
            g_main_loop_quit(loop);
            break;
        default:
            break;
    }

    return TRUE;
}

static void new_metadata_callback(GstElement * object, guint size, gpointer metadata_ptr, gpointer user_data) {
    g_print("Received new-metadata signal\n");
    g_print("Metadata: %s\n", metadata_ptr);
    // Handle metadata here
}

int main(int argc, char *argv[]) {
    GstElement *pipeline, *src, *obuinject, *obuextract, *sink;
    GstBus *bus;
    GMainLoop *loop;
    GByteArray *barray = NULL;

    gst_init(&argc, &argv);

    loop = g_main_loop_new(NULL, FALSE);

    // Create the GStreamer pipeline
    pipeline = gst_parse_launch("videotestsrc is-live=true num-buffers=10 ! av1enc cpu-used=8 ! obuinject metadata=\"Hello World?\" name=inject ! obuextract signal-new-metadata=true name=extract ! av1dec ! xvimagesink sync=false async=true", NULL);
    g_assert(pipeline != NULL);

    // Get the bus to handle messages
    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    gst_bus_add_watch(bus, bus_callback, loop);
    gst_object_unref(bus);

    // Get the source pad of the obuinject element
    obuinject = gst_bin_get_by_name(GST_BIN(pipeline), "inject");
    g_assert(obuinject != NULL);

    // Set binary metadata
    barray = g_byte_array_new_take(binary_metadata, sizeof(binary_metadata));
    g_object_set(obuinject, "metadata-binary", barray, NULL);
    g_boxed_free(G_TYPE_BYTE_ARRAY, barray);

    // Get the source pad of the obuextract element
    obuextract = gst_bin_get_by_name(GST_BIN(pipeline), "extract");
    g_assert(obuextract != NULL);

    // Connect to the new-metadata signal using g_signal_connect
    g_signal_connect(G_OBJECT(obuextract), "new-metadata", G_CALLBACK(new_metadata_callback), NULL);

    gst_object_unref(obuextract);

    // Start the pipeline
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    // Run the GMainLoop
    g_main_loop_run(loop);

    // Cleanup
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
    g_main_loop_unref(loop);

    return 0;
}



Previous: Examples/Using Gstd Index Next: Contact Us