Example programs
================
This is a collection of example programs demonstrating how to use Netint hardware
transcoding solutions through libavcodec.

Compile
================
In Linux
If run example under Linux, please use "make" to build.
If run example under Android, please use the following command to build:
  ./build_apiexample_for_android.sh --ffmpeg_path=xxx
Note: xxx is the path where FFmpeg is placed, apiexample is depent on ffmpeg build.
You can use "./build_apiexample_for_android.sh -h" to see details.

In Windows
If run example under Windows, use "make WINDOWS=TRUE" to build.

###
Building example programs

These libavcodec api example programs were written for use with FFmpeg-n4.2.1.
Use 'make build_info' to see a list of supported examples for the FFmpeg build.
FFmpeg must be built with shared libraries to link to these api example programs.
For example, from the FFmpeg directory, run:
  sudo make clean; bash build_ffmpeg.sh --shared && sudo make install && sudo ldconfig

To build ni_xstack to run with ni_quadra_drawtext filter, use --nidrawtext option, e.g.:
  bash build_ffmpeg.sh --nidrawtext --shared

To build libavcodec api example programs, from this directory run:
  sudo make clean; make

Note: About build of FFmpeg for Android, please refer to <<APPS608 Android Docker setup Application Note>>

###
ni_demuxing_decoding

This example program uses libavformat to demux an input video, then uses Netint HW decoder
through libavcodec to decode it to YUV.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec
Supported encoder: NULL

Support FFmpeg version: 3.1.1 and above

Usage exmaple:
  sudo ./ni_demuxing_decoding input_file.h264 output_file.yuv


###
ni_encode_video

This example program take in a YUV input file and encodes it with Netint's HW encoder
through libavcodec. Can set encoding parameters as described in the Codensity T408
Integration & Programming Guide.

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 3.1.1 and above

Usage exmaple:
  sudo ./ni_encode_video -i input.yuv --size 426x240 -r 25 -c h265_ni_quadra_enc -x gopPresetIdx=5:intraPeriod=120:RcEnable=1 -b 100000 -o output.h265
  sudo ./ni_encode_video -s 1920x1080 -r 30 -p rgba -i Dinner_1920x1080p30_15.rgba -c h264_ni_quadra_enc -x "intraPeriod=0:RcEnable=1:bitrate=4000000" -o out_rgba.h264
  sudo ./ni_encode_video -i Dinner_1920x1080p30_300.yuv -s 1920x1080 -r 30 -c h265_ni_quadra_enc -x crfFloat=23 -b 100000 -M 1 -o output.h265
Parameters:
	-s | --size                  Size of input yuv in [width]x[height].
	-x | --xcoder_params         Xcoder parameters. See Integration and Programing Guide for details.
	-i | --input                 Input yuv file.
	-o | --output                Output video file.
	-c | --codec                 Codec name. [h264_ni_quadra_enc, h265_ni_quadra_enc].
	-r | --fps                   FPS of output.
	-b | --bitrate               Bitrate in bits/second.
	-e | --enc                   Encoder device index to use. See ni_rsrc_mon.
	-l | --loop                  Loop read input count.
	-g | --log_level             Log level for messages. [NONE, FATAL, ERROR, INFO, DEBUG, TRACE]
	-h | --help                  Help info.

	Testing intermittent idle of input:
	-w | --inst_restart_count    Number of times to restart encoder instance and re-read input.
	-a | --interval_frame        Number of frames between intervals of test activity.
								 (if 0, use random interval).
	-v | --interval_time         Number of seconds to sleep at each interval_frame.
								 (if 0, random between 1s - 20s).
	-k | --force_key_frame       Flag to force key frame at each interval (must set interval_frame).

	Testing Region of Interest:
	-z | --roi                   Apply demo ROI mode. Options: 1 -> Border ROI, 2 -> Center ROI.

	Testing Bitrate reconfiguration:
	-m | --bitrate_reconfig      Use side data to reconfigure bitrate target throughout video.
								 The --bitrate parameter must be set. Use the format
								 bitrate_min:bitrate_max:bitrate_step:frame_interval to cause target
								 bitrate to sweep in a saw-tooth pattern between bitrate_min and
								 bitrate_max in increments of bitrate_step every frame_interval frames.
	-M | --general_reconfig      Use general side to reconfig such as crf, vbvbuffersize, vbvmaxrate throughout video
								 It will take effect at frame 100 and reconfig the crf to 23 and vbv buffer size to 2500


###
ni_multi_thread_transcoding

This example would start multiple threads specified at once.
In each thread, it opens a decoder AVCodecContext instance, an encoder
AVCodecContext instance and simple source-to-sink FilterContext.
The output file is named "output-%{thread index}".%{mux name} and stored
in output directory specified by parameter. when there is a sequence change,
the encoder would be flushed, closed and re-opened for frames with
the new sequence.

The main thread calculates and prints fps in the front until
there is an ctrl-c interrupt or all the transcoding threads are done.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc, av1_ni_quadra_enc

Support FFmpeg version: 3.4.2 and above

Usage example:
	sudo ./ni_multi_thread_transcoding -x "intraPeriod=120:RcEnable=1" \
	-i /path/to/mp4 -e h264_ni_quadra_enc -d h264_ni_quadra_dec -p "out=hw" -t 8 -s mp4

Note:
	to transcode the video clip in the LGXCOD-2155:
	sudo ./ni_multi_thread_transcoding -r -s flv -i input.flv -d h264 -e h264_ni_quadra_enc -x \
	"RcEnable=1:hvsQPEnable=1:bitrate=670000:gopPresetIdx=8:intraPeriod=0:repeatHeaders=1:GenHdrs=1"

Parameters:
	-x | --encoder-params    encoder parameters.
	-i | --input             input file path.
	-o | --output_dir        output directory path.
	-e | --encoder           encoder name.
	-d | --decoder           decoder name.
	-p | --decoder-params    decoder parameters.
	-t | --threads           number of codec threads.
	-b | --bitrate           bitrate.
	-n | --devid             device id.
	-s | --suffix            file extension of output. Use 'null' for no output.
	-l | --loop              numbers of loop to go.
	-f | --filter            decoded frames passing through filters.
	-r | --repeat-header     force repeating headers for IDR frames.
	-v | --loglevel          available debug level: warning, info, debug, trace.
	-k | --force-keyframe    encode a keyframe whenever input source has a keyframe.
	-c | --rescale-ts        rescale timestamp and timebase to default timebase of file type in --suffix.
	-a | --disable-audio     disable audio streams.
	-h | --help              print this help information.


###
ni_multi_thread_encode_video

This example would start multiple threads specified at once.
In each thread, it creates and opens an AVCodecContext intance,
and runs encoder with YUV files as the input source. The output
file is named "output-%{thread index}".%{codec} and stored in
the directory specified by parameter.

The main thread calculates and prints fps in the front until
there is an ctrl-c interrupt or all the encode threads are done.

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 3.1.1 and above

Usage example:
	sudo ./multi_thread_encode_video -x "intraPeriod=120:RcEnable=1" \
	-i /path/to/YUV -c h264_ni_quadra_enc -p 1920x1080 -d 0 -t 8 -s 100

Parameters:
	-x - NetInt encoder parameters.
	-i - the input file path.
	-o - the output directory.
	-c - encoder name from "ffmpeg -encoders".
	-b - bitrate
	-p - pixels format, must be WidthxHeight.
	-d - for ni encoder, which card to operate on.
	-t - how many threads to create.
	-s - how many encode loops to run.


###
ni_multi_thread_lowdelay_encode

This example would start multiple low delay encode instances 
Each encode instance utilizes a pair of threads 
(input thread + output thread) to simulate real time input 
frequency at specified frames per second.
Also latency is reduced by avoiding frame data copy when possible.
The output file is named "output-<thread index>.<codec>" 
and stored in the directory specified by parameter.

The main thread calculates and prints fps in the front until 
there is an ctrl-C interrupt or all the encode threads are done.

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 3.4.2 and above

Usage example:
  sudo ./ni_multi_thread_lowdelay_encode -x gopPresetIdx=9:RcEnable=1:intraPeriod=120:EnableRdoQuant=0:rdoLevel=1:cuLevelRCEnable=0:lowDelay=1:vbvBufferSize=0:bitrate=16000000:framerate=60 \
  -i /path/to/YUV -c h265_ni_quadra_enc -p 3840x2160 -d 0 -t 4 -s 8

Parameters:
  -p | --pixel            [width]x[height] of yuv
  -x | --xcoder_params    xcoder parameters
  -i | --input_file       input yuv file
  -o | --output_dir       output directory path
  -c | --codec            codec name
  -r | --fps              FPS of input
  -t | --threads          number of threads
  -b | --bitrate          bitrate
  -n | --nsid             namespace id (eg. /dev/nvme0n1)
  -d | --devid            device id (eg. /dev/nvme0)
  -s | --loop             run loop count
  -g | --loglevel         FFmpeg log level. [quiet, panic, fatal, error,
                          warning, info, verbose, debug, trace]
  -R | --fixed_fps        limit processing rate to a fixed FPS
  -m | --mute             do not print periodic performance info"
  -f | --pr_fps           print periodic performance info"
  -y | --sync             sync mode test
  -h | --help             help info


###
ni_tile_encoding

Tile encoding is a feature to accelerate large video stream encoding
with single card. In this feature we separate the original YUV file into
several tiles. Each tile will be encoded in a worker thread in the demo 
code. Each worker thread may be handling one more tile partition(s) 
encoding, depending on the number of worker threads created and the number 
of tile partitions. Currently the tile encoding demo application can 
support at most 36 tile partitions on a single card, please also note 
currently the demo does not support distributing tile partitions encoding 
on multiple cards. 

Encoding parameters of each tile including their resolutions, segment 
address, and bitstream filters will be set. First, we need to extract YUV 
frames from YUV file. Next, we dispatch the frame to the filter thread; the 
filter thread uses ni_quadra_hwupload filter to transfer each frames YUV 
data to Quadra device memory, and then uses ni_quadra_split filter to 
generate multiple references of the frame for multiple encoding instances.
For instance, if we set tiles as 3x3 for a 8K video stream, the parameters 
of AVFilter graph will be as follows:

```
ni_quadra_hwupload=-1,ni_quadra_split=9:0:0[sin_0][sin_1][sin_2][sin_3][sin_4][sin_5][sin_6][sin_7][sin_8] 
```

After filtering, we will dispatch each reference of the frame (which is now 
a representation of the YUV data in device memory) to one of the worker 
threads. Each worker thread sends frame descriptors to encoder and receives 
AVPackets to/from one or more encoding instance(s). For each encoding 
instance, we also setup crop parameters corresponding to the tile partition, 
as shown in the following example: 

```
# encoder parameters for 3x3 tiles for a 8K video stream
gopPresetIdx=1:cropWidth=2560:cropHeight=1408:horOffset=0:verOffset=0
gopPresetIdx=1:cropWidth=2560:cropHeight=1408:horOffset=2560:verOffset=0
gopPresetIdx=1:cropWidth=2560:cropHeight=1408:horOffset=5120:verOffset=0
:
```

The crop parameters would be calculated automatically in demo code. Then 
there are raw-to-tile and tile-repack bitstream filters. The raw-to-tile 
filter will calculate and save the correct tile segment address and sizes. 
The tile-repack filter will generate OBU sequence header, frame header and 
tile group header with the saved tile information, and it will compose 
separating tile packets as one. Finally, we generate a IVF (for AV1) or HEVC 
bitstream as the output. Following are the parameters for raw-to-tile 
bitstream filters:

```
# raw-to-tile bitstream filter for 3x3 tiles for a 8K video stream
av1_rawtotile=width=7680:height=4320:column=3:row=3:x=0:y=0:x_w=2560:y_h=1408
av1_rawtotile=width=7680:height=4320:column=3:row=3:x=2560:y=0:x_w=2560:y_h=1408
av1_rawtotile=width=7680:height=4320:column=3:row=3:x=5120:y=0:x_w=2560:y_h=1408
: 
```

Following are the parameters for tile-repack bitstream filter: 

```
# tile-repack bitstream filter
"av1_tile_repack=tile_num=9"
```
Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc, av1_ni_quadra_enc

Support FFmpeg version: 4.2.1 and above

Usage examples:
AV1
----
        sudo ./ni_tile_encoding -s 7680x4320 -c av1_ni_quadra_enc -o tile_out.ivf -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 2x4 
        sudo ./ni_tile_encoding -s 7680x4320 -c av1_ni_quadra_enc -o tile_out.av1 -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 3x3 
        sudo ./ni_tile_encoding -s 7680x4320 -c av1_ni_quadra_enc -o tile_out.av1 -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 4x4 -j 8 
        sudo ./ni_tile_encoding -s 7680x4320 -c av1_ni_quadra_enc -o tile_out.av1 -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 6x6 # no more than 36 tiles

HEVC
----
        sudo ./ni_tile_encoding -s 7680x4320 -c h265_ni_quadra_enc -o tile_out.hevc -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 2x4
        sudo ./ni_tile_encoding -s 7680x4320 -c h265_ni_quadra_enc -o tile_out.hevc -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 3x3
        sudo ./ni_tile_encoding -s 7680x4320 -c h265_ni_quadra_enc -o tile_out.hevc -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 4x4 -j 8
        sudo ./ni_tile_encoding -s 7680x4320 -c h265_ni_quadra_enc -o tile_out.hevc -i cubes_7680x4320p25_50_br100000_b3__B265d.yuv -t 6x6 # no more than 36 tiles

Parameters:
	-h, --help            help info
	-s, --size            [width]x[height] of YUV
	-p, --pix_fmt         pixel format of YUV
	-x, --xcoder_params   xcoder parameters
	-i, --inputfile       input yuv file
	-o, --output_file     output filename. Use av1 extension for AV1 OBU, ivf for AV1 IVF, hevc for HEVC
	-c, --codec           codec name: av1_ni_quadra_enc for AV1 tile encoding, h265_ni_quadra_enc for HEVC tile encoding
	-t, --tiles           [column]x[row] of tiles
	-j, --threads         number of threads to use, default value is the lesser of (number of processors, number of tiles)
	-b, --bitrate         bitrate
	
	
###
ni_hevc_tile_decoding

The HEVC tile decoder is a new feature to accelerate large video stream decoding
with multi-cards. In this feature we input a tile encoded HEVC stream and it
will calculate the number of tiles in extra-data in AVPacket and allocate the
same number of worker theads for decoding. The AVPacket also need a bitstream
filter called frame-split to re-encode the slice headers to remove tile flags
that the input HEVC stream contains. Then we can decode the YUV frames out.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: NULL

Support FFmpeg version: 4.2.1 and above

Usage example:
	sudo ./ni_hevc_tile_decoding -c h265_ni_quadra_dec -i tile_test.h265 -o out.yuv

Parameters:
	-h, --help	print this help message
	-i, --input	input h264/hevc file.
	-c, --codec	decoder codec name, ie. hevc, h265_ni_quadra_dec
	-o, --output	path to output YUV file

###
ni_hevc_tile_transcoding

The HEVC tile transcoder is a new feature to trasncode both large non-tile AVC
and HEVC stream into HEVC stream in tiles with multi-cards. The decoding
function is single-threading because the input stream does not contain tile
flags in bitstream. And the encoding funtion is similar with `ni_hevc_encoding`
in multi-threading.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 4.2.1 and above

Usage examples:
	sudo ./ni_hevc_tile_transcoding -d h264_ni_quadra_dec -e h265_ni_quadra_enc -o tile_out.h265 -i helium_8192x8192p24_50_b7.h264 -t 1x4 # 4-card
	sudo ./ni_hevc_tile_transcoding -d h264_ni_quadra_dec -e h265_ni_quadra_enc -o tile_out.h265 -i helium_8192x8192p24_50_b7.h264 -t 2x2 # 4-card
	sudo ./ni_hevc_tile_transcoding -d h264_ni_quadra_dec -e h265_ni_quadra_enc -o tile_out.h265 -i helium_8192x8192p24_50_b7.h264 -t 2x4 # 8-card
	sudo ./ni_hevc_tile_transcoding -d h264_ni_quadra_dec -e h265_ni_quadra_enc -o tile_out.h265 -i helium_8192x8192p24_50_b7.h264 -t 1x8 # 8-card

Parameters:
	-h, --help              help info
	-x, --xcoder_params     xcoder parameters
	-i, --inputfile         input yuv file
	-d, --decoder           decoder name
	-e, --encoder           encoder name
	-t, --tiles             [column]x[row] of tiles
	-b, --bitrate           bitrate


###
ni_multiview_tile_encoding

As the name implies, multiview tile encoding application encodes multiple
YUV files (up to 4 inputs in current implementation), converts each
encoded frame to tile, and stitches the tiles together to form the output
bitstream. The output "multiview" bitstream will include multiple video 
sequences on the same screen.

By default, the application creates multiple encoder worker threads for
better efficiency, the number of worker threads is configurable.
Each worker thread may be handling one or more tile partition(s)
encoding, depending on the number of worker threads created and the number
of tile partitions. Currently the multiview tile encoding application can 
support up to 4 inputs (hence 4 tile partitions). Please also note that
currently the application does not support distributing tile partitions 
encoding on multiple cards.

Please also note that HEVC tile width and height need to be CTB aligned, 
and the application can be configured to either pad or crop the input 
videos to 64x64 aligned width and height if the input resolution is not 
naturally aligned.

When the application is configured to pad the input frames, the 
application pipeline is {main thread -> filter thread -> encoder worker 
thread -> repackaging thread}. The main thread reads from the input YUV 
file, the filter thread uploads YUV data to Quadra card and invokes 2D 
engine to perform padding, the encoder worker thread encodes and converts
the encoded frames to tiles, and finally the repackaging thread stitches 
the tiles together and writes to the output multiview bitstream. 

For the filter thread, a sample filter graph is shown below 

```
[0:v]ni_quadra_hwupload=-1,ni_quadra_pad=1920:1088[in_0];[1:v]ni_quadra_hwupload=-1,ni_quadra_pad=1920:1088[in_1];[2:v]ni_quadra_hwupload=-1,ni_quadra_pad=1920:1088[in_2];[3:v]ni_quadra_hwupload=-1,ni_quadra_pad=1920:1088[in_3]
```
For the encoder thread, sample encoding parameters are shown below
(Please note that unlike the hwupload / pad / rawtotile / repack filters 
which are configured by the application automatically, the encoder 
parameters needs to be confgiured by the user via application parameter
`-x`)

```
frameRate=60:frameRateDenom=1:gopPresetIdx=5:motionConstrainedMode=2:lookaheadDepth=10:rcEnable=1:vbvBufferSize=3000
```

Also for the encoder thread, sample rawtotile bitstream filter parameters 
(for tile conversion) are shown below

``
hevc_rawtotile=width=3840:height=2176:column=2:row=2:x=0:y=0
hevc_rawtotile=width=3840:height=2176:column=2:row=2:x=1920:y=0
hevc_rawtotile=width=3840:height=2176:column=2:row=2:x=0:y=1088
hevc_rawtotile=width=3840:height=2176:column=2:row=2:x=1920:y=1088
```
For the repackaging thread, sample tile_repack filter (for repackaging / 
stitching tiles to bitstream) parameters are shown below

```
hevc_tile_repack=tile_num=4
```

When the application is configured to crop the input frames, the 
application pipeline is {main thread -> encoder worker thread -> 
repackaging thread}. Note that filter thread is not required because
Quadra encoder support cropping.

For cropping, sample encoding parameters are shown below
(Please note that the application automatically adds cropping settings to
encoder parameters, and therefore the user does not need to add cropping 
settings in the encoder parameters specified via application parameter 
`-x`)

```
frameRate=60:frameRateDenom=1:gopPresetIdx=5:motionConstrainedMode=2:lookaheadDepth=10:rcEnable=1:vbvBufferSize=3000:cropWidth=1920:cropHeight=1024:horOffset=0:verOffset=0
```

NOTE - Please note encoder parameter motionConstrainedMode needs to
be set to 1 (PERFORMANCE) or 2 (QAULITY) to prevent artifacts in the
output multiview bitstream. For more details about motionConstrainedMode,
please refer to Quadra Integration Programming Guide document

NOTE - Please note that encoder parameters specified by application
parameter `-x` is applied to all inputs. Also, application parameter 
`-s` and `-r` are applied to all inputs, because it is required for all 
inputs to have the same resolution and the same framerate.

NOTE - Please also note that all inputs need to be encoded with the same 
gop pattern and key frame interval; therefore, adaptive gop (default 
gopPresetIdx -1) is not allowed

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 4.2.1 and above

Usage examples:
HEVC with padding
----
        sudo ./ni_multiview_tile_encoding -s 1920x1080 -p yuv420p -c h265_ni_quadra_enc -o quadra.hevc -i 0:input0.yuv -i 1:input1.yuv -i 2:input2.yuv -i 3:input3.yuv -t 2x2 -x frameRate=60:frameRateDenom=1:gopPresetIdx=5:motionConstrainedMode=2:lookaheadDepth=10:rcEnable=1:vbvBufferSize=3000 -r 60 -g -b 4000000 -f

HEVC with cropping
----
        sudo ./ni_multiview_tile_encoding -s 1920x1080 -p yuv420p -c h265_ni_quadra_enc -o quadra.hevc -i 0:input0.yuv -i 1:input1.yuv -i 2:input2.yuv -i 3:input3.yuv -t 2x2 -x frameRate=60:frameRateDenom=1:gopPresetIdx=5:motionConstrainedMode=2:lookaheadDepth=10:rcEnable=1:vbvBufferSize=3000 -r 60 -g -b 4000000

NOTE - Please note application parameter `-i` required format is
[tile index]:[input yuv file], where the tile index is in raster scan 
order, with tile index 0 being the top left tile partition and tile index
3 being the bottom right tile partition

Parameters:
	-h, --help            help info
	-s, --size            [width]x[height] of YUV
	-p, --pix_fmt         pixel format of YUV
	-x, --xcoder_params   xcoder parameters
	-i, --inputfile       [tile index]:[input yuv file] (up to 4 inputs)
	-c, --codec           codec name: h265_ni_quadra_enc for HEVC tile encoding (currently supports HEVC only)
	-o, --output_file     output filename. Use hevc extension for HEVC tile encoding
	-t, --tiles           [column]x[row] of tiles
	-j, --threads         number of threads to use, default value is the lesser of (number of processors, number of tiles)
	-q, --frame_queue_depth         input frame queue depth, default value is 3 (max queue depth is 10)
        -f, --pad_filter      pad input frame to 64x64 aligned instead of cropping input frame
        -v, --verbose         print verbose logs
	-b, --bitrate         bitrate
	-r, --fps             framerate
        -g, --log             output each of the encoded bitstreams before tile conversion
	
	
###
ni_av1_tile_decoding

The AV1 tile decoder is a demo to show how to decode the tiled AV1 stream
generated by Quadra with ni_av1_tile_transcoding when there are P frames in
the output stream. In this demo we input a tile encoded AV1 stream and it
will calculate the number of tiles from extra-data in AVPacket and allocate the
same number of worker theads for decoding. The AVPacket also goes through a
bitstream filter called ni_av1_frame_split to re-encode the headers in the stream
so that each tile can be decoded as a standalone stream. Then we decode each
stream containing just one tile with libaom AV1 decoder to get the YUV output.
Finally the YUV output of all the tiles are assembled together to form the 
complete output frame YUV.

NOTE - this demo uses libaom AV1 decoder so libaom needs to be installed and ffmpeg
needs to be compiled with libaom support to run this demo.

Supported decoder: libaom decoder
Supported encoder: NULL

Support FFmpeg version: 4.2.1 and above

Usage example:
	sudo ./ni_av1_tile_decoding -i tile_test.ivf -o out.yuv

Parameters:
	-h, --help	print this help message
	-i, --input	input tiled hevc file.
	-c, --codec	decoder codec name, ie. hevc, h265_ni_quadra_dec
	-o, --output	path to output YUV file
  -j, --threads   number of threads to use, default value is number of processors


###
ni_2D_engine_application

This example program takes in encoded input, decodes it with a netint HW
decoder, then applies netint HW scaling. Raw frame is output.
Some padding may be automatically inserted by netint HW padding filter
for odd resolution input/output.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec, jpeg_ni_quadra_dec
Supported encoder: NULL

Support FFmpeg version: 3.4.2 and above

Usage example:
  sudo ./ni_2D_engine_application -i Dinner_1920x1080p30_300.h264 -o outbgrp.rgb
  -d h264_ni_quadra_dec -x out=hw -n 0
  -s "ni_quadra_scale=640:360,ni_quadra_pad=640:640:0:0:0x727272,ni_quadra_scale=640:640:format=bgrp,hwdownload,format=bgrp"

  sudo ./ni_2D_engine_application -i Bee_3840x2160p1_1.jpeg -o outrgb.rgb -d jpeg_ni_quadra_dec -x out=hw -n 0 -s "ni_quadra_scale=640:360:format=rgba,ni_quadra_pad=640:384:0:12:black,hwdownload,format=rgba"

Params:
  -x | --decoder-params    decoder parameters
  -i | --input             input file path
  -o | --output_file       output file path
  -d | --decoder           decoder name
  -n | --devid             device id
  -v | --loglevel          ffmpeg log level. [quiet, panic, fatal, error,
                           warning, info, verbose, debug, trace]
  -s | --filter_dsc        filter params,like FFmpeg -vf
  -t | --filetxt           input filetext,the file write many picture path
  -h | --help              print this help information


###
ni_multi_thread_yuv420to444

This example would start multiple threads specified at once.
When the thread is specified to 1, it actually opens 3 thread, 2 decoder threads and one filter
thread 'yuv420to444'.
The output file is named 'output-%{thread index}.yuv' and stored
in output directory specified by parameter.

The filter thread calculates and prints fps in the front until
there is an ctrl-c interrupt or all the threads are done.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec
Supported encoder: NULL

Support FFmpeg version: 3.1.1 and above

Usage example:
    sudo ./ni_multi_thread_yuv420to444 -d h264_ni_quadra_dec -f ~/input0.h264 -s ~/input1.h264 \
    -o ./output/

Note:
   input0 and input1 must encoded with the same encoding parameters after the 'yuv444to420' filter;
   the frame numbers of input0/input1 must be equal;
   if an error or eof occurs on any of the decoding threads, the filter will exits. 

Params:
  -f | --input0            the first input file path.
  -s | --input1            the second input file path.
  -o | --output_dir        output directory path. if not specified, the output will be empty.
  -d | --decoder           decoder name.
  -t | --threads           number of codec threads.
  -n | --devid             device id.
  -v | --loglevel          available debug level: warning, info, debug, trace.
  -h | --help              print this help information.


###
ni_encode_ai_test

This example program takes in yuv420p or bgra input and upload swframes to
hwframes. Then select 1 frame every X frames to do ROI. To visualize the target
of ROI, an overlay image may be applied. Note, the filter must use names 'input'
and 'output'.

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 4.2.1 and above

Usage example:
  sudo ./ni_encode_ai_test -s 1920x1080 -v yvu420p -r 25 -i vidyo4_720p_60fps.yuv \
  -p box_190x290.png -l 190x290 -c h264_ni_quadra_enc -e 0 -x "RcEnable=1:bitrate=2000000" \
  -m 2 -f "[input]ni_quadra_hwupload=0,ni_quadra_roi=nb=./network_binary1.nb:qpoffset=-0.6[output]" \
  -k 1280x720 -o vidyo4_720p60_overlay_roi.h264

Params:
  -s | --src_size              Size of input yuv in [width]x[height]
  -k | --dst_size              Size of output video in [width]x[height]
  -x | --xcoder_params         Xcoder parameters. See Integration and Programing Guide for details
  -i | --input                 Input yuv file
  -o | --output                Output video file
  -c | --encode_name           Codec name [h264_ni_quadra_enc, h265_ni_quadra_enc]
  -r | --fps                   FPS of output
  -b | --bitrate               Bitrate in bits/second
  -e | --enc                   Encoder device index to use. See ni_rsrc_mon
  -f | --filter_dsc            Use filter. This must use name 'input' and 'output'
  -m | --select_frame          frame period to re-acquire target for overlay and ROI
  -p | --picture_name          Picture name. Use it to overlay
  -l | --picture_size          Picture size in [width]x[height]
  -v | --input_format          Input_format. (eg. bgra, yuv420p)
  -g | --log_level             Log level for messages [NONE, FATAL, ERROR, INFO, DEBUG, TRACE]
  -h | --help                  Help info


###
ni_transcode_ai_test

This example program takes in encoded input, decodes it with a netint HW
decoder, then applies netint HW scaling. Select 1 frame every X frames to
do ROI.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 4.2.1 and above

Usage example:
  sudo ./ni_transcode_ai_test -d h264_ni_quadra_dec -x "out=hw" -i vidyo4_720p_60fps.h264 \
  -f "ni_quadra_roi=nb=./network_binary.nb:qpoffset=-0.6" -m 30 \
  -e h264_ni_quadra_enc -n 0 -p "roiEnable=1:RcEnable=1:bitrate=2000000" \
  -o vidyo4_720p60_roi.h264

Params:
  -x | --decoder-params    decoder parameters
  -i | --input             input file path
  -o | --output_file       output file path
  -d | --decoder           decoder name
  -n | --devid             device id
  -v | --loglevel          available debug level: warning, info, debug, trace
  -f | --filter_dsc        filter set params
  -b | --bitrate           set bitrate
  -m | --select_frame      frame period to re-acquire target for ROI
  -e | --encode-name       encode name
  -p | --encode_params     encode params
  -h | --help              print this help information


###
ni_multi_encode_scale

The sample program receives bgra input, uploads swframes to 2D engine, 
and performs multi-resolution conversion coding.

Supported decoder: NULL
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 3.4.2 and above

Usage exmaple:
  sudo ./ni_multi_encode_scale -s 1920x1080 -i Dinner_1920x1080p30_300bgra.rgb \
  -o outdem2 -c h264_ni_quadra_enc -r 25 -e 0 -x "RcEnable=1:bitrate=1024000" -b 1024000\
  -k 1920x1080 -k 1280x720  -k 960x640 -t 3

Params:
  -s | --src_size              Size of input bgra in [width]x[height]
  -k | --dst_size              Size of output video in [width]x[height]
  -x | --xcoder_params         Xcoder parameters. See Integration and Programing Guide for details
  -i | --input                 Input bgra file
  -o | --output                Output video file
  -c | --codec                 Codec name.
  -r | --fps                   FPS of output
  -b | --bitrate               Bitrate in bits/second
  -e | --enc                   Encoder device index to use. See ni_rsrc_mon
  -t | --threads               threads number
  -g | --log_level             available debug level: warning, info, debug, trace
  -h | --help                  Help info


###
ni_xstack

This example application is used to demonstrate performant ni_xstack filter implementation.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 4.1.3 and above

Usage exmaple:
#for 2x2 inputs and single output
  sudo ./ni_xstack -i input/clip5.mp4 -d h264_ni_quadra_dec -i input/clip10.mp4 -d h264_ni_quadra_dec \
  -i input/clip15.mp4 -d h264_ni_quadra_dec -i input/clip20.mp4 -d h264_ni_quadra_dec -e h264_ni_quadra_enc \
  -f "inputs=4:layout=0_0|w0_0|0_h0|w0_h0:size=540_360|540_360|540_360|540_360" -o 2x2_ni_xstack.h264

#for 4x4 inputs and multiple outputs
  sudo ./ni_xstack -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw" \
  -f "inputs=16:layout=0_0|0_h0|0_h0+h1|0_h0+h1+h2|w0_0|w0_h0|w0_h0+h1|w0_h0+h1+h2|w0+w1_0|w0+w1_h0|w0+w1_h0+h1|w0+w1_h0+h1+h2|w0+w1+w2_0|w0+w1+w2_h0|w0+w1+w2_h0+h1|w0+w1+w2_h0+h1+h2:\
  size=960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540:fill=BLACK:shortest=1:keep_alive_timeout=10" \
  -e h264_ni_quadra_enc -o 4K.h264 -o 1080p.h264 -s 1920x1080 -o 720p.h264 -s 1280x720 -o 540p.h264 -s 960x540

#for PIP (Picture-in-Picture) with timestamp
  sudo ./ni_xstack -i 1080p.h264 -d h264_ni_quadra_dec \
              -i 720p.h264 -d h264_ni_quadra_dec \
              -i 360p.h264 -d h264_ni_quadra_dec \
              -i 540p.h264 -d h264_ni_quadra_dec \
              -i 720p.h264 -d h264_ni_quadra_dec \
              -i 360p.h264 -d h264_ni_quadra_dec \
              -i 540p.h264 -d h264_ni_quadra_dec \
  -e h264_ni_quadra_enc \
  -f "inputs=7:layout=0_0|1660_40|1660_166|1660_292|1660_418|1660_544|1660_670:size=1920_1080|224_126|224_126|224_126|224_126|224_126|224_126" \
  -t "font=Sans:fontcolor=Red:fontsize=36:text='%{pts\:localtime\:1456007118}':x=100:y=100" -s 1280x720 -o PIP-720p-text.h264

#for image overlay onto stream
  sudo ./ni_xstack -i 1080p.h264 -d h264_ni_quadra_dec \
  -I logo1.jpg \
  -I logo2.bmp \
  -I logo3.png \
  -e h264_ni_quadra_enc \
  -f "inputs=4:layout=0_0|100_40|300_200|500_300:size=1920_1080|224_126|200_100|200_100:shortest=1" \
  -s 1280x720 -o stream_image_overlay.h264

#for multiple filter with different description
 sudo ./ni_xstack -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw:scale0=1920x1080" -i input/test1.h264 -d h264_ni_quadra_dec \
 -p "out=hw:scale0=540x360" -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw:scale0=540x360" -e h264_ni_quadra_enc \
 -f "inputs=3:layout=0_0|100_100|640_100:size=1920_1080|540_360|540_360:fill=BLACK:shortest=1:keep_alive_timeout=10" -o out0.h264 \
 -f "inputs=3:layout=0_0|100_100|100_460:size=1920_1080|540_360|540_360:fill=BLACK:shortest=1:keep_alive_timeout=10" -o out1.h264

#for image, yuv input onto stream with multiple filter that have different description
 sudo ./ni_xstack -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw:scale0=540x360" -i input/test1.yuv -S 1920x1080 -P 540x360\
 -i input/test1.png -P 540x360 -e h264_ni_quadra_enc \
 -f "inputs=3:layout=0_0|0_h0|w0_0:size=540_360|540_360|540_360:fill=BLACK:shortest=1:keep_alive_timeout=10" -o out0.h264 \
 -f "inputs=3:layout=0_0|w0_0|w0_h0:size=540_360|540_360|540_360:fill=BLACK:shortest=1:keep_alive_timeout=10" -o out1.h264

#for pad after xstack
  sudo ./ni_xstack -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw:scale0=540x360" -i input/test1.h264 -d h264_ni_quadra_dec \
  -p "out=hw:scale0=540x360" -f "inputs=3:layout=0_0|0_h0:size=540_360|540_360:fill=BLACK:shortest=1:keep_alive_timeout=10" \
  -F 1920:1080:0:0:0x000000

Params:
-i | --input                    input video file name.
-I | --input_image              input image file name.
-d | --decoder                  decoder name.
-p | --decoder-params           decoder parameters (applicable to all decoders).
-S | --input-res                only for yuv input, yuv resolution, must set fot yuv input.
-P | --scale-res                for sw input like yuv and picture , scaled resolution, if use default, 
                                it will not do scale in most situation.
-l | --loop                     number of input cycles.
-e | --encoder                  encoder name.
-x | --encoder-params           encoder parameters (applicable to all encoders).
-o | --output                   output file name.
-s | --resolution               output file resolution, in the format of Width x Height, -s is optional,
                                and if present, is associated with the output file name preceding it.
-t | --text                     ni_quadra_drawtext filter description.
-F | --pad                      ni_quadra_pad filter description
-n | --devid                    device id.
-f | --filter                   ni_quadra_xstack filter description.
-v | --loglevel                 available debug level: warning, info, debug, trace.
-h | --help                     print this help information.

###
ni_transcode_filter

This example is used to do transcode and one input and one output filter
supported filter: ni_quadra_scale, ni_quadra_overlay, ni_quadra_crop, ni_quadra_pad, ni_quadra_roi, ni_quadra_bg
                  ni_quadra_rotate, ni_quadra_drawbox, ni_quadra_drawtext

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc, av1_ni_quadra_enc

Support FFmpeg version: 3.4.2 and above

Usage example
 sudo ./ni_transcode_filter -i Dinner.h264 -o output.h264 -d h264_ni_quadra_dec -p "out=hw" -e h264_ni_quadra_enc \
 -x "RcEnable=1:bitrate=1024000" -b 1024000 -n 0 -f "movie=input/a.png,ni_quadra_hwupload=0[watermask];[in][watermask]ni_quadra_overlay=0:0[text];\
 [text]ni_quadra_drawtext=font=Sans:fontcolor=Red:fontsize=36:text=hello:x=100:y=100" 

 sudo ./ni_transcode_filter -i Dinner.h264 -o output.h264 -d h264_ni_quadra_dec -p "out=hw" -e h264_ni_quadra_enc \
 -n 0 -f "ni_quadra_drawtext=font=Sans:fontcolor=Red:fontsize=36:text=test:x=100:y=100" -x "RcEnable=1:bitrate=1024000" \
 -m 100 -s "text=hello:x=200:y=200:t1=hi:x1=300:y1=300"

Params:
-i | --input             input file path.
-d | --decoder           decoder name.
-p | --decoder_params    decoder parameters.
-o | --output_file       output file path.
-e | --encoder           encoder name.
-x | --encode_params     encoder parameters.
-f | --filter_desc       filter description.
-m | --reconf_num        the frame num reconfig happen.
-s | --reconfig_desc     reconfig filter description.
-b | --bitrate           set bitrate.
-n | --devid             device id.
-v | --loglevel          available debug level: warning, info, debug, trace.
-h | --help              print this help information.

###
ni_ppu_split

This example is used to do ppu and split

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc

Support FFmpeg version: 3.4.2 and above

Usage example
 sudo ./ni_ppu_split -d h264_ni_quadra_dec -p "out=hw:scale0=1280x720:enableOut1=1:scale1=854x480" -i Dinner.h264 \
 -f 'ni_quadra_split=1:1:0' -e h265_ni_quadra_enc -x "RcEnable=1:bitrate=10000000" -o out1.h265 -e h265_ni_quadra_enc \
 -x "RcEnable=1:bitrate=4000000" -o out2.h265

Params:
-i | --input             input file path.
-d | --decoder           decoder name.
-p | --decoder_params    decoder parameters.
-o | --output_file       output file path.
-e | --encoder           encoder name.
-x | --encode_params     encoder parameters.
-f | --filter_desc       filter description.
-n | --devid             device id.
-v | --loglevel          available debug level: warning, info, debug, trace.
-h | --help              print this help information.

###
ni_live_xstack

This example application is used to demonstrate ni_xstack filter implementation.

Supported decoder: h264_ni_quadra_dec, h265_ni_quadra_dec, vp9_ni_quadra_dec
Supported encoder: h264_ni_quadra_enc, h265_ni_quadra_enc, av1_ni_quadra_enc

Support FFmpeg version: 4.1.3 and above

Usage exmaple:
#for 2x2 inputs and single output
  sudo ./ni_live_xstack -i input/clip5.mp4 -d h264_ni_quadra_dec -i input/clip10.mp4 -d h264_ni_quadra_dec \
  -i input/clip15.mp4 -d h264_ni_quadra_dec -i input/clip20.mp4 -d h264_ni_quadra_dec -e h264_ni_quadra_enc \
  -f "[0:v][1:v][2:v][3:v]ni_quadra_xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0:size=540_360|540_360|540_360|540_360" -o 2x2_ni_xstack.h264

#for 4x4 inputs and multiple outputs
  sudo ./ni_live_xstack -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec \
  -i input/test1.h264 -d h264_ni_quadra_dec -i input/test1.h264 -d h264_ni_quadra_dec -p "out=hw" \
  -f "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v]ni_quadra_xstack=inputs=16:\
  layout=0_0|0_h0|0_h0+h1|0_h0+h1+h2|w0_0|w0_h0|w0_h0+h1|w0_h0+h1+h2|w0+w1_0|w0+w1_h0|w0+w1_h0+h1|w0+w1_h0+h1+h2|w0+w1+w2_0|w0+w1+w2_h0|w0+w1+w2_h0+h1|w0+w1+w2_h0+h1+h2:\
  size=960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540|960_540:fill=BLACK:shortest=1:keep_alive_timeout=10[in];\
  [in]ni_quadra_split=4:0:0[out0][in1][in2][in3];[in1]ni_quadra_scale=1920x1080[out1];[in2]ni_quadra_scale=1280x720[out2];[in3]ni_quadra_scale=960x540[out3]" \
  -e h264_ni_quadra_enc -o 4K.h264 -o 1080p.h264 -o 720p.h264 -o 540p.h264

#for image overlay onto stream
  sudo ./ni_live_xstack -i Dinner.h264 -d h264_ni_quadra_dec -i timestamp2.mkv -d h264_ni_quadra_dec -I Fallen_Leaves.jpeg -e h264_ni_quadra_enc \
  -f "[0:v][1:v][2:v]ni_quadra_xstack=inputs=3:layout=0_0|w0_0|270_360:size=540_360|540_360|540_360:fill=BLACK:shortest=0:keep_alive_timeout=10[in];\
  [in]ni_quadra_split=2:0:0[out0][in1];[in1]ni_quadra_scale=1280x720[out1]" -o out1.h264 -o out2.h264

#for live stream input and output 
 sudo ./ni_live_xstack -i rtsp://av_stream -d h265_ni_quadra_dec -i Dinner.flv -d h264_ni_quadra_dec \
 -I Fallen_Leaves.jpeg -e h264_ni_quadra_enc -f "[0:v][1:v][2:v]ni_quadra_xstack=inputs=3:layout=0_0|w0_0|270_360:size=540_360|540_360|540_360:fill=BLACK:\
 shortest=0:keep_alive_timeout=10[in];[in]ni_quadra_split=2:0:0[out0][in1];[in1]ni_quadra_scale=1280x720[out1]" -o rtmp://10.20.131.147:1935/live/test \
 -o rtmp://10.20.131.147:1935/live/test2
  
Params:
-i | --input                    input video file name.
-I | --input_image              input image file name.
-d | --decoder                  decoder name.
-p | --decoder-params           decoder parameters.
-S | --input-res                only for yuv input, yuv resolution, must set fot yuv input
-s | --scale-res                for sw input like yuv and picture , scaled resolution, if use default,  it will not do scale in most situation
-l | --loop                     number of input cycles for yuv input.
-e | --encoder                  encoder name.
-x | --encoder-params           encoder parameters.
-o | --output                   output file name.
-f | --filter                   ni_quadra_xstack filter description.
-n | --devid                    device id.
-v | --loglevel                 available debug level: warning, info, debug, trace.
-h | --help                     print this help information.