Skip to content

Commit e84268e

Browse files
authored
Merge pull request qualcomm-linux#166 from smuppand/camera-yavta
Camera_RDI_FrameCapture: stabilize RDI capture via parsed media-graph config + richer CI diagnostics
2 parents 3e80ab3 + 59e072f commit e84268e

File tree

2 files changed

+214
-96
lines changed

2 files changed

+214
-96
lines changed
Lines changed: 182 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,26 @@
11
#!/bin/sh
22
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
33
# SPDX-License-Identifier: BSD-3-Clause-Clear
4-
4+
# --- Robustly find and source init_env ---------------------------
55
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
66
INIT_ENV=""
77
SEARCH="$SCRIPT_DIR"
88
while [ "$SEARCH" != "/" ]; do
99
if [ -f "$SEARCH/init_env" ]; then
10-
INIT_ENV="$SEARCH/init_env"
11-
break
10+
INIT_ENV="$SEARCH/init_env"; break
1211
fi
1312
SEARCH=$(dirname "$SEARCH")
1413
done
14+
[ -z "$INIT_ENV" ] && echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 && exit 1
1515

16-
if [ -z "$INIT_ENV" ]; then
17-
echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2
18-
exit 1
19-
fi
20-
21-
if [ -z "$__INIT_ENV_LOADED" ]; then
22-
# shellcheck disable=SC1090
23-
. "$INIT_ENV"
24-
fi
16+
# shellcheck disable=SC1090
17+
[ -z "$__INIT_ENV_LOADED" ] && . "$INIT_ENV"
2518
# shellcheck disable=SC1090,SC1091
2619
. "$TOOLS/functestlib.sh"
2720

2821
TESTNAME="Camera_RDI_FrameCapture"
2922
RES_FILE="./$TESTNAME.res"
30-
test_path=$(find_test_case_by_name "$TESTNAME")
23+
test_path="$(find_test_case_by_name "$TESTNAME")"
3124
cd "$test_path" || exit 1
3225

3326
print_usage() {
@@ -50,44 +43,153 @@ USER_FORMAT=""
5043
FRAMES=10
5144
while [ $# -gt 0 ]; do
5245
case "$1" in
53-
--format)
54-
shift
55-
USER_FORMAT="$1"
56-
;;
57-
--frames)
58-
shift
59-
FRAMES="$1"
60-
;;
61-
--help)
62-
print_usage
63-
exit 0
64-
;;
65-
*)
66-
log_error "Unknown argument: $1"
67-
print_usage
68-
exit 1
69-
;;
46+
--format) shift; USER_FORMAT="$1" ;;
47+
--frames) shift; FRAMES="$1" ;;
48+
--help) print_usage; exit 0 ;;
49+
*) log_error "Unknown argument: $1"; print_usage; exit 1 ;;
7050
esac
7151
shift
7252
done
7353

74-
# --------- Prechecks ---------
54+
# Helper: print planned media-ctl / yavta sequence for CI logs
55+
print_planned_commands() {
56+
media_node="$1"
57+
pixfmt="$2"
58+
59+
log_info "[CI] Planned sequence:"
60+
log_info " media-ctl -d $media_node --reset"
61+
62+
# media-ctl -V (show with possible TARGET_FORMAT substitution exactly like configure helper does)
63+
if [ -n "$MEDIA_CTL_V_LIST" ]; then
64+
printf '%s\n' "$MEDIA_CTL_V_LIST" | while IFS= read -r vline; do
65+
[ -z "$vline" ] && continue
66+
vline_out="$(printf '%s' "$vline" | sed -E "s/fmt:[^/]+\/([0-9]+x[0-9]+)/fmt:${pixfmt}\/\1/g")"
67+
log_info " media-ctl -d $media_node -V '$vline_out'"
68+
done
69+
fi
70+
# media-ctl -l
71+
if [ -n "$MEDIA_CTL_L_LIST" ]; then
72+
printf '%s\n' "$MEDIA_CTL_L_LIST" | while IFS= read -r lline; do
73+
[ -z "$lline" ] && continue
74+
log_info " media-ctl -d $media_node -l '$lline'"
75+
done
76+
fi
77+
# yavta control writes (pre)
78+
if [ -n "$YAVTA_CTRL_PRE_LIST" ]; then
79+
printf '%s\n' "$YAVTA_CTRL_PRE_LIST" | while IFS= read -r ctrl; do
80+
[ -z "$ctrl" ] && continue
81+
dev="$(printf '%s' "$ctrl" | awk '{print $1}')"
82+
reg="$(printf '%s' "$ctrl" | awk '{print $2}')"
83+
val="$(printf '%s' "$ctrl" | awk '{print $3}')"
84+
[ -n "$dev" ] && [ -n "$reg" ] && [ -n "$val" ] && \
85+
log_info " yavta --no-query -w '$reg $val' $dev"
86+
done
87+
fi
88+
# main yavta capture (dimensions may be empty occasionally)
89+
size_arg=""
90+
if [ -n "$YAVTA_W" ] && [ -n "$YAVTA_H" ]; then
91+
size_arg="-s ${YAVTA_W}x${YAVTA_H}"
92+
fi
93+
if [ -n "$YAVTA_DEV" ]; then
94+
log_info " yavta -B capture-mplane -c -I -n $FRAMES -f $pixfmt $size_arg -F $YAVTA_DEV --capture=$FRAMES --file='frame-#.bin'"
95+
fi
96+
# yavta control writes (post)
97+
if [ -n "$YAVTA_CTRL_POST_LIST" ]; then
98+
printf '%s\n' "$YAVTA_CTRL_POST_LIST" | while IFS= read -r ctrl; do
99+
[ -z "$ctrl" ] && continue
100+
dev="$(printf '%s' "$ctrl" | awk '{print $1}')"
101+
reg="$(printf '%s' "$ctrl" | awk '{print $2}')"
102+
val="$(printf '%s' "$ctrl" | awk '{print $3}')"
103+
[ -n "$dev" ] && [ -n "$reg" ] && [ -n "$val" ] && \
104+
log_info " yavta --no-query -w '$reg $val' $dev"
105+
done
106+
fi
107+
}
108+
109+
# --------- DT Precheck ---------
75110
if ! dt_confirm_node_or_compatible "isp" "cam" "camss"; then
76111
log_skip "$TESTNAME SKIP – No ISP/camera node/compatible found in DT"
77112
echo "$TESTNAME SKIP" >"$RES_FILE"
78113
exit 0
79114
fi
80115

81-
DRIVER_MOD="qcom_camss"
82-
DMESG_MODULES='qcom_camss|camss|isp'
83-
DMESG_EXCLUDE='dummy regulator|supply [^ ]+ not found|using dummy regulator|Failed to create device link|reboot-mode.*-EEXIST|can.t register reboot mode'
116+
# --------- Kernel config sanity (MANDATORY bits only gate if totally absent) ---------
117+
log_info "[CONFIG] Expect at least: CONFIG_VIDEO_QCOM_CAMSS=y (or =m)"
118+
check_kernel_config "CONFIG_VIDEO_QCOM_CAMSS CONFIG_MEDIA_CONTROLLER CONFIG_V4L2_FWNODE" \
119+
|| log_warn "[CONFIG] One or more options missing; will continue if CAMSS stack is otherwise present"
84120

85-
if ! is_module_loaded "$DRIVER_MOD"; then
86-
log_skip "$TESTNAME SKIP – Driver module $DRIVER_MOD not loaded"
121+
# Optional visibility: print any CAMCC entries (name varies by tree)
122+
if ! check_kernel_config "CONFIG_QCOM_CAMCC_SC7280"; then
123+
if command -v zgrep >/dev/null 2>&1; then
124+
CAMCC_SYMS="$(zgrep -E '^CONFIG_.*CAMCC.*=(y|m)' /proc/config.gz 2>/dev/null || true)"
125+
else
126+
CAMCC_SYMS="$(gzip -dc /proc/config.gz 2>/dev/null | grep -E '^CONFIG_.*CAMCC.*=(y|m)' || true)"
127+
fi
128+
if [ -n "$CAMCC_SYMS" ]; then
129+
printf '%s\n' "$CAMCC_SYMS" | while IFS= read -r s; do
130+
[ -n "$s" ] && log_info "[CONFIG] $s"
131+
done
132+
fi
133+
fi
134+
135+
# --------- Broader readiness gate (module OR builtin OR nodes OR dmesg) ---------
136+
DMESG_CACHE="$(dmesg 2>/dev/null || true)"
137+
138+
if [ -e /dev/media0 ] || [ -e /dev/video0 ]; then
139+
log_pass "[READY] Media/video nodes present:"
140+
for f in /dev/media* /dev/video*; do
141+
[ -e "$f" ] || continue
142+
log_info " - $f"
143+
done
144+
elif is_module_loaded qcom_camss; then
145+
log_pass "[READY] qcom_camss module loaded"
146+
elif [ -d /sys/module/qcom_camss ]; then
147+
log_pass "[READY] qcom_camss present as builtin"
148+
elif printf '%s\n' "$DMESG_CACHE" | grep -qiE 'qcom[-_]camss'; then
149+
log_info "[READY] CAMSS messages found in dmesg (likely builtin)"
150+
else
151+
log_skip "Camera_RDI_FrameCapture SKIP – CAMSS driver not present (module or built-in)"
87152
echo "$TESTNAME SKIP" >"$RES_FILE"
88153
exit 0
89154
fi
90155

156+
# --------- Module inventory (visibility only; no gating) ---------
157+
MODULES_LIST="qcom_camss camcc_sc7280 videodev mc v4l2_fwnode v4l2_async videobuf2_common videobuf2_v4l2 videobuf2_dma_contig videobuf2_dma_sg videobuf2_memops"
158+
159+
present_mods=""
160+
builtin_mods=""
161+
missing_mods=""
162+
for m in $MODULES_LIST; do
163+
if is_module_loaded "$m"; then
164+
present_mods="$present_mods $m"
165+
elif [ -d "/sys/module/$m" ]; then
166+
builtin_mods="$builtin_mods $m"
167+
else
168+
missing_mods="$missing_mods $m"
169+
fi
170+
done
171+
172+
if [ -n "$present_mods" ]; then
173+
log_pass "[MODULES] Loaded:"
174+
for m in $present_mods; do [ -n "$m" ] && log_info " - $m"; done
175+
fi
176+
if [ -n "$builtin_mods" ]; then
177+
log_info "[MODULES] Built-in:"
178+
for m in $builtin_mods; do [ -n "$m" ] && log_info " - $m"; done
179+
fi
180+
if [ -n "$missing_mods" ]; then
181+
log_warn "[MODULES] Not found:"
182+
for m in $missing_mods; do [ -n "$m" ] && log_info " - $m"; done
183+
fi
184+
185+
# Sensor modules (best-effort)
186+
SENSOR_MODS="$(awk '{print $1}' /proc/modules 2>/dev/null | grep -E '^(imx|ov|gc|ar)[0-9]+' | tr '\n' ' ')"
187+
[ -n "$SENSOR_MODS" ] && { log_info "[MODULES] Sensors:"; for s in $SENSOR_MODS; do log_info " - $s"; done; }
188+
189+
# --------- Dmesg probe errors (non-benign filter) ---------
190+
DRIVER_MOD="qcom_camss"
191+
DMESG_MODULES='qcom_camss|camss|isp'
192+
DMESG_EXCLUDE='dummy regulator|supply [^ ]+ not found|using dummy regulator|Failed to create device link|reboot-mode.*-EEXIST|can.t register reboot mode'
91193
if scan_dmesg_errors "$SCRIPT_DIR" "$DMESG_MODULES" "$DMESG_EXCLUDE"; then
92194
log_skip "$TESTNAME SKIP – $DRIVER_MOD probe errors detected in dmesg"
93195
echo "$TESTNAME SKIP" >"$RES_FILE"
@@ -102,100 +204,101 @@ check_dependencies media-ctl yavta python3 v4l2-ctl || {
102204
}
103205

104206
# --------- Media Node Detection ---------
105-
MEDIA_NODE=$(detect_media_node)
207+
MEDIA_NODE="$(detect_media_node)"
106208
if [ -z "$MEDIA_NODE" ]; then
107209
log_skip "$TESTNAME SKIP – Media node not found"
108210
echo "$TESTNAME SKIP" >"$RES_FILE"
109211
exit 0
110212
fi
111213
log_info "Detected media node: $MEDIA_NODE"
112214

113-
# --------- Pipeline Detection ---------
114-
TOPO_FILE=$(mktemp "/tmp/${TESTNAME}_topo.XXXXXX")
115-
TMP_PIPELINES_FILE=$(mktemp "/tmp/${TESTNAME}_blocks.XXXXXX")
215+
# Light-touch global reset once
216+
media-ctl -d "$MEDIA_NODE" -r >/dev/null 2>&1 || true
217+
log_info "Media graph reset (-r) done on $MEDIA_NODE"
218+
sleep 0.2
219+
220+
# --------- Pipeline Detection (Python) ---------
221+
TOPO_FILE="$(mktemp "/tmp/${TESTNAME}_topo.XXXXXX")"
222+
TMP_PIPELINES_FILE="$(mktemp "/tmp/${TESTNAME}_blocks.XXXXXX")"
116223
trap 'rm -f "$TOPO_FILE" "$TMP_PIPELINES_FILE"' EXIT
117224

118225
media-ctl -p -d "$MEDIA_NODE" >"$TOPO_FILE" 2>/dev/null
119-
PYTHON_PIPELINES=$(run_camera_pipeline_parser "$TOPO_FILE")
226+
PYTHON_PIPELINES="$(run_camera_pipeline_parser "$TOPO_FILE")"
120227
if [ -z "$PYTHON_PIPELINES" ]; then
121228
log_skip "$TESTNAME SKIP – No valid pipelines found"
122229
echo "$TESTNAME SKIP" >"$RES_FILE"
123230
exit 0
124231
fi
125-
126-
printf "%s\n" "$PYTHON_PIPELINES" > "$TMP_PIPELINES_FILE"
232+
printf '%s\n' "$PYTHON_PIPELINES" >"$TMP_PIPELINES_FILE"
127233

128234
log_info "User format override: ${USER_FORMAT:-<none>}"
129235
log_info "Frame count per pipeline: $FRAMES"
130236

131-
# --------- Pipeline Processing ---------
237+
# --------- Pipeline Processing (core logic unchanged) ---------
132238
PASS=0; FAIL=0; SKIP=0; COUNT=0
133239
block=""
134-
135240
while IFS= read -r line || [ -n "$line" ]; do
136241
if [ "$line" = "--" ]; then
137242
COUNT=$((COUNT+1))
138243
TMP="/tmp/cam_block.$$.$COUNT"
139-
printf "%s\n" "$block" > "$TMP"
244+
printf '%s\n' "$block" > "$TMP"
140245

141-
# Parses block and sets SENSOR, VIDEO, YAVTA_DEV, FMT, etc
246+
# Parses block and sets SENSOR, VIDEO, YAVTA_DEV, YAVTA_FMT, MEDIA_CTL_* lists, etc.
142247
parse_pipeline_block "$TMP"
143248
rm -f "$TMP"
144249

145250
# -------- Multi-format support (POSIX style, no arrays) --------
146251
FORMATS_LIST="$USER_FORMAT"
147-
if [ -z "$FORMATS_LIST" ]; then
148-
# No user override, use detected format for this pipeline only
149-
FORMATS_LIST="$YAVTA_FMT"
150-
fi
252+
[ -z "$FORMATS_LIST" ] && FORMATS_LIST="$YAVTA_FMT"
151253

152-
OLD_IFS="$IFS"
153-
IFS=','
254+
OLD_IFS="$IFS"; IFS=','
154255
for FMT_OVERRIDE in $FORMATS_LIST; do
155-
FMT_OVERRIDE=$(printf '%s' "$FMT_OVERRIDE" | sed 's/^ *//;s/ *$//')
156-
TARGET_FORMAT="$FMT_OVERRIDE"
157-
[ -z "$TARGET_FORMAT" ] && TARGET_FORMAT="$YAVTA_FMT"
256+
FMT_OVERRIDE="$(printf '%s' "$FMT_OVERRIDE" | sed 's/^ *//;s/ *$//')"
257+
TARGET_FORMAT="$FMT_OVERRIDE"; [ -z "$TARGET_FORMAT" ] && TARGET_FORMAT="$YAVTA_FMT"
158258

159-
log_info "----- Pipeline $COUNT: ${SENSOR:-unknown} $VIDEO $TARGET_FORMAT -----"
259+
# New banner: show pad mbus fmt and video pixfmt
260+
PAD_MBUS_FMT="$(printf '%s\n' "$MEDIA_CTL_V_LIST" | sed -n 's/.*fmt:\([^/]]*\)\/.*/\1/p' | head -n1)"
261+
[ -z "$PAD_MBUS_FMT" ] && PAD_MBUS_FMT="auto"
262+
log_info "----- Pipeline $COUNT: ${SENSOR:-unknown} $VIDEO [pads:$PAD_MBUS_FMT] [video:$TARGET_FORMAT] -----"
160263

161264
if [ -z "$VIDEO" ] || [ "$VIDEO" = "None" ] || [ -z "$YAVTA_DEV" ]; then
162265
log_skip "$SENSOR: Invalid pipeline – skipping"
163266
SKIP=$((SKIP+1))
164267
continue
165268
fi
166269

270+
# CI debug: print the exact commands we will run
271+
print_planned_commands "$MEDIA_NODE" "$TARGET_FORMAT"
272+
273+
# Configure & capture (original helpers)
167274
configure_pipeline_block "$MEDIA_NODE" "$TARGET_FORMAT"
168275
execute_capture_block "$FRAMES" "$TARGET_FORMAT"
169276
RET=$?
170277

278+
# Safety net retry
279+
if [ "$RET" -ne 0 ]; then
280+
log_warn "First attempt failed; resetting media graph and retrying once"
281+
log_info " media-ctl -d $MEDIA_NODE -r"
282+
media-ctl -d "$MEDIA_NODE" -r >/dev/null 2>&1 || true
283+
sleep 0.1
284+
print_planned_commands "$MEDIA_NODE" "$TARGET_FORMAT"
285+
configure_pipeline_block "$MEDIA_NODE" "$TARGET_FORMAT"
286+
execute_capture_block "$FRAMES" "$TARGET_FORMAT"
287+
RET=$?
288+
fi
289+
171290
case "$RET" in
172-
0)
173-
log_pass "$SENSOR $VIDEO $TARGET_FORMAT PASS"
174-
PASS=$((PASS+1))
175-
;;
176-
1)
177-
log_fail "$SENSOR $VIDEO $TARGET_FORMAT FAIL (capture failed)"
178-
FAIL=$((FAIL+1))
179-
;;
180-
2)
181-
log_skip "$SENSOR $VIDEO $TARGET_FORMAT SKIP (unsupported format)"
182-
SKIP=$((SKIP+1))
183-
;;
184-
3)
185-
log_skip "$SENSOR $VIDEO missing data – skipping"
186-
SKIP=$((SKIP+1))
187-
;;
291+
0) log_pass "$SENSOR $VIDEO $TARGET_FORMAT PASS"; PASS=$((PASS+1)) ;;
292+
1) log_fail "$SENSOR $VIDEO $TARGET_FORMAT FAIL (capture failed)"; FAIL=$((FAIL+1)) ;;
293+
2) log_skip "$SENSOR $VIDEO $TARGET_FORMAT SKIP (unsupported format)"; SKIP=$((SKIP+1)) ;;
294+
3) log_skip "$SENSOR $VIDEO missing data – skipping"; SKIP=$((SKIP+1)) ;;
188295
esac
189296
done
190297
IFS="$OLD_IFS"
191298
block=""
192299
else
193-
if [ -z "$block" ]; then
194-
block="$line"
195-
else
196-
block="$block
197-
$line"
198-
fi
300+
if [ -z "$block" ]; then block="$line"; else block="$block
301+
$line"; fi
199302
fi
200303
done < "$TMP_PIPELINES_FILE"
201304

@@ -207,5 +310,4 @@ elif [ "$FAIL" -gt 0 ]; then
207310
else
208311
echo "$TESTNAME SKIP" >"$RES_FILE"
209312
fi
210-
211313
exit 0

0 commit comments

Comments
 (0)