|
|
Line 5: |
Line 5: |
| </noinclude> | | </noinclude> |
|
| |
|
| {{review|For Examples section please divide it in 2 pages: 1. Library basic usage. 2. Add data to MPEG Transport Stream.|Enrique}}
| | |
|
| |
|
| == Testing library == | | == Testing library == |
Line 35: |
Line 35: |
| ./misb-converter --decode -i klv.bin -o output.json | | ./misb-converter --decode -i klv.bin -o output.json |
| </syntaxhighlight> | | </syntaxhighlight> |
|
| |
| == Reference application ==
| |
| {{review|Move this to the other page (2. Add data to MPEG Transport Stream), Please start the example saying there are plans to implement a GStreamer misb codec, but in the meantime there's a reference to include the encoded data into a MPEG Transport Stream.|Enrique}}
| |
|
| |
| 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 [https://developer.ridgerun.com/wiki/index.php/GStreamer_In-Band_Metadata_for_MPEG_Transport_Stream/Examples/_C/C%2B%2B GStreamer In-Band Metadata for MPEG Transport Stream - Examples - C - C++]
| |
|
| |
| <syntaxhighlight lang="C">
| |
| /* 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 = "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;
| |
| }
| |
| </syntaxhighlight>
| |
|
| |
| == Building the application ==
| |
|
| |
| In order to build the appication, copy the example into a file called '''main.c''' and build using the following command:
| |
|
| |
| <pre>
| |
| gcc -Wall main.c -o main `pkg-config --cflags --libs gstreamer-1.0`
| |
| </pre>
| |
|
| |
| After this you will end up with a binary called main.
| |
|
| |
| == Running the application ==
| |
|
| |
| Execute the application with the following command:
| |
|
| |
| <pre>
| |
| ./main
| |
| </pre>
| |
|
| |
| 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'''.
| |