fix(client): prove hardware encoder availability

This commit is contained in:
Brad Stein 2026-08-12 11:47:19 -03:00
parent 75df8c94e1
commit 164ef497f0
12 changed files with 204 additions and 74 deletions

6
Cargo.lock generated
View File

@ -1658,7 +1658,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "lesavka_client"
version = "0.27.7"
version = "0.27.8"
dependencies = [
"anyhow",
"async-stream",
@ -1692,7 +1692,7 @@ dependencies = [
[[package]]
name = "lesavka_common"
version = "0.27.7"
version = "0.27.8"
dependencies = [
"anyhow",
"base64",
@ -1704,7 +1704,7 @@ dependencies = [
[[package]]
name = "lesavka_server"
version = "0.27.7"
version = "0.27.8"
dependencies = [
"anyhow",
"base64",

View File

@ -4,7 +4,7 @@ path = "src/main.rs"
[package]
name = "lesavka_client"
version = "0.27.7"
version = "0.27.8"
edition = "2024"
[dependencies]

View File

@ -55,7 +55,7 @@ impl CameraCapture {
if buildable_encoder("vah264enc") {
return Ok((
"vah264enc",
supported_encoder_property("vah264enc", &["keyframe-period"]),
supported_encoder_property("vah264enc", &["key-int-max", "keyframe-period"]),
));
}
if buildable_encoder("vaapih264enc") {
@ -110,7 +110,7 @@ impl CameraCapture {
"nvautogpuh265enc",
&["iframeinterval", "idrinterval", "gop-size"][..],
),
("vah265enc", &["keyframe-period"][..]),
("vah265enc", &["key-int-max", "keyframe-period"][..]),
("vaapih265enc", &["keyframe-period"][..]),
("v4l2h265enc", &["idrcount"][..]),
] {
@ -157,8 +157,30 @@ impl CameraCapture {
#[cfg(not(coverage))]
fn ffmpeg_hevc_nvenc_available() -> bool {
if !Path::new("/dev/nvidiactl").exists() {
return false;
}
Command::new("ffmpeg")
.args(["-hide_banner", "-loglevel", "error", "-h", "encoder=hevc_nvenc"])
.args([
"-hide_banner",
"-loglevel",
"error",
"-f",
"lavfi",
"-i",
"color=c=black:s=128x128:r=1",
"-frames:v",
"1",
"-an",
"-pix_fmt",
"nv12",
"-c:v",
"hevc_nvenc",
"-f",
"null",
"-",
])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()

View File

@ -186,7 +186,7 @@ fn coverage_h264_encoder_choice_honors_stable_test_overrides() {
("nvh264enc", ("nvh264enc", None)),
("nvautogpuh264enc", ("nvautogpuh264enc", None)),
("vulkanh264enc", ("vulkanh264enc", Some("idr-period"))),
("vah264enc", ("vah264enc", Some("keyframe-period"))),
("vah264enc", ("vah264enc", Some("key-int-max"))),
("vaapih264enc", ("vaapih264enc", Some("keyframe-period"))),
("v4l2h264enc", ("v4l2h264enc", Some("idrcount"))),
("unknown", ("x264enc", Some("key-int-max"))),

View File

@ -1,6 +1,6 @@
[package]
name = "lesavka_common"
version = "0.27.7"
version = "0.27.8"
edition = "2024"
build = "build.rs"

View File

@ -293,6 +293,17 @@ gadget has successfully queued a verified frame. The honest long-term answer is
to retain a small Linux verification host in the lab when possible; otherwise
the calibrated server telemetry is the available integrity contract.
### The `0.27.8` Proof Candidate
End-to-end preparation exposed a separate client hardware-selection defect:
FFmpeg advertising `hevc_nvenc` did not prove that CUDA could encode a frame.
On the operator workstation the NVIDIA device was unavailable while the Intel
VA-API HEVC/H.264 route was healthy. Release 0.27.8 runtime-probes NVENC before
selection, falls back to the working GStreamer hardware encoder, and uses the
modern `key-int-max` property for `vah264enc` and `vah265enc`. The hardware
smoke harness now exercises the same usable route and retains encoded streams
plus hardware-decoded proof frames.
## 7. The Current Downstream Video Failure
The current blank downstream feeds fail before transport or decoding.
@ -356,7 +367,7 @@ The safe completion sequence for this incident is:
6. Run `scripts/install/server.sh` as the trusted deployment path. Preserve the
already-attached USB gadget unless a controlled rebuild is explicitly
required.
7. Confirm Theia reports server version `0.27.7`, the pushed release revision,
7. Confirm Theia reports server version `0.27.8`, the pushed release revision,
direct MJPEG normalizer timeout `0`, and a coherent UVC contract.
8. Open both downstream RPCs and prove that each emits changing, decodable H.264
frames.
@ -374,7 +385,7 @@ hardware contract is repeatable. The remaining work falls into five groups.
### A. Install And Version Parity
- Push and deploy `0.27.7` through the client/server install scripts.
- Push and deploy `0.27.8` through the client/server install scripts.
- Confirm client/server version and revision in every hardware probe artifact.
- Eliminate the current state where a fixed client talks to an unfixed server.
@ -440,6 +451,6 @@ host repair:
9. disconnect/reconnect and device changes recover without stale media; and
10. diagnostics identify the failed physical stage when any item breaks.
Until that sequence passes on the installed `0.27.7` client/server pair, the
Until that sequence passes on the installed `0.27.8` client/server pair, the
current release should be described as a validated code correction awaiting
hardware deployment and end-to-end acceptance, not as a completed product fix.

View File

@ -147,6 +147,14 @@ first_available_gst_element() {
return 1
}
ffmpeg_hevc_nvenc_usable() {
[[ -e /dev/nvidiactl ]] || return 1
run_as_user ffmpeg -hide_banner -loglevel error \
-f lavfi -i color=c=black:s=128x128:r=1 \
-frames:v 1 -an -pix_fmt nv12 -c:v hevc_nvenc -f null - \
>/dev/null 2>&1
}
report_client_media_acceleration() {
log "1f. Inspecting client media acceleration routes"
@ -166,8 +174,7 @@ report_client_media_acceleration() {
vah265enc \
vaapih265enc \
v4l2h265enc || true)
if command -v ffmpeg >/dev/null 2>&1 \
&& ffmpeg -hide_banner -loglevel error -h encoder=hevc_nvenc >/dev/null 2>&1; then
if command -v ffmpeg >/dev/null 2>&1 && ffmpeg_hevc_nvenc_usable; then
ffmpeg_hevc_encoder="hevc_nvenc"
fi
h264_encoder=$(first_available_gst_element \
@ -209,7 +216,7 @@ report_client_media_acceleration() {
if gst-inspect-1.0 nvcodec 2>&1 | grep -q 'Unable to initialize CUDA library'; then
echo "⚠️ NVIDIA nvcodec is installed but CUDA initialization failed; NVENC HEVC is unavailable to GStreamer."
if [[ -n $ffmpeg_hevc_encoder ]]; then
echo " FFmpeg hevc_nvenc is available and will be used for HEVC upstream hardware encode."
echo " FFmpeg hevc_nvenc encoded a probe frame and will be used for HEVC upstream hardware encode."
else
echo " Install a working NVENC/VAAPI/V4L2 HEVC route before enabling HEVC upstream."
fi

View File

@ -10,10 +10,10 @@ RESULTS_TSV="${ARTIFACT_DIR}/results.tsv"
SUMMARY_JSON="${ARTIFACT_DIR}/summary.json"
SUMMARY_TXT="${ARTIFACT_DIR}/summary.txt"
UPSTREAM_HEVC_FILE="${ARTIFACT_DIR}/upstream-hevc-nvenc.hevc"
UPSTREAM_HEVC_FRAME="${ARTIFACT_DIR}/upstream-hevc-cuda-frame.png"
DOWNSTREAM_H264_FILE="${ARTIFACT_DIR}/downstream-h264-nvenc.h264"
DOWNSTREAM_H264_FRAME="${ARTIFACT_DIR}/downstream-h264-cuda-frame.png"
UPSTREAM_HEVC_FILE="${ARTIFACT_DIR}/upstream-hevc-hardware.hevc"
UPSTREAM_HEVC_FRAME="${ARTIFACT_DIR}/upstream-hevc-hardware-frame.png"
DOWNSTREAM_H264_FILE="${ARTIFACT_DIR}/downstream-h264-hardware.h264"
DOWNSTREAM_H264_FRAME="${ARTIFACT_DIR}/downstream-h264-hardware-frame.png"
AUDIO_WAV="${ARTIFACT_DIR}/audio-aac-roundtrip.wav"
AUDIO_RMS_JSON="${ARTIFACT_DIR}/audio-aac-roundtrip-rms.json"
SMOKE_WIDTH="${LESAVKA_HARDWARE_SMOKE_WIDTH:-1280}"
@ -57,10 +57,13 @@ ffmpeg_has_encoder() {
| awk -v codec="${codec}" '$2 == codec { found = 1 } END { exit found ? 0 : 1 }'
}
ffmpeg_has_decoder() {
local codec="$1"
ffmpeg -hide_banner -decoders 2>/dev/null \
| awk -v codec="${codec}" '$2 == codec { found = 1 } END { exit found ? 0 : 1 }'
ffmpeg_nvenc_usable() {
local encoder="$1"
[[ -e /dev/nvidiactl ]] || return 1
ffmpeg -hide_banner -loglevel error -nostdin \
-f lavfi -i color=c=black:s=128x128:r=1 \
-frames:v 1 -an -pix_fmt nv12 -c:v "${encoder}" -f null - \
>/dev/null 2>&1
}
run_logged() {
@ -108,9 +111,9 @@ summary_txt = pathlib.Path(sys.argv[3])
artifact_dir = pathlib.Path(sys.argv[4])
artifact_paths = {
"upstream_hevc_stream": sys.argv[5],
"upstream_hevc_cuda_frame": sys.argv[6],
"upstream_hevc_hardware_frame": sys.argv[6],
"downstream_h264_stream": sys.argv[7],
"downstream_h264_cuda_frame": sys.argv[8],
"downstream_h264_hardware_frame": sys.argv[8],
"audio_aac_roundtrip_wav": sys.argv[9],
"audio_aac_roundtrip_rms": sys.argv[10],
}
@ -190,6 +193,39 @@ select_gst_h264_decoder() {
return 1
}
select_gst_hevc_decoder() {
local decoder
for decoder in nvh265dec vah265dec vaapih265dec v4l2h265dec v4l2slh265dec; do
if gst_has "${decoder}"; then
printf '%s\n' "${decoder}"
return 0
fi
done
return 1
}
select_gst_hevc_encoder() {
local encoder
for encoder in nvh265enc nvautogpuh265enc vah265enc vaapih265enc v4l2h265enc; do
if gst_has "${encoder}"; then
printf '%s\n' "${encoder}"
return 0
fi
done
return 1
}
select_gst_h264_encoder() {
local encoder
for encoder in nvh264enc nvautogpuh264enc vah264enc vaapih264enc v4l2h264enc; do
if gst_has "${encoder}"; then
printf '%s\n' "${encoder}"
return 0
fi
done
return 1
}
gst_h264_decode_chain() {
case "$1" in
vulkanh264dec)
@ -204,6 +240,17 @@ gst_h264_decode_chain() {
esac
}
gst_hevc_decode_chain() {
case "$1" in
nvh265dec|vah265dec|vaapih265dec|v4l2h265dec|v4l2slh265dec)
printf '%s\n' "$1"
;;
*)
return 1
;;
esac
}
select_gst_aac_encoder() {
local encoder
for encoder in fdkaacenc voaacenc avenc_aac; do
@ -226,36 +273,49 @@ main() {
exit 1
fi
if ! ffmpeg_has_encoder hevc_nvenc; then
record_result "client_upstream_hevc_nvenc_available" "fail" "ffmpeg hevc_nvenc encoder is missing" ""
OVERALL=1
else
record_result "client_upstream_hevc_nvenc_available" "pass" "ffmpeg hevc_nvenc encoder is available" ""
fi
if ! ffmpeg_has_encoder h264_nvenc; then
record_result "client_downstream_h264_nvenc_source_available" "fail" "ffmpeg h264_nvenc encoder is missing for downstream test source" ""
OVERALL=1
else
record_result "client_downstream_h264_nvenc_source_available" "pass" "ffmpeg h264_nvenc encoder is available for downstream test source" ""
fi
if ! ffmpeg_has_decoder hevc_cuvid; then
record_result "client_hevc_cuvid_visual_decode_available" "fail" "ffmpeg hevc_cuvid decoder is missing for visual evidence frame" ""
OVERALL=1
else
record_result "client_hevc_cuvid_visual_decode_available" "pass" "ffmpeg hevc_cuvid decoder is available for visual evidence frame" ""
fi
if ! ffmpeg_has_decoder h264_cuvid; then
record_result "client_h264_cuvid_visual_decode_available" "fail" "ffmpeg h264_cuvid decoder is missing for visual evidence frame" ""
OVERALL=1
else
record_result "client_h264_cuvid_visual_decode_available" "pass" "ffmpeg h264_cuvid decoder is available for visual evidence frame" ""
fi
local hevc_encoder=""
local hevc_encoder_route=""
local h264_encoder=""
local h264_encoder_route=""
local gst_hevc_decoder=""
local gst_hevc_chain=""
local gst_h264_decoder=""
local gst_h264_chain=""
if ffmpeg_has_encoder hevc_nvenc && ffmpeg_nvenc_usable hevc_nvenc; then
hevc_encoder="hevc_nvenc"
hevc_encoder_route="ffmpeg"
elif hevc_encoder="$(select_gst_hevc_encoder)"; then
hevc_encoder_route="gstreamer"
else
record_result "client_upstream_hevc_hardware_encoder" "fail" "no runtime-usable HEVC hardware encoder found" ""
OVERALL=1
fi
if [[ -n ${hevc_encoder} ]]; then
record_result "client_upstream_hevc_hardware_encoder" "pass" "selected ${hevc_encoder_route}:${hevc_encoder}" ""
fi
if ffmpeg_has_encoder h264_nvenc && ffmpeg_nvenc_usable h264_nvenc; then
h264_encoder="h264_nvenc"
h264_encoder_route="ffmpeg"
elif h264_encoder="$(select_gst_h264_encoder)"; then
h264_encoder_route="gstreamer"
else
record_result "client_downstream_h264_hardware_source" "fail" "no runtime-usable H.264 hardware encoder found" ""
OVERALL=1
fi
if [[ -n ${h264_encoder} ]]; then
record_result "client_downstream_h264_hardware_source" "pass" "selected ${h264_encoder_route}:${h264_encoder}" ""
fi
if gst_hevc_decoder="$(select_gst_hevc_decoder)"; then
gst_hevc_chain="$(gst_hevc_decode_chain "${gst_hevc_decoder}")"
record_result "client_upstream_gstreamer_hevc_hw_decoder_available" "pass" "selected ${gst_hevc_decoder}" ""
else
record_result "client_upstream_gstreamer_hevc_hw_decoder_available" "fail" "no GStreamer hardware H.265 decoder found" ""
OVERALL=1
fi
if gst_h264_decoder="$(select_gst_h264_decoder)"; then
gst_h264_chain="$(gst_h264_decode_chain "${gst_h264_decoder}")"
record_result "client_downstream_gstreamer_h264_hw_decoder_available" "pass" "selected ${gst_h264_decoder}" ""
@ -273,29 +333,41 @@ main() {
fi
if [[ ${OVERALL} -eq 0 ]]; then
run_shell "client_upstream_hevc_nvenc_file" \
"GPU encodes a synthetic upstream HEVC stream with hevc_nvenc" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -f lavfi -i testsrc2=size=${SMOKE_WIDTH}x${SMOKE_HEIGHT}:rate=${SMOKE_FPS} -frames:v ${SMOKE_FRAMES} -an -sn -dn -vf format=nv12 -c:v hevc_nvenc -preset p1 -tune ll -rc cbr -b:v ${SMOKE_BITRATE_KBPS}k -maxrate ${SMOKE_BITRATE_KBPS}k -bufsize ${SMOKE_BITRATE_KBPS}k -g ${SMOKE_FPS} -bf 0 -forced-idr 1 -f hevc '${UPSTREAM_HEVC_FILE}'"
if [[ ${hevc_encoder_route} == ffmpeg ]]; then
run_shell "client_upstream_hevc_hardware_file" \
"GPU encodes a synthetic upstream HEVC stream with ${hevc_encoder}" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -f lavfi -i testsrc2=size=${SMOKE_WIDTH}x${SMOKE_HEIGHT}:rate=${SMOKE_FPS} -frames:v ${SMOKE_FRAMES} -an -sn -dn -vf format=nv12 -c:v ${hevc_encoder} -preset p1 -tune ll -rc cbr -b:v ${SMOKE_BITRATE_KBPS}k -maxrate ${SMOKE_BITRATE_KBPS}k -bufsize ${SMOKE_BITRATE_KBPS}k -g ${SMOKE_FPS} -bf 0 -forced-idr 1 -f hevc '${UPSTREAM_HEVC_FILE}'"
else
run_shell "client_upstream_hevc_hardware_file" \
"GPU encodes a synthetic upstream HEVC stream with ${hevc_encoder}" \
"gst-launch-1.0 -q videotestsrc num-buffers=${SMOKE_FRAMES} is-live=false pattern=smpte ! video/x-raw,width=${SMOKE_WIDTH},height=${SMOKE_HEIGHT},framerate=${SMOKE_FPS}/1 ! videoconvert ! video/x-raw,format=NV12 ! ${hevc_encoder} ! h265parse config-interval=-1 ! video/x-h265,stream-format=byte-stream,alignment=au ! filesink location='${UPSTREAM_HEVC_FILE}'"
fi
run_shell "client_upstream_hevc_gstreamer_parse" \
"GStreamer accepts the HEVC elementary stream shape used by the upstream bundle path" \
"gst-launch-1.0 -q filesrc location='${UPSTREAM_HEVC_FILE}' ! h265parse config-interval=-1 ! video/x-h265,stream-format=byte-stream,alignment=au ! fakesink sync=false"
run_shell "client_upstream_hevc_cuvid_frame" \
"CUDA decodes one visual proof frame from the upstream HEVC stream" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -c:v hevc_cuvid -i '${UPSTREAM_HEVC_FILE}' -frames:v 1 '${UPSTREAM_HEVC_FRAME}'"
run_shell "client_upstream_hevc_hardware_frame" \
"GStreamer hardware decoder ${gst_hevc_decoder} emits one visual HEVC proof frame" \
"gst-launch-1.0 -q filesrc location='${UPSTREAM_HEVC_FILE}' ! h265parse ! ${gst_hevc_chain} ! videoconvert ! pngenc snapshot=true ! filesink location='${UPSTREAM_HEVC_FRAME}'"
run_shell "client_downstream_h264_nvenc_file" \
"GPU creates a downstream-like H.264 elementary stream for decoder verification" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -f lavfi -i testsrc2=size=${SMOKE_WIDTH}x${SMOKE_HEIGHT}:rate=${SMOKE_FPS} -frames:v ${SMOKE_FRAMES} -an -sn -dn -vf format=nv12 -c:v h264_nvenc -preset p1 -tune ll -rc cbr -b:v ${SMOKE_BITRATE_KBPS}k -maxrate ${SMOKE_BITRATE_KBPS}k -bufsize ${SMOKE_BITRATE_KBPS}k -g ${SMOKE_FPS} -bf 0 -forced-idr 1 -f h264 '${DOWNSTREAM_H264_FILE}'"
if [[ ${h264_encoder_route} == ffmpeg ]]; then
run_shell "client_downstream_h264_hardware_file" \
"GPU creates a downstream-like H.264 elementary stream with ${h264_encoder}" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -f lavfi -i testsrc2=size=${SMOKE_WIDTH}x${SMOKE_HEIGHT}:rate=${SMOKE_FPS} -frames:v ${SMOKE_FRAMES} -an -sn -dn -vf format=nv12 -c:v ${h264_encoder} -preset p1 -tune ll -rc cbr -b:v ${SMOKE_BITRATE_KBPS}k -maxrate ${SMOKE_BITRATE_KBPS}k -bufsize ${SMOKE_BITRATE_KBPS}k -g ${SMOKE_FPS} -bf 0 -forced-idr 1 -f h264 '${DOWNSTREAM_H264_FILE}'"
else
run_shell "client_downstream_h264_hardware_file" \
"GPU creates a downstream-like H.264 elementary stream with ${h264_encoder}" \
"gst-launch-1.0 -q videotestsrc num-buffers=${SMOKE_FRAMES} is-live=false pattern=smpte ! video/x-raw,width=${SMOKE_WIDTH},height=${SMOKE_HEIGHT},framerate=${SMOKE_FPS}/1 ! videoconvert ! video/x-raw,format=NV12 ! ${h264_encoder} ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream,alignment=au ! filesink location='${DOWNSTREAM_H264_FILE}'"
fi
run_shell "client_downstream_h264_gstreamer_hw_decode" \
"GStreamer decodes H.264 with hardware decoder ${gst_h264_decoder}" \
"gst-launch-1.0 -q filesrc location='${DOWNSTREAM_H264_FILE}' ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream,alignment=au ! ${gst_h264_chain} ! videoconvert ! fakesink sync=false"
run_shell "client_downstream_h264_cuvid_frame" \
"CUDA decodes one visual proof frame from the downstream H.264 stream" \
"ffmpeg -hide_banner -loglevel warning -y -nostdin -c:v h264_cuvid -i '${DOWNSTREAM_H264_FILE}' -frames:v 1 '${DOWNSTREAM_H264_FRAME}'"
run_shell "client_downstream_h264_hardware_frame" \
"GStreamer hardware decoder ${gst_h264_decoder} emits one visual H.264 proof frame" \
"gst-launch-1.0 -q filesrc location='${DOWNSTREAM_H264_FILE}' ! h264parse ! ${gst_h264_chain} ! videoconvert ! pngenc snapshot=true ! filesink location='${DOWNSTREAM_H264_FRAME}'"
run_shell "audio_aac_roundtrip_wav" \
"GStreamer encodes and decodes a 1 kHz tone to a WAV artifact for audio-path sanity" \

View File

@ -16,7 +16,7 @@ bench = false
[package]
name = "lesavka_server"
version = "0.27.7"
version = "0.27.8"
edition = "2024"
autobins = false

View File

@ -216,13 +216,18 @@ mod camera_include_contract {
}
#[test]
fn hevc_prefers_proven_ffmpeg_nvenc_unless_gstreamer_is_explicit() {
fn hevc_prefers_runtime_proven_ffmpeg_nvenc_unless_gstreamer_is_explicit() {
let encoder_source = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/client/src/input/camera/encoder_selection.rs"
));
for expected in [
"Path::new(\"/dev/nvidiactl\").exists()",
"color=c=black:s=128x128:r=1",
"\"hevc_nvenc\"",
"\"-f\",",
"\"null\"",
"Some(\"ffmpeg_hevc_nvenc\" | \"hevc_nvenc\" | \"nvenc\")",
"Some(\"gstreamer\" | \"gst\") => false",
"_ => Self::ffmpeg_hevc_nvenc_available()",
@ -236,6 +241,16 @@ mod camera_include_contract {
!encoder_source.contains("!Self::gstreamer_hevc_hardware_encoder_available()"),
"a present GStreamer HEVC encoder must not suppress the proven FFmpeg/NVENC path"
);
assert!(
encoder_source.contains(
"supported_encoder_property(\"vah264enc\", &[\"key-int-max\", \"keyframe-period\"])",
),
"modern vah264enc must receive its real short-GOP property"
);
assert!(
encoder_source.contains("(\"vah265enc\", &[\"key-int-max\", \"keyframe-period\"][..])"),
"modern vah265enc must receive its real short-GOP property"
);
}
#[test]

View File

@ -103,7 +103,9 @@ fn client_install_reports_nvidia_and_open_source_media_routes() {
"first_available_gst_element",
"nvidia-smi is available",
"NVIDIA nvcodec is installed but CUDA initialization failed",
"FFmpeg hevc_nvenc is available",
"FFmpeg hevc_nvenc encoded a probe frame",
"ffmpeg_hevc_nvenc_usable",
"/dev/nvidiactl",
"proprietary NVIDIA GStreamer route",
"Vulkan/VAAPI/V4L2 GStreamer route",
"nvh265enc",

View File

@ -17,10 +17,10 @@ fn hardware_media_smoke_stays_manual_and_artifact_backed() {
"Manual: local/remote hardware media smoke evidence; not part of CI.",
"summary_json: ${SUMMARY_JSON}",
"summary_txt: ${SUMMARY_TXT}",
"upstream-hevc-nvenc.hevc",
"upstream-hevc-cuda-frame.png",
"downstream-h264-nvenc.h264",
"downstream-h264-cuda-frame.png",
"upstream-hevc-hardware.hevc",
"upstream-hevc-hardware-frame.png",
"downstream-h264-hardware.h264",
"downstream-h264-hardware-frame.png",
"audio-aac-roundtrip.wav",
"audio-aac-roundtrip-rms.json",
] {
@ -36,8 +36,9 @@ fn hardware_media_smoke_uses_accelerated_video_paths() {
for marker in [
"hevc_nvenc",
"h264_nvenc",
"hevc_cuvid",
"h264_cuvid",
"ffmpeg_nvenc_usable",
"vah265enc",
"vah265dec",
"vah264dec",
"vulkanh264dec",
"v4l2slh264dec",