C Application Example
GstObuMetadata |
---|
GstObuMetadata Basics |
Getting Started |
User Guide |
Examples |
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; }