KlvInjectorTestApp

KlvInjectorTestApp is a simplified example that demonstrates how to process video stream, file or uncompressed frames from a capture device, add Klv metadata and create STANAG 4609 compliant stream or file.

Command line arguments

Demo application will accept the following arguments

Short Command Description
-i --input Input url. The url is a file path or Udp url, like udp://227.1.1.1:30120. To select specific network interface, add Nic selection - udp://227.1.1.1:30120/nic=192.168.1.10
-c --captureDevice Input Capture device name or id returned by List capture devices call
-o --output Output url (network).
-f --file File target Output url.
--klvPid Klv Pid. If Klv found in the stream, it's Pid number will be used. If not present and not provided, 0X1F1 will be used
--dataPid Private data Pid, if needs to be inserted.
-p --packet Default Klv packet to insert. Can be either RAW Klv or Json.
-t --timeInterval Klv insertion interval (for default packet). If set to 0 (default), will be inserted with every frame.
-v --video Show video during processing. Default - false.
--maxDelay Max sync delay. Max delay between the video and klv.
--caching Network caching. Increase the value if the network stream has jitter. Decrease, to lower the latency.
--syncKlvMode SyncKlv Mode. Default - false (generates ASYNC KLV).
--frameResolution Frame resolution - 'Width'x'Height'. Default 720x480.
-b --bitrate Encoding bitrate (in KBit/s). Default 1000.
--framerate Frame rate. Default 30.
--encodingProfile Baseline = 0, HighProfile = 1, MainProfile = 2. Default 0 (baseline)
--licenseFile License File path. If not set, Injector will try to load KlvInjector.lic file in Application.StartupPath directory.
--licenseKey License key.
-? --help Help.

For example:

KlvInjectorTestApp.exe -i udp://227.1.1.1:30120 -o udp://225.1.1.1:1234 -p defaultPacket.bin

Using SDK

Let's create a VS project, add the references and make sure all the required dependencies are copied to the target directory.

KlvInjector related references:
- KlvInjector
- KlvPlayer
- StCoreWr
- Klv2JsonLib

Test App related references:
- Colorful.Console
- FluentCommanLineParser
- Newtonsoft.Json

Next, we create an instance of the KlvInjector, initialize it and add events:

CKlvInjector m_KlvInjector = new CKlvInjector();

// Setup events
m_KlvInjector.PlayerEvent += new NotifyPlayerEvent(OnPlayerEvent);                //  Player general events notification
m_KlvInjector.ErrorEvent += new NotifyError(OnErrorEvent);                        //  Player error events
m_KlvInjector.PidDetectionEvent += new NotifyPidDetection(OnPidDetectionEvent);   //  PID detection events (video / KLV / audio / data)
m_KlvInjector.SyncFrameEvent += new NotifySyncFrame(OnSyncFrameEvent);            //  Synchronized Video frames / Klv / Private data  

There are some additional parameters that may be configured:

// Setup video / audio rendering
// Set to true if you want to decode and show the video / audio
m_KlvInjector.RenderVideo = true;  
m_KlvInjector.RenderAudio = false;

// Set Window handle to render video to. If set to 0, the default window will be created internally.
m_KlvInjector.Hwnd = 0;

// If your source is a udp stream, set Caching (de-jitter) buffer. Set to minimal possible value (depending on your stream) to get a low latency stream playback. Note, this is a latency you add, so be careful.
m_KlvInjector.Caching = 300;

// Configure KlvInsertion mode - SYNC or ASYNC
m_klvProps = new KlvDataPropsWr(ProcessingModeWr.INSERT_KLV_ASYNC);

// Configure uncompressed video extraction mode.  Please note, depending on video resolution, this is a pretty resource demanding operation, so do not request uncompressed video frames unless you need them.
m_KlvInjector.VideoCaptureMode.uncompressedVideo = UncompressedVideoModeWr.UncompressedVideoMode_None;
// Configure compressed video extraction mode. Note, if you intend to insert packets on the video frame callback context, set it to true, otherwise the event will never fire
m_KlvInjector.VideoCaptureMode.fCompressedVideo = true;

// Read default packet, if needed
if (!string.IsNullOrEmpty(m_DefaultPcktPath))
    ReadDefaultPacket();

Next, we'll configure the output. In this demo we'll have both network and file targets, so the resulted STANAG stream will be simultaneously recorded to file and recasted to the network.

// Network stream target
m_KlvInjector.NetTarget.Url = m_targetUrl;      // output url. For example, udp://225.1.1.1:1234 to send the stream as multicast udp 
m_KlvInjector.NetTarget.Use = true;             // Enable network stream output.

// File target
m_KlvInjector.FileTarget.Dir = Path.GetDirectoryName(m_targetFile);
m_KlvInjector.FileTarget.Name = Path.GetFileName(m_targetFile);
m_KlvInjector.FileTarget.SegmentationType = FileSegmentationType.SegmentationType_None;     // No segmentation
m_KlvInjector.FileTarget.Use = true;                                                        // Enable file recording output.

We're almost done. Last thing to do is to actually configure the KLV PID. The best place for this would be at the runtime, when we get the detection event. Here we have all the information needed. The source stream may already have KLV or Data Pids, so here we can decide whether to add an additional Klv PID, replace the existing one, etc. If your source stream does not have a Klv pid you can just call m_KlvInjector.AddKlvPidToOutput method.

void OnPidDetectionEvent(List<PidInfoWr> pidList)
{
    pidList.ForEach(pid =>
    {
        Console.WriteLine("Pid 0X{0} type {1}", pid.streamId.ToString("X"), pid.streamType, Color.LightGray);

        // Find video pid. We'll use it for statistics.
        if (pid.streamType == StreamType.VIDEO)
            m_VideoPid = pid.streamId;

        // Find first Klv PID. If already present in the stream, we'll replace it with our data. If there is no KLV, we'll use the default 0X1F1 value.
        if (pid.streamType == StreamType.KLV && m_KlvPid == -1)
            m_KlvPid = pid.streamId;
    });

    // Add KLV PID to multiplexer
    m_KlvInjector.AddKlvPidToOutput(m_KlvPid != -1 ? m_KlvPid : 0X1F1, m_klvProps);
}

Note. If there is a need to drop an existing Klv data or process and reinsert it, call m_KlvInjector.IgnorePidInOutput(klvPid) followed by m_KlvInjector.AddKlvPidToOutput(newKlvPid);

There are some additional parameters that can be configured but for the sake of simplicity we'll first go with defaults.

// Initialize injector
m_KlvInjector.Init(m_Url);      // The url is a file path or Udp url, like udp://227.1.1.1:30120. To select specific network interface, add Nic selection - udp://227.1.1.1:30120/nic=192.168.1.10

// Start Processing
m_KlvInjector.Start();

Now the process is running and we can insert the Klv data when needed.

  m_KlvInjector.WritePacketToOutputPid(m_InsertKlvPid, pckt, timestamp);
  • timestamp - timestamp for SYNC KLV. Reference clock (100-nanosecond). You can set -1 or nothing at all. In the later case the timestamp will be set automatically.
  • pcktBuf - RAW Klv buffer.