# C++ Application Code

A set of example applications are provided which illustrate the use of the FPGA based NDI IP cores with the Advanced NDI SDK. For full details and a theory of operation covering the entire system (software, hardware, and OS), refer to "Theory of Operation" in the "NFI FPGA Reference Design" section.

### Directory structure

Source code for the C++ Application examples is organized into the following subdirectories under the `fpga_reference_design/src/cpp/` directory:

| Directory    | Contents                                                   |
| ------------ | ---------------------------------------------------------- |
| ndi\_common/ | Files common to all NDI applications                       |
| ndi\_decode/ | Example NDI Decoder application (eg: TV or Monitor)        |
| ndi\_encode/ | Example NDI Encoder application (eg: Camera or NDI Source) |
| ndi\_util/   | Debug and utility applications                             |

## Getting Started

### Prerequisites

The following prerequisites must be installed before you can build the example applications.

#### libuio

* Source Code: <https://github.com/Linutronix/libuio>

libuio is used to access the FPGA hardware via entries in the device-tree

The available uSD card images have libuio packages compiled from source (see `~/libuio`) and the debian packages installed. For other platforms, libuio will need to be compiled and installed manually.

#### NDI Advanced SDK Library

The NDI Advanced SDK allows the sending and receiving of compressed frames, which is required to use the FPGA encoder. To install the library, simply copy the files to an appropriate location for your system. The example uSD card images have the NDI library files already installed in `/usr/local/lib` and `/usr/local/include`.

### Building and Installing

Once the prerequisites have been installed, building the applications is straight-forward:

```
cd <NDI_SDK>/fpga_reference_design/src/cpp
make
sudo make install
```

The applications will be installed with setuid privileges to the `/usr/local/bin/` directory.

### ndi\_encode

The `ndi_encode` utility is an example application illustrating the use of the FPGA based NDI encoder IP and the Advanced NDI SDK to create an NDI sender.

he ndi\_encode program is simply launched from the command line, eg:

```
ndi_encode
```

Note that this will launch the version installed in /usr/local/bin/. Alternatively, the program can be run from the build directory. Note that root permissions are required so it is necessary to use sudo:

```
sudo /path/to/workdir/ndi_encode
```

#### Run Time Commands

Once running, the program will listen for commands on stdin. These commands are intended to modify the running behavior of the program and illustrate how to integrate with a separate utility monitoring the physical video input source (eg: an HDMI or SDI input) as a signal is acquired, locked, or lost.

The commands which change the raw video parameters (resolution, frame rate, format, alpha) only apply when running in pattern generator mode. With a real video input, format details are determined automatically by the tracking logic.

* start | stop

  Start or stop streaming video and audio. This would correspond with the acquisition (start) or loss (stop) of a stable signal.
* 720 | 1080 | 4k

  Change the video resolution
* 24 | 25 | 30 | 50 | 60

  Set the primary video frame rate
* 1000 | 1001

  Set the secondary frame rate: 1000=exact (eg: 60.00), 1001=NTSC (eg: 59.94)
* UYVY | YUYV | NV16 | UYVW | Y216 | P216 | 420 | NV12 | 420W | P016

  Set the raw video format
* Alpha+ | Alpha-

  Enable / Disable alpha (4:2:2 modes only)
* exit

  Quit the program

#### Command Line Options

Various command line switches are available to control the program's behavior:

**General Options**

* Set default video resolution
  * -1 1080p60 (default)
  * -7 720p60
  * -4 4Kp60
* Video options
  * -P Pattern generator

    Use the built-in pattern generator instead of live video input.
  * -v Increase verbosity

    Output more detailed information. This switch may be provided multiple times to further increase the debugging output. The available levels are:

    * Fatal
    * Error (default)
    * Warning
    * Information
    * Debugging
  * -q Decrease verbosity (quiet)

    Decrease the amount of output generated. This switch may be provided multiple times. See the discussion of -v (above) for details.
* Audio Options
  * -h HDMI input

    Use embedded audio from the HDMI stream.
  * -l Line input

    Use analog audio input.
  * -p Pattern generator

    The audio input hardware includes a simple saw-tooth pattern generator that can be used as an input source for testing.

**Debugging and Advanced Options**

* -X Disable video capture

  This disables the video capture thread. No video frames will be captured, compressed, or sent to the NDI stack. Only audio will be processed.
* -x Disable audio capture

  This disables the video capture thread. No audio samples will be captured, compressed, or sent to the NDI stack. Only video will be processed.
* -F Full resolution capture only

  This option disables the preview stream and only sends full resolution frames to the NDI stack.
* -f fflush() after each log message

  This is useful if the application is crashing to insure log error messages actually reach the terminal.
* -A Use ACP
* -B Bypass ACP

  These options do nothing on the current Zynq development boards and only apply to Cyclone-V based platforms.

### ndi\_decode

The `ndi_decode` utility is an example application illustrating the use of the FPGA based NDI encoder IP and the Advanced NDI SDK to create an NDI receiver.

#### Usage

The ndi\_decode program is simply launched from the command line, eg:

```
# Launch and display the first NDI source found
ndi_decode

# Launch and connect to a specific NDI source
ndi_decode -s "Machine name (NDI channel)"
```

Note that this will launch the version installed in /usr/local/bin/. Alternatively, the program can be run from the build directory. Note that root permissions are required so it is necessary to use sudo:

`sudo /path/to/workdir/ndi_receive`

#### Command Line Options

Various command line switches are available to control the program's behavior:

**General Options**

* -s `<NDI Source>`

  Specify NDI source to stream. If this setting is not provided, ndi\_receive will attempt to connect to the first NDI source it finds on the network.
* Set output video resolution
  * -1 1080p (default)
  * -7 720p
  * -4 4Kp
* Set output video framerate
  * -6 60 Hz (default)
  * -5 50 Hz
* Select output video
  * -k Output key (alpha) data if available instead of image data
* Select SDRAM burst mode
  * -b Disable SDRAM burst mode (e.g., 1 macroblock to SDRAM per burst transfer). Default behavior is to burst 4 macroblocks to SDRAM per burst transfer.
* -o `<output format>`

  Specifies the output video format, where `output format` is one of the enumerated `video_format_t` values in `hardware.h` in decimal. The default is packed 4:2:2 (e.g., UYVY).

**Debugging and Advanced Options**

* -v Increase verbosity

  Output more detailed information. This switch may be provided multiple times to further increase the debugging output. The available levels are:

  * Fatal
  * Error (default)
  * Warning
  * Information
  * Debugging
* -q Decrease verbosity (quiet)

  Decrease the amount of output generated. This switch may be provided multiple times. See the discussion of -v (above) for details.
* -f fflush() after each log message

  This is useful if the application is crashing to insure log error messages actually reach the terminal.
* -A Use ACP
* -B Bypass ACP

  These options do nothing on the current Zynq development boards and only apply to Cyclone-V based platforms.
* -c `<capture file>`

Allows for individual frames to be captured to the filesystem. This switch is intended for debugging purposes and assumes that the stride is equal to the length of a row of image data. The default is to capture frame number 25, but this can be modified using the `-n` argument to select a different value. No more than one frame can be captured at a time.

* -n `<frame capture number>`

If capturing video frames, indicates the frame number to capture (defaults to 25). Requires the use of the `-c` option to capture frames.

### ndi\_reg

The `ndi_reg` utility allows reading and writing of the NDI hardware registers. To read an NDI register, provide the register address on the command line:

```
# Read the Video Input register
ndi_reg 0x200
```

To write an NDI register, provide the register address and write data on the command line:

```
# Write the Video Input register
ndi_reg 0x200 0x00c00100
```

#### Register Map

Each major hardware block is allocated a range of control register addresses as detailed below and implemented in the `device.h` and `hardware.h` files in the `src/cpp/ndi_common/` directory.

| Hardware           | Base Address | Length |
| ------------------ | ------------ | ------ |
| NDI Encoder Core 0 | 0x000        | 0x40   |
| NDI Encoder Core 1 | 0x040        | 0x40   |
| NDI Encoder Core 2 | 0x080        | 0x40   |
| NDI Encoder Core 3 | 0x0c0        | 0x40   |
| NDI Decoder Core 0 | 0x100        | 0x40   |
| NDI Decoder Core 1 | 0x140        | 0x40   |
| NDI Decoder Core 2 | 0x180        | 0x40   |
| NDI Decoder Core 3 | 0x1c0        | 0x40   |
| Video Input        | 0x200        | 0x10   |
| Preview Input      | 0x210        | 0x10   |
| Audio Input        | 0x220        | 0x10   |
| Video Tracking     | 0x230        | 0x10   |
| Video Output       | 0x280        | 0x10   |
| Audio Output       | 0x290        | 0x10   |
| Version (Date)     | 0x3fe        | 0x10   |
| Version (Revision) | 0x3ff        | 0x10   |

For low-level details on register settings and bit definitions refer to the specific C++ class code and headers for the hardware as described in the "Theory of Operation" section.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ndi.video/all/developing-with-ndi/advanced-sdk/ndi-advanced-sdk-fpga-example-reference-design/ndi-advanced-sdk-fpga-ip/c++-application-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
