Difference between revisions of "LibMISB/Examples/GStreamer Application"

From RidgeRun Developer Connection
Jump to: navigation, search
m
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
 
<noinclude>
 
<noinclude>
{{LibMISB/Head|previous=Examples/Library_basic_usage|next=Evaluating|keywords=}}
+
{{LibMISB/Head|previous=Examples/Library_basic_usage|next=Evaluating|metakeywords=}}
 
</noinclude>
 
</noinclude>
  
Line 8: Line 8:
  
 
=== GStreamer application ===
 
=== 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 [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++]
+
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++].
 +
 
 +
'''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>]'''.
  
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
Line 42: Line 44:
  
  
const char* filename = "klv.bin";
+
const char* filename = "<PATH>/klv.bin";
  
 
typedef struct _GstMetaDemo GstMetaDemo;
 
typedef struct _GstMetaDemo GstMetaDemo;

Latest revision as of 12:35, 8 March 2023



Previous: Examples/Library_basic_usage Index Next: Evaluating





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

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:

./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.



Previous: Examples/Library_basic_usage Index Next: Evaluating