<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" id="owaParaStyle">
<!--
p
        {margin-top:0;
        margin-bottom:0}
p
        {margin-top:0;
        margin-bottom:0}
-->
P {margin-top:0;margin-bottom:0;}</style>
</head>
<body fpstyle="1" ocsi="0">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">Hi,<br>
<br>
I have unsuccessfully looked for examples code of the mpegtsmux plugins to mux KLV metadata in a video.<br>
<a href="https://github.com/GStreamer/gst-plugins-bad/tree/master/tests/examples" target="_blank">https://github.com/GStreamer/gst-plugins-bad/tree/master/tests/examples</a><br>
<br>
I also search for a response on the mailing list archives to my questioning without success.<br>
<a href="https://lists.freedesktop.org/archives/gstreamer-devel/2015-December/055789.html" target="_blank">https://lists.freedesktop.org/archives/gstreamer-devel/2015-December/055789.html</a><br>
<a href="https://lists.freedesktop.org/archives/gstreamer-devel/2016-February/056957.html" target="_blank">https://lists.freedesktop.org/archives/gstreamer-devel/2016-February/056957.html</a><br>
<br>
So, how to embed klv into mpegts stream?</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt"><br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">If someone is able to tell me the changes to make to the code to mux the KLV metadata and save them in a video file, here is my sample code that records a video stream (h264) with
 mpegtsmux from a webcam using GStreamer 1.8.3: <br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt"><br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">#include <string.h><br>
#include <gst/gst.h><br>
#include <signal.h><br>
#include <unistd.h><br>
#include <stdlib.h><br>
#include <iostream><br>
<br>
static GMainLoop *loop;<br>
static GstElement *pipeline, *appsrc, *src, *tee, *encoder, *muxer, *filesink, *videoconvert, *videosink, *queue_record, *queue_display, *caps_filter, *capsfilter_klv;<br>
static GstBus *bus;<br>
<br>
/* KLV data from Day_Flight.mpg */<br>
static const guint8 rtp_KLV_frame_data[] = {<br>
  0x06, 0x0e, 0x2b, 0x34, 0x02, 0x0b, 0x01, 0x01,<br>
  0x0e, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00,<br>
  0x81, 0x91, 0x02, 0x08, 0x00, 0x04, 0x6c, 0x8e,<br>
  0x20, 0x03, 0x83, 0x85, 0x41, 0x01, 0x01, 0x05,<br>
  0x02, 0x3d, 0x3b, 0x06, 0x02, 0x15, 0x80, 0x07,<br>
  0x02, 0x01, 0x52, 0x0b, 0x03, 0x45, 0x4f, 0x4e,<br>
  0x0c, 0x0e, 0x47, 0x65, 0x6f, 0x64, 0x65, 0x74,<br>
  0x69, 0x63, 0x20, 0x57, 0x47, 0x53, 0x38, 0x34,<br>
  0x0d, 0x04, 0x4d, 0xc4, 0xdc, 0xbb, 0x0e, 0x04,<br>
  0xb1, 0xa8, 0x6c, 0xfe, 0x0f, 0x02, 0x1f, 0x4a,<br>
  0x10, 0x02, 0x00, 0x85, 0x11, 0x02, 0x00, 0x4b,<br>
  0x12, 0x04, 0x20, 0xc8, 0xd2, 0x7d, 0x13, 0x04,<br>
  0xfc, 0xdd, 0x02, 0xd8, 0x14, 0x04, 0xfe, 0xb8,<br>
  0xcb, 0x61, 0x15, 0x04, 0x00, 0x8f, 0x3e, 0x61,<br>
  0x16, 0x04, 0x00, 0x00, 0x01, 0xc9, 0x17, 0x04,<br>
  0x4d, 0xdd, 0x8c, 0x2a, 0x18, 0x04, 0xb1, 0xbe,<br>
  0x9e, 0xf4, 0x19, 0x02, 0x0b, 0x85, 0x28, 0x04,<br>
  0x4d, 0xdd, 0x8c, 0x2a, 0x29, 0x04, 0xb1, 0xbe,<br>
  0x9e, 0xf4, 0x2a, 0x02, 0x0b, 0x85, 0x38, 0x01,<br>
  0x2e, 0x39, 0x04, 0x00, 0x8d, 0xd4, 0x29, 0x01,<br>
  0x02, 0x1c, 0x5f<br>
};<br>
<br>
static gboolean<br>
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)<br>
{<br>
  switch (GST_MESSAGE_TYPE (message)) {<br>
    case GST_MESSAGE_ERROR:{<br>
      g_main_loop_quit (loop);<br>
<br>
      GError *err = NULL;<br>
      gchar *name, *debug = NULL;<br>
      name = gst_object_get_path_string (message->src);<br>
      gst_message_parse_error (message, &err, &debug);<br>
<br>
      std::string err_message = err->message;<br>
      if(err_message == "Output window was closed"){<br>
          std::cout << std::endl << err_message << std::endl;<br>
      }<br>
      else{<br>
          g_printerr ("\nERROR: from element %s: %s\n", name, err->message);<br>
          if (debug != NULL)<br>
              g_printerr ("Additional debug info:\n%s\n", debug);<br>
      }<br>
<br>
      g_error_free (err);<br>
      g_free (debug);<br>
      g_free (name);<br>
      break;<br>
    }<br>
    case GST_MESSAGE_WARNING:{<br>
        GError *err = NULL;<br>
        gchar *name, *debug = NULL;<br>
<br>
        name = gst_object_get_path_string (message->src);<br>
        gst_message_parse_warning (message, &err, &debug);<br>
<br>
        g_printerr ("ERROR: from element %s: %s\n", name, err->message);<br>
        if (debug != NULL)<br>
        g_printerr ("Additional debug info:\n%s\n", debug);<br>
<br>
        g_error_free (err);<br>
        g_free (debug);<br>
        g_free (name);<br>
        break;<br>
    }<br>
    case GST_MESSAGE_EOS: {<br>
        g_print ("Got EOS\n");<br>
        g_main_loop_quit(loop);<br>
        break;<br>
    }<br>
    default:<br>
        break;<br>
  }<br>
<br>
  return TRUE;<br>
}<br>
void need_data(GstElement* element, guint, gpointer userData)<br>
{<br>
    std::cout << "need_data" << std::endl;<br>
    // TODO push binary data (rtp_KLV_frame_data) in Big-Endian.<br>
}<br>
void sigintHandler(int unused)<br>
{<br>
    g_print("You ctrl-c-ed!");<br>
    gst_element_send_event(pipeline, gst_event_new_eos());<br>
}<br>
int main(int argc, char *argv[])<br>
{<br>
    signal(SIGINT, sigintHandler);<br>
    gst_init (&argc, &argv);<br>
<br>
    guint major, minor, micro, nano;<br>
    gst_version (&major, &minor, &micro, &nano);<br>
    std::string nano_str = nano==1 ? "(CVS)" : (nano==2 ? "(Prerelease)" : "");<br>
    std::cout << "This program is linked against GStreamer " << major << "." << minor<< "." << micro << " " << nano_str << std::endl;<br>
<br>
    pipeline = gst_pipeline_new(NULL);<br>
    appsrc = gst_element_factory_make ("appsrc", "source");<br>
    src = gst_element_factory_make("v4l2src", NULL);<br>
    tee = gst_element_factory_make("tee", "tee");<br>
    encoder = gst_element_factory_make("x264enc", NULL);<br>
    muxer = gst_element_factory_make("mpegtsmux", NULL);<br>
    filesink = gst_element_factory_make("filesink", NULL);<br>
    videoconvert = gst_element_factory_make("videoconvert", NULL);<br>
    videosink = gst_element_factory_make("autovideosink", NULL);<br>
    queue_display = gst_element_factory_make("queue", "queue_display");<br>
    queue_record = gst_element_factory_make("queue", "queue_record");<br>
    caps_filter  = gst_element_factory_make("capsfilter", NULL);<br>
    capsfilter_klv = gst_element_factory_make("capsfilter", NULL);<br>
<br>
    if (!pipeline || !src || !tee || !encoder || !muxer || !filesink || !videoconvert || !videosink || !queue_record || !queue_display) {<br>
            std::cerr << "Failed to create elements:"<br>
                  << (!pipeline? " pipeline " : "")<br>
                  << (!src? " v4l2src " : "")<br>
                  << (!tee? " tee " : "")<br>
                 << (!encoder? " x264enc " : "")<br>
                 << (!muxer? " mpegtsmux " : "")<br>
                 << (!filesink? " filesink " : "")<br>
                 << (!videoconvert? " videoconvert " : "")<br>
                 << (!videosink? " autovideosink " : "")<br>
                 << (!queue_display? " queue_display " : "")<br>
                 << (!queue_record? " queue_record " : "")<br>
                 << std::endl;<br>
            return -1;<br>
        }<br>
<br>
    // Create caps<br>
    /*GstCaps *video_cap = gst_caps_new_simple ("video/x-raw",<br>
                         "width", G_TYPE_INT, 640,<br>
                         "height", G_TYPE_INT, 480,<br>
                         "framerate", GST_TYPE_FRACTION, 30, 1,<br>
                         NULL);*/<br>
    GstCaps *klv_caps = gst_caps_new_simple("meta/x-klv", "parsed", G_TYPE_BOOLEAN, TRUE, "sparse", G_TYPE_BOOLEAN, TRUE, nullptr);<br>
    GstCaps *caps = gst_caps_new_full (<br>
              gst_structure_new ("video/x-raw",<br>
                     "width", G_TYPE_INT, 640,<br>
                     "height", G_TYPE_INT, 480,<br>
                     "framerate", GST_TYPE_FRACTION, 30, 1,<br>
                     NULL),<br>
              gst_structure_new ("meta/x-klv",<br>
                     "parsed", G_TYPE_BOOLEAN, TRUE,<br>
                     "sparse", G_TYPE_BOOLEAN, TRUE,<br>
                     NULL),<br>
              NULL);<br>
<br>
    g_object_set(appsrc, "caps", klv_caps, nullptr);<br>
    g_object_set(appsrc, "format", GST_FORMAT_TIME, nullptr);<br>
<br>
    g_object_set (src, "device", "/dev/video0", NULL);<br>
    g_object_set (encoder, "noise-reduction", 10000, NULL);<br>
    //g_object_set (encoder, "tune", "Zero latency", NULL);<br>
    g_object_set (encoder, "threads", 4, NULL);<br>
    g_object_set(filesink, "location", "/home/jean/Desktop/rec.mpg", NULL);<br>
    g_object_set(filesink, "async", 0, NULL);<br>
    g_object_set(caps_filter, "caps", caps, NULL);<br>
    //g_object_set(capsfilter_klv, "caps", klv_caps, NULL);<br>
    gst_caps_unref(caps);<br>
    //gst_caps_unref(klv_caps);<br>
<br>
    gst_bin_add_many(GST_BIN(pipeline), src, caps_filter, tee, queue_record, encoder, muxer, filesink, queue_display, videoconvert, videosink, NULL);<br>
    if (!gst_element_link_many(src, tee, caps_filter, NULL)<br>
        || !gst_element_link_many(tee, queue_record, encoder, muxer, filesink, NULL)<br>
        || !gst_element_link_many(tee, queue_display, videoconvert, videosink, NULL)) {<br>
        g_error("Failed to link elements");<br>
        return -2;<br>
    }<br>
<br>
    gst_element_set_state(pipeline, GST_STATE_PLAYING);<br>
    if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {<br>
        g_error("Failed to go into PLAYING state");<br>
    }<br>
<br>
    bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));<br>
    gst_bus_add_signal_watch(bus);<br>
    g_signal_connect(G_OBJECT(bus), "message", G_CALLBACK(message_cb), NULL);</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">    //g_signal_connect(bus, "need-data", G_CALLBACK(need_data), NULL);<br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">    gst_object_unref(GST_OBJECT(bus));<br>
<br>
    g_signal_connect(appsrc, "need-data", G_CALLBACK(need_data), NULL);<br>
<br>
    loop = g_main_loop_new(NULL, FALSE);<br>
    g_print("Starting loop");<br>
    g_main_loop_run(loop);<br>
<br>
    // Free resources<br>
    gst_object_unref (bus);<br>
    gst_element_set_state (pipeline, GST_STATE_NULL);<br>
    gst_object_unref (pipeline);<br>
<br>
    return 0;<br>
}<br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt"><br>
</div>
<div style="direction:ltr; font-family:Tahoma; color:#000000; font-size:10pt">// Thanks!<br>
</div>
</div>
</div>
</body>
</html>