Skip to content

Coming from NVIDIA DeepStream

DeepStream and this framework are both GStreamer pipelines with a metadata model. The main differences: inference runs through MIGraphX on AMD GPUs instead of TensorRT; frames live in VA surfaces (memory:VAMemory) instead of NVMM; and per-model settings are a small JSON file (model-info) instead of a config_infer_*.txt.

Element map

DeepStream This framework Notes
nvv4l2decoder vah264dec / vah265dec / vaav1dec Output video/x-raw(memory:VAMemory),format=NV12
nvstreammux gvastreammux output-mode=container, or independent branches with a shared model-instance-id Container mode keeps each source's resolution; there is no width/height rescale to a common batch size.
nvinfer (primary) amddetect / amdinference
nvinfer (secondary, process-mode=2) amdclassify inference-region=roi-list classifies boxes from the upstream detector (up to 300)
nvtracker gvatrack tracking-type=short-term-imageless NvDCF, IOU and DeepSORT low-level libraries are not available. An image-free IOU/Kalman tracker only.
nvdsosd amdwatermark Boxes, labels, track IDs, masks, COCO-17 skeletons on the GPU
nvvideoconvert none needed; vapostproc for explicit format/scale amd* elements take NV12 VAMemory directly
nvmsgconv + nvmsgbroker amdmetapublish (MQTT, Kafka, file) Different JSON schema; see metadata. AMQP, Azure IoT and Redis are not provided.
nvdsanalytics (ROI, line crossing, direction) not provided Implement on the metadata in amdpython or a probe.
nvdspreprocess built into the inference elements VA video processor crop/scale + HIP normalization
nvv4l2h264enc / nvv4l2h265enc amdencode See encoding and serving
nvstreamdemux gvastreamdemux
nvdsmetamux, nvof, nvdspostprocess not provided

nvinfer configuration

config_infer_*.txt / property Here
onnx-file, model-engine-file model = .mxr from amdva-compile-model model.onnx model.mxr. TensorRT engines cannot be imported.
net-scale-factor, offsets input.scale, input.mean (offset * scale) in model-info
model-color-format input.channel_order
maintain-aspect-ratio, symmetric-padding input.letterbox (symmetric padding is what letterbox does)
infer-dims input.shape
num-detected-classes, labelfile-path output.num_classes, labels
network-type (0 detector, 1 classifier, 2 segmentation) task_type and element choice
batch-size element batch-size = compiled batch (--batch)
interval (frames skipped) inference-interval (infer every Nth frame): interval=2 becomes inference-interval=3
gie-unique-id, operate-on-gie-id pipeline order; model-instance-id only shares one executor
operate-on-class-ids, filter-out-class-ids not available; filter in a callback
pre-cluster-threshold, nms-iou-threshold, cluster-mode confidence-threshold, nms-threshold (NMS only)
parse-bbox-func-name, custom-lib-path not available. Adapters: yolov8, yolov8-seg, yolov8-pose, classification, semantic segmentation, raw tensors
network-mode (FP32/FP16/INT8) amdva-compile-model --precision=fp16|fp32; no INT8 path
output-tensor-meta task_type=raw keeps output tensors on the GPU in AmdAnalysisMeta
tensor-meta-pool-size, workspace-size none

Example, DeepStream:

gst-launch-1.0 uridecodebin uri=file:///in.mp4 ! m.sink_0 \
  nvstreammux name=m batch-size=1 width=1920 height=1080 ! \
  nvinfer config-file-path=config_infer_primary.txt ! \
  nvtracker ll-lib-file=libnvds_nvmultiobjecttracker.so ll-config-file=tracker.yml ! \
  nvvideoconvert ! nvdsosd ! nvvideoconvert ! nvv4l2h264enc ! h264parse ! mp4mux ! filesink location=out.mp4

This framework:

gst-launch-1.0 -e filesrc location=in.h264 ! h264parse ! vah264dec ! \
  'video/x-raw(memory:VAMemory),format=NV12' ! \
  amddetect model=model.mxr model-info=model-info.json batch-size=1 ! \
  gvatrack tracking-type=short-term-imageless ! \
  amdwatermark ! amdencode bitrate=6000 ! h264parse ! mp4mux ! filesink location=out.mp4

There is no nvvideoconvert because nothing leaves the GPU in between.

Batching and multiple streams

DeepStream batches by pushing every source into nvstreammux. Here, give every branch an inference element with the same model-instance-id, the same model and the same batch-size; the shared executor assembles one batch per batch-timeout (default 20 ms) from all branches, one request per source per batch, padding partial batches on the GPU. For sources of different resolutions use gvastreammux output-mode=container ! amddetect ! gvastreamdemux and give every demux branch its own queue. See examples/pipelines/multistream-encode.sh.

batched-push-timeout and live-source have no direct property; for live RTSP sources do not set max-fps on the mux.

Metadata

DeepStream Here
NvDsBatchMeta, NvDsFrameMeta one buffer per frame; frame identity (source, generation, sequence, PTS) in AmdAnalysisMeta
NvDsObjectMeta (rect_params, confidence, class_id, object_id) GstAnalyticsODMtd (box, score, label quark) related to a GstAnalyticsTrackingMtd
classifier meta GstAnalyticsClsMtd related to the parent object
mask / segmentation meta GPU tensors in AmdAnalysisMeta
NvDsUserMeta tensor output task_type=raw, tensors stay on the GPU
pyds probes amdpython (frame_dict, read-only metadata) or a C++ pad probe
pyds.get_nvds_buf_surface (pixel access) not available by design; use the C++ GPU APIs

Memory

DeepStream Here
video/x-raw(memory:NVMM) video/x-raw(memory:VAMemory) (decoder, inference, encoder)
nvbuf-memory-type none
CUDA unified memory HIP device buffers owned by the model executor; VA surfaces imported into HIP via DMA-BUF

The AMD inference elements only accept NV12 VAMemory (or a gvastreammux container of it) and default to require-zero-copy=true, so caps negotiation fails instead of silently copying system-memory frames.

Not provided

INT8 calibration, TensorRT engine import, nvinferserver/Triton, NvDCF and DeepSORT trackers, ReID tracker features, nvdsanalytics, custom bounding-box parsers, audio and Smart Record. Person ReID and semantic search exist in the NVR sample, not as framework elements.