Assume you have a Jetson app with a custom detector and a TensorRT
.engine. This is the migration case most Jetson teams actually care about:
Best practice: recover the source model and rebuild the deployment artifact for Qualcomm instead of treating the TensorRT engine as portable.For this post, assume the running case study: a custom YOLO face detector used inside a Jetson smart-camera app. On Jetson, it may run through PyTorch, Ultralytics, TensorRT, or DeepStream. On Dragonwing, we will rebuild the deployment path through ONNX, QAIRT/QNN, quantization, a context binary, and app-side postprocessing. Before you start:
The migration path
A practical custom model migration is a set of gates, not one magic conversion command:Step 0: inventory what you have
Start by separating portable source artifacts from Jetson-specific deployment artifacts. Useful artifacts:Step 1: recover and export the source model
For a YOLO detector, start from the training checkpoint:
Shortest rule: make PyTorch and ONNX Runtime match first. QNN cannot fix a bad ONNX export.
Step 2: check AI Hub first
Before building a custom conversion pipeline, check whether your model architecture already exists in AI Hub. For YOLO-style models:Step 3: convert ONNX to a Qualcomm artifact
Qualcomm QAIRT/QNN conversion is not the same shape astrtexec.
Jetson often feels like one build step:
qnn-onnx-converter followed by qnn-model-lib-generator. AI Hub and some SDK flows may hand you a DLC instead. Use the flow that matches your SDK release, and verify exact flags with --help.
Local QNN model-library flow:
Step 4: handle unsupported operators
This is the point where the Qualcomm onboarding gap can become visible. Do not hide it behind a generic “debug the converter” instruction. Record the operator, graph location, affected backend, and fallback cost; then use this order: If the converter rejects an operator, use this order:
For
Z1_UNCLASSIFIED, the safest path is to save logs, model, inputs, outputs, and tool versions before escalating. This preserves evidence for the real fix.
Step 5: quantize with real calibration data
If you want efficient HTP/NPU execution, quantization is central. A TensorRT calibration cache is not useful here. It is TensorRT-specific. Recalibrate for Qualcomm. For a YOLO face detector, use real images from the target environment:--input_list calibration_input_list.txt to qnn-onnx-converter, then compiling the generated graph with qnn-model-lib-generator:
libQnnModelDlc.so.
Important gotcha from the current docs:
If accuracy drops, use a retry ladder instead of random flag changes:a8w16is not a valid HTP mode. Usea8w8,a16w8,a16w16, orfp16.
Use the first strategy that passes your accuracy SLA.
Step 6: build the context binary
A QNN context binary is the target deployment artifact for this path. Resolve the target SoC first:dsp_arch, VTCM, and other backend options from the SDK examples for your exact model and target; do not copy tuning values across SoCs without validating them. In published commands, include the tested context_config.json or point readers to the exact SDK sample config used for that board.
Build the context binary:
--model libQnnModelDlc.so --dlc_path out/best_a8w8.dlc, with the same backend and config.
Expected output:
Step 7: deploy the runtime bundle
A deployment is not just the model file. It also needs compatible runtime libraries and config. At minimum, expect a bundle like this:scp for Linux targets. Reserve adb push for Android targets.
Step 8: run inference on device
On the device:backend_ext.json minimal:
backend_extensions. Start from the matching SDK example and add settings incrementally.
Step 9: validate against the right baseline
Always compare against the ONNX Runtime FP32 golden baseline, not TensorRT FP16. Why? TensorRT output already includes NVIDIA-specific graph transformations and precision behavior. The neutral reference is the source model export. Suggested validation gates:
A tiny comparison helper:
Step 10: move YOLO postprocessing into the app
Jetson Python examples often hide YOLO decode and NMS behind Ultralytics. Once you export and deploy, you may receive raw tensors. Make postprocessing explicit:Step 11: benchmark only after functional validation
First prove HTP works:
Capture memory delta, not just raw peak:
Benchmark plan for the YOLO migration
Use the same input clip, preprocessing contract, postprocessing thresholds, and accuracy set on both devices. Capture this matrix before making platform claims:
If you cite external benchmark numbers, label them as source-document references and keep them separate from your own device results. The benchmark method matters more than a borrowed headline number.

