GstSEIMetadata/Examples/C Example: Difference between revisions
mNo edit summary |
|||
(9 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
<noinclude> | <noinclude> | ||
{{ | {{GstSEIMetadata/Head|previous=Examples/Using Gstd|next=Examples/Latency Measurement Example|metakeywords=}} | ||
</noinclude> | </noinclude> | ||
==Inserting metadata as binary using a C application== | |||
The following is an example that shows how to insert metadata as binary through a C application. | The following is an example that shows how to insert metadata as binary through a C application. | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
Line 26: | Line 27: | ||
#define FILE_LOCATION "./seiinject_metadata_binary_videotestsrc_avc.h264" | #define FILE_LOCATION "./seiinject_metadata_binary_videotestsrc_avc.h264" | ||
static guint8 binary_metadata[] = { | |||
/*This is "Hello World!!" in hexadecimal*/ | |||
static guint8 | |||
/* | |||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, | 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, | ||
}; | }; | ||
Line 153: | Line 146: | ||
/*Prepare metadata*/ | /*Prepare metadata*/ | ||
metalen = sizeof( | metalen = sizeof(binary_metadata); | ||
barray = g_byte_array_new_take( | barray = g_byte_array_new_take(binary_metadata, metalen); | ||
g_object_set(seiinject, "metadata-binary", barray, NULL); | g_object_set(seiinject, "metadata-binary", barray, NULL); | ||
g_boxed_free(G_TYPE_BYTE_ARRAY, barray); | g_boxed_free(G_TYPE_BYTE_ARRAY, barray); | ||
Line 217: | Line 210: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Application Walk-through == | === Application Walk-through === | ||
This is a quick walk-trough to better understand the process of creating the pipeline and injecting the metadata in the previous example. | This is a quick walk-trough to better understand the process of creating the pipeline and injecting the metadata in the previous example. | ||
=== Pipeline description === | ==== Pipeline description ==== | ||
<syntaxhighlight lang="C" highlight="3"> | <syntaxhighlight lang="C" highlight="3"> | ||
Line 231: | Line 224: | ||
As seen above, all we need to inject the metadata is the '''seiinject''' element, which will take the provided metadata, inject it into the encoded stream and then store it in the file seiinject_metadata_binary_videotestsrc_avc.h264 | As seen above, all we need to inject the metadata is the '''seiinject''' element, which will take the provided metadata, inject it into the encoded stream and then store it in the file seiinject_metadata_binary_videotestsrc_avc.h264 | ||
=== Metadata packet === | ==== Metadata packet ==== | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
static guint8 binary_metadata[] = { | |||
/*This is "Hello World!!" in hexadecimal*/ | |||
static guint8 | |||
/* | |||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, | 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, | ||
}; | }; | ||
Line 250: | Line 236: | ||
Note that this could have been any array of bytes, the above one is just an example. | Note that this could have been any array of bytes, the above one is just an example. | ||
=== Metadata injection === | ==== Metadata injection ==== | ||
<syntaxhighlight lang="C" line highlight="16"> | <syntaxhighlight lang="C" line highlight="16"> | ||
Line 266: | Line 252: | ||
/*Prepare metadata*/ | /*Prepare metadata*/ | ||
metalen = sizeof( | metalen = sizeof(binary_metadata); | ||
barray = g_byte_array_new_take( | barray = g_byte_array_new_take(binary_metadata, metalen); | ||
g_object_set(seiinject, "metadata-binary", barray, NULL); | g_object_set(seiinject, "metadata-binary", barray, NULL); | ||
g_boxed_free(G_TYPE_BYTE_ARRAY, barray); | g_boxed_free(G_TYPE_BYTE_ARRAY, barray); | ||
Line 276: | Line 262: | ||
* '''metadata binary:''' In line 16, the metadata binary is injected using the '''metadata-binary''' property. | * '''metadata binary:''' In line 16, the metadata binary is injected using the '''metadata-binary''' property. | ||
== Building the application == | === Building the application === | ||
In order to build the appication, copy the example into a file called '''main.c''' and build using the following command: | In order to build the appication, copy the example into a file called '''main.c''' and build using the following command: | ||
Line 286: | Line 272: | ||
After this you will end up with a binary called main. | After this you will end up with a binary called main. | ||
== Running the application == | === Running the application === | ||
Execute the application with the following command: | Execute the application with the following command: | ||
<pre> | <pre> | ||
./main | GST_DEBUG="2,*obu*:MEMDUMP" ./main | ||
</pre> | </pre> | ||
Line 298: | Line 284: | ||
To check the data was inserted correctly you can run: | To check the data was inserted correctly you can run: | ||
<pre> | <pre> | ||
GST_DEBUG=*seiextract*: | GST_DEBUG=*seiextract*:MEMDUMP gst-launch-1.0 filesrc location=seiinject_metadata_binary_videotestsrc_avc.h264 ! video/x-h264,stream-format=avc ! seiextract ! fakesink | ||
</pre> | </pre> | ||
And you will see something like this: | And you will see something like this: | ||
Line 315: | Line 301: | ||
<noinclude> | <noinclude> | ||
{{ | {{GstSEIMetadata/Foot|Examples/Using Gstd|Examples/Latency Measurement Example}} | ||
</noinclude> | </noinclude> |
Latest revision as of 19:29, 13 February 2024
GstSEIMetadata |
---|
GstSEIMetadata Basics |
Getting Started |
User Guide |
Examples |
Performance |
Contact Us |
Inserting metadata as binary using a C application
The following is an example that shows how to insert metadata as binary through a C application.
/** * Copyright (C) 2021 RidgeRun, LLC (http://www.ridgerun.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2 as * published by the Free Software Foundation. */ #include <glib.h> #include <glib-unix.h> #include <gst/gst.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define PIPELINE_DESCRIPTION \ "videotestsrc num-buffers=10 ! video/x-raw,width=16,height=240 ! x264enc ! video/x-h264,stream-format=avc ! " \ "seiinject name=inject ! filesink name=sink location=seiinject_metadata_binary_videotestsrc_avc.h264" #define FILE_LOCATION "./seiinject_metadata_binary_videotestsrc_avc.h264" static guint8 binary_metadata[] = { /*This is "Hello World!!" in hexadecimal*/ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, }; typedef struct _GstMetaDemo GstMetaDemo; struct _GstMetaDemo { GstElement *pipeline; GstElement *seiinject; GstElement *filesink; GMainLoop *main_loop; }; static gboolean create_pipeline(GstMetaDemo *metademo); static void start_pipeline(GstMetaDemo *metademo); static void stop_pipeline(GstMetaDemo *metademo); static void release_resources(GstMetaDemo *metademo); static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data); int main(int argc, char *argv[]) { GstMetaDemo *metademo = g_malloc(sizeof(GstMetaDemo)); if(!metademo){ g_print("Could not create demo\n"); return 1; } /* Initialization */ gst_init(&argc, &argv); if (!create_pipeline(metademo)) { g_free(metademo); return 1; } /* Set the pipeline to "playing" state*/ g_print("Playing pipeline\n"); start_pipeline(metademo); /* Iterate */ g_print("Running...\n"); g_main_loop_run(metademo->main_loop); /* Out of the main loop, clean up nicely */ g_print("Returned, stopping playback\n"); release_resources(metademo); return 0; } static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *)data; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: g_print("End of stream\n"); g_main_loop_quit(loop); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error(msg, &error, &debug); g_free(debug); g_printerr("Error: %s\n", error->message); g_error_free(error); g_main_loop_quit(loop); break; } default: break; } return TRUE; } static gboolean create_pipeline(GstMetaDemo *metademo) { GMainLoop *loop; GstElement *pipeline = NULL; GstElement *seiinject = NULL; GstElement *filesink = NULL; GstBus *bus = NULL; GByteArray *barray = NULL; guint metalen = 0; GError *error = NULL; if (!metademo) { return FALSE; } loop = g_main_loop_new(NULL, FALSE); pipeline = gst_parse_launch(PIPELINE_DESCRIPTION, &error); if (error) { g_printerr("Unable to build pipeline (%s)\n", error->message); g_clear_error(&error); return FALSE; } seiinject = gst_bin_get_by_name(GST_BIN(pipeline), "inject"); if (!seiinject) { g_printerr("Could not get metadata element\n"); return FALSE; } filesink = gst_bin_get_by_name(GST_BIN(pipeline), "sink"); if (!filesink) { g_printerr("Could not get filesink element\n"); return FALSE; } /*Prepare metadata*/ metalen = sizeof(binary_metadata); barray = g_byte_array_new_take(binary_metadata, metalen); g_object_set(seiinject, "metadata-binary", barray, NULL); g_boxed_free(G_TYPE_BYTE_ARRAY, barray); g_object_set(G_OBJECT(filesink), "location", FILE_LOCATION, NULL); /* we add a message handler */ bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_add_watch(bus, bus_call, loop); gst_object_unref(bus); metademo->pipeline = pipeline; metademo->main_loop = loop; metademo->seiinject = seiinject; metademo->filesink = filesink; return TRUE; } static void start_pipeline(GstMetaDemo *metademo) { gst_element_set_state(metademo->pipeline, GST_STATE_PLAYING); } static void stop_pipeline(GstMetaDemo *metademo) { gst_element_set_state(metademo->pipeline, GST_STATE_NULL); } static void release_resources(GstMetaDemo *metademo) { if (!metademo) { return; } stop_pipeline(metademo); if (metademo->pipeline) { gst_object_unref(metademo->pipeline); metademo->pipeline = NULL; } if (metademo->seiinject) { gst_object_unref(metademo->seiinject); metademo->seiinject = NULL; } if (metademo->filesink) { gst_object_unref(metademo->filesink); metademo->filesink = NULL; } if (metademo->main_loop) { g_main_loop_unref(metademo->main_loop); metademo->main_loop = NULL; } } static gboolean handle_signal(gpointer data) { GstMetaDemo *metademo = (GstMetaDemo *)data; g_main_loop_quit(metademo->main_loop); return TRUE; }
Application Walk-through
This is a quick walk-trough to better understand the process of creating the pipeline and injecting the metadata in the previous example.
Pipeline description
#define PIPELINE_DESCRIPTION \ "videotestsrc num-buffers=10 ! video/x-raw,width=16,height=240 ! x264enc ! video/x-h264,stream-format=avc ! " \ "seiinject name=inject ! filesink name=sink location=seiinject_metadata_binary_videotestsrc_avc.h264"
As seen above, all we need to inject the metadata is the seiinject element, which will take the provided metadata, inject it into the encoded stream and then store it in the file seiinject_metadata_binary_videotestsrc_avc.h264
Metadata packet
static guint8 binary_metadata[] = { /*This is "Hello World!!" in hexadecimal*/ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x21, };
Note that this could have been any array of bytes, the above one is just an example.
Metadata injection
seiinject = gst_bin_get_by_name(GST_BIN(pipeline), "inject"); if (!seiinject) { g_printerr("Could not get metadata element\n"); return FALSE; } filesink = gst_bin_get_by_name(GST_BIN(pipeline), "sink"); if (!filesink) { g_printerr("Could not get filesink element\n"); return FALSE; } /*Prepare metadata*/ metalen = sizeof(binary_metadata); barray = g_byte_array_new_take(binary_metadata, metalen); g_object_set(seiinject, "metadata-binary", barray, NULL); g_boxed_free(G_TYPE_BYTE_ARRAY, barray); g_object_set(G_OBJECT(filesink), "location", FILE_LOCATION, NULL);
- metadata binary: In line 16, the metadata binary is injected using the metadata-binary property.
Building 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.
Running the application
Execute the application with the following command:
GST_DEBUG="2,*obu*:MEMDUMP" ./main
This will create a file called seiinject_metadata_binary_videotestsrc_avc.h264 in the same directory where the application is running.
To check the data was inserted correctly you can run:
GST_DEBUG=*seiextract*:MEMDUMP gst-launch-1.0 filesrc location=seiinject_metadata_binary_videotestsrc_avc.h264 ! video/x-h264,stream-format=avc ! seiextract ! fakesink
And you will see something like this:
Setting pipeline to PAUSED ... Pipeline is PREROLLING ... 0:00:00.017574482 7940 0x55ba08c160a0 DEBUG seiextract gstseiextract.c:251:gst_sei_extract_set_caps:<seiextract0> set_caps 0:00:00.017615098 7940 0x55ba08c160a0 DEBUG seiextract gstseiextract.c:257:gst_sei_extract_set_caps: parsing caps: video/x-h264, stream-format=(string)avc 0:00:00.017748013 7940 0x55ba08c160a0 LOG seiextract gstseiextract.c:295:gst_sei_extract_prepare_output_buffer:<seiextract0> prepare_output_buffer 0:00:00.017781023 7940 0x55ba08c160a0 LOG seiextract gstseiextract.c:345:gst_sei_extract_prepare_output_buffer:<seiextract0> Not the expected payload type: 5 0:00:00.017789475 7940 0x55ba08c160a0 LOG seiextract gstseiextract.c:352:gst_sei_extract_prepare_output_buffer:<seiextract0> The extracted data is: Hello World!! ...
Where you can see the "Hello World!!" message we inserted as binary.