Encoding STANAG 4609 MISB KLV with GStreamer and MisbCore library

This sample application demonstrates how to create a simplified GStreamer pipeline for encoding and injecting MISB601 KLV metadata into STANAG 4609 files/streams using MisbCore library

For the sake of simplicity, we'll use GStreamer's videotestsrc as a video source, encode it into H.264, encode a static metadata packet (updated with a current time ), multiplex everything, and record it into a standard-compliant STANAG 4609 file.

Building the pipeline

The code is pretty straightforward - we start manually creating a pipeline that consists of the videotestsrc and x264enc plugins, add multiplexer, and a filesink. Some additional auxiliary plugins will be added as well...


Below we'll show some essential code snippets - everything else is a regular GStreamer code...

As with all GStreamer applications, we start by creating a pipeline and loading plugins.
We'll use appsrc as our data source, so let's configure it:

g_object_set(G_OBJECT(dataSrc), "caps", gst_caps_new_simple("meta/x-klv", "parsed", G_TYPE_BOOLEAN, TRUE, "spare", G_TYPE_BOOLEAN, TRUE, "is-live", G_TYPE_BOOLEAN, TRUE, NULL), NULL);
  g_object_set(G_OBJECT(dataSrc), "format", GST_FORMAT_TIME, NULL);
  g_object_set(G_OBJECT(dataSrc), "do-timestamp", TRUE, NULL);

We should also configure video encoding and file target parameters (check out the sample source code for more info).

Let's assign a callback need-data which will signal that the source needs more data. In this callback we'll encode our metadata and push the RAW KLV:

/* Assign callback to encode and push metadata */
  g_signal_connect(dataSrc, "need-data", G_CALLBACK(pushKlv), NULL);

Before we implement the data injection, we need to load the misbCore library:

First, we load the library (somewhere at the beginning of our application):

void *handle;

/* Load library */
handle = dlopen((char *)PathToLibrary, RTLD_LAZY);

Next, we get the pointer to the encode method:

typedef char *(*encodeFunc)(char *, int &len);
encodeFunc encode601Pckt = (encodeFunc)funcAddr(handle, (char *)"Encode");

Now, lets look at the callback. 

static void pushKlv(GstElement *src, guint, GstElement)
  GstFlowReturn ret;
  GstBuffer *buffer;
  bool fInsert = false;
  int len;

  // Wait for a frame duration interval since the last inserted packet. As we're inserting ASYNC KLV, it is good enough for the demo...
  while (!fInsert)
    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
    float diff = std::chrono::duration(now - lastPcktTime).count();

    if (diff > frameDuration)
      fInsert = true;

  // First, encode the klv buffer from jsonPcktStr
  char *buf = encode601Pckt((char *)(jsonPcktStr), len);

  buffer = gst_buffer_new_allocate(NULL, len, NULL);

  // For ASYNC_KLV, we need to remove timestamp and duration from the buffer

  // Fill the buffer with the encoded KLV data
  gst_buffer_fill(buffer, 0, buf, len);

  ret = gst_app_src_push_buffer((GstAppSrc *)src, buffer);

  if (ret != GST_FLOW_OK)
    g_printerr("Flow error");
    lastPcktTime = std::chrono::steady_clock::now();
    g_print("Klv packet count: %llu.  Buf size: %d \n", counter, len);

Klv timestamp

In the sample, we don't provide a mandatory Tag 2 (timestamp).
When no timestamp is found, MisbCore will automatically set the current time.

Running the application.

Now, everything is ready and we can run the application:

Klv packet count: 1.  Buf size: 106 
Klv packet count: 2.  Buf size: 106 
Klv packet count: 3.  Buf size: 106 
Klv packet count: 4.  Buf size: 106 
Klv packet count: 5.  Buf size: 106 
Klv packet count: 6.  Buf size: 106 
Klv packet count: 7.  Buf size: 106 
Klv packet count: 8.  Buf size: 106 
Klv packet count: 9.  Buf size: 106 

STANAG 4609 file should be created and a packet counter with the buffer size will be sent to console.

Cleaning up

MisbCore allocates memory for the last encoded buffer, so we need to free it at the end:

  /* Clean up allocated resources */
    cleanUpFunc cleanUp = (cleanUpFunc)funcAddr(handle, (char*)"CleanUp");

Source code

The complete source code is available as part of SDK.

No Comments

Post a Comment