LibMISB - Examples - GStreamer Application
LibMISB |
---|
![]() |
Introduction |
Supported Standards |
Getting Started |
Examples |
Evaluating |
Contact Us |
Add data to MPEG Transport Stream
The following sample application shows how to inject already-encoded metadata into a MPEG-TS stream, it assumes the metadata was already encoded using the library. In future releases, it will be provided a set of GStreamer elements for encoding and decoding the metadata inline in the pipeline.
GStreamer application
In the following example, we show you how to use Gstreamer In-Band metadata to add a KLV packet (generated by LibMISB) into a Transport Stream. Based on GStreamer In-Band Metadata for MPEG Transport Stream - Examples - C - C++.
![]() | Important: The encoded packet that was generated by LibMISB must declare in the variable const char* filename and you need to define packet length in static guint8 klv_metadata[<PACKET_LENGTH>]. |
/* Copyright (C) 2022 RidgeRun, LLC (http://www.ridgerun.com)
* All Rights Reserved.
*
* The contents of this software are proprietary and confidential to RidgeRun,
* LLC. No part of this program may be photocopied, reproduced or translated
* into another programming language without prior written consent of
* RidgeRun, LLC. The user is free to modify the source code after obtaining
* a software license from RidgeRun. All source code changes must be provided
* back to RidgeRun without any encumbrance.
*/
#include <glib.h>
#include <glib-unix.h>
#include <gst/gst.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PIPELINE_DESCRIPTION \
"metasrc name=meta ! meta/x-klv,stream_type=21 ! mpegtsmux name=mux ! " \
"filesink name=sink location=./metadata_misb_library.ts videotestsrc " \
"is-live=true ! video/x-raw,width=640,height=480,framerate=30/1 ! queue ! " \
"x264enc ! mux."
#define METADATA_PERIOD_SECS 1
#define FILE_LOCATION "./metadata_misb_library.ts"
static guint8 klv_metadata[61];
const char* filename = "<PATH>/klv.bin";
typedef struct _GstMetaDemo GstMetaDemo;
struct _GstMetaDemo {
GstElement *pipeline;
GstElement *metasrc;
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);
static gboolean handle_signal(gpointer data);
int main(int argc, char *argv[]) {
struct stat sb;
FILE* in_file = fopen(filename, "rb");
if (!in_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
fread(klv_metadata, sizeof(klv_metadata), 1, in_file);
for(uint i = 0; i<sizeof(klv_metadata); i++)
printf("%u ", klv_metadata[i]);
printf("\n");
fclose(in_file);
GstMetaDemo *metademo = g_malloc(sizeof(GstMetaDemo));
if(!metademo){
g_print("Could not create demo\n");
return 1;
}
g_unix_signal_add(SIGINT, (GSourceFunc)handle_signal, metademo);
/* 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 *metasrc = NULL;
GstElement *filesink = NULL;
GstBus *bus = NULL;
GByteArray *barray = NULL;
guint8 *array_copy = 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;
}
metasrc = gst_bin_get_by_name(GST_BIN(pipeline), "meta");
if (!metasrc) {
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*/
/*We need to copy the array since the GByteArray will be the new owner and free it for us*/
metalen = sizeof(klv_metadata);
array_copy = g_malloc (metalen);
memcpy (array_copy, klv_metadata, metalen);
barray = g_byte_array_new_take(array_copy, metalen);
g_object_set(metasrc, "metadata-binary", barray, NULL);
g_boxed_free(G_TYPE_BYTE_ARRAY, barray);
g_object_set(G_OBJECT(metasrc), "period", METADATA_PERIOD_SECS, NULL);
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->metasrc = metasrc;
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->metasrc) {
gst_object_unref(metademo->metasrc);
metademo->metasrc = 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;
}
Building the application
To build the application, 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:
./main
This will create a file called 'metadata_misb_library.ts in the same directory where the application is running.
Stop the application with Ctrl + C.