Skip to content

Commit 40a2abd

Browse files
authored
Merge pull request qualcomm-linux#139 from smuppand/camera_rdi
Camera RDI Pipeline: Modularize and Robustify Frame Capture with Dynamic Python Parsing
2 parents 7c59ffe + 19ba8d6 commit 40a2abd

File tree

4 files changed

+852
-51
lines changed

4 files changed

+852
-51
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Camera RDI Frame Capture Test
2+
3+
This test validates functional camera RDI (Raw Dump Interface) pipelines by:
4+
5+
- Dynamically detecting all camera pipelines using `media-ctl`
6+
- Parsing valid RDI pipelines with a Python helper script
7+
- Streaming frames using `yavta` from detected working pipelines
8+
- Supporting manual override of video format and frame count
9+
10+
## 📁 Test Directory Structure
11+
12+
```
13+
Camera_RDI_FrameCapture/
14+
├── run.sh
15+
├── README_Camera_RDI_FrameCapture.md
16+
17+
```
18+
19+
## 🧠 How It Works
20+
21+
1. Detects media device node dynamically
22+
2. Dumps the topology to a temporary file
23+
3. Parses pipeline details using `parse_media_topology.py`
24+
4. For each detected pipeline:
25+
- Applies correct media-ctl `-V` and `-l` configuration
26+
- Sets V4L2 controls pre-/post-streaming via `yavta`
27+
- Attempts frame capture using `yavta`
28+
5. Logs PASS/FAIL/SKIP per pipeline
29+
6. Generates a `.res` file with final test result
30+
31+
## ⚙️ Dependencies
32+
33+
Make sure the following tools are available in the target filesystem:
34+
35+
- `media-ctl`
36+
- `yavta`
37+
- `v4l2-ctl`
38+
- `python3`
39+
- Python camera pipeline parser (see `utils/camera/parse_media_topology.py`)
40+
- Kernel module: `qcom_camss`
41+
- Required DT nodes for `camss`, `isp`, or `camera` compatible strings
42+
43+
## 🧪 Usage
44+
45+
```sh
46+
./run.sh [--format <fmt1,fmt2,...>] [--frames <count>] [--help]
47+
```
48+
49+
### Examples:
50+
51+
- Auto-detect and capture 10 frames per working RDI pipeline:
52+
```sh
53+
./run.sh
54+
```
55+
56+
- Force UYVY format and capture 5 frames:
57+
```sh
58+
./run.sh --format UYVY --frames 5
59+
```
60+
61+
- Comma-seperated list of V4L2 formats to attempt per pipeline
62+
```sh
63+
./run.sh --format SRGGB10P,YUYV,UYVY --frames 5
64+
```
65+
66+
## 📦 Output
67+
68+
- Captured frame files: `frame-#.bin` in current directory
69+
- Result summary: `Camera_RDI_FrameCapture.res`
70+
- Detailed logs through `functestlib.sh`-based `log_info`, `log_pass`, etc.
71+
72+
## ✅ Pass Criteria
73+
74+
- At least one pipeline successfully captures frames
75+
- Logs include `"Captured <n> frames"` for at least one working video node
76+
77+
## ❌ Fail/Skip Criteria
78+
79+
- If pipeline configuration fails or no frames captured, it is marked FAIL
80+
- If no working pipelines are found or prerequisites are unmet, test is SKIPPED
81+
82+
## 🧼 Cleanup
83+
84+
Temporary files created:
85+
- `/tmp/v4l2_camera_RDI_dump_topo.*`
86+
- `/tmp/v4l2_camera_RDI_dump_pipelines.*`
87+
88+
They are auto-removed at the end of the test.
89+
90+
## 📝 Notes
91+
92+
- The test is dynamic and supports multiple pipelines per board
93+
- Python script only outputs **valid** working pipelines (validated via `v4l2-ctl`)
94+
- `run.sh` is robust, CI-ready, and skips flaky or unsupported configurations gracefully
95+
96+
---
97+
98+
© Qualcomm Technologies, Inc. – All rights reserved
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/bin/sh
2+
# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3+
# SPDX-License-Identifier: BSD-3-Clause-Clear
4+
5+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6+
INIT_ENV=""
7+
SEARCH="$SCRIPT_DIR"
8+
while [ "$SEARCH" != "/" ]; do
9+
if [ -f "$SEARCH/init_env" ]; then
10+
INIT_ENV="$SEARCH/init_env"
11+
break
12+
fi
13+
SEARCH=$(dirname "$SEARCH")
14+
done
15+
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
25+
# shellcheck disable=SC1090,SC1091
26+
. "$TOOLS/functestlib.sh"
27+
28+
TESTNAME="Camera_RDI_FrameCapture"
29+
RES_FILE="./$TESTNAME.res"
30+
test_path=$(find_test_case_by_name "$TESTNAME")
31+
cd "$test_path" || exit 1
32+
33+
print_usage() {
34+
cat <<EOF
35+
Usage: $0 [--format <v4l2_fmt1,v4l2_fmt2,...>] [--frames <count>] [--help]
36+
37+
Options:
38+
--format <v4l2_fmt1,v4l2_fmt2,...> Test one or more comma-separated formats (e.g., UYVY,NV12)
39+
--frames <count> Number of frames to capture per pipeline (default: 10)
40+
--help Show this help message
41+
EOF
42+
}
43+
44+
log_info "----------------------------------------------------------------------"
45+
log_info "------------------- Starting $TESTNAME Testcase ----------------------"
46+
log_info "=== Test Initialization ==="
47+
48+
# --------- Argument Parsing ---------
49+
USER_FORMAT=""
50+
FRAMES=10
51+
while [ $# -gt 0 ]; do
52+
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+
;;
70+
esac
71+
shift
72+
done
73+
74+
# --------- Prechecks ---------
75+
if ! dt_confirm_node_or_compatible "isp" "cam" "camss"; then
76+
log_skip "$TESTNAME SKIP – No ISP/camera node/compatible found in DT"
77+
echo "$TESTNAME SKIP" >"$RES_FILE"
78+
exit 0
79+
fi
80+
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'
84+
85+
if ! is_module_loaded "$DRIVER_MOD"; then
86+
log_skip "$TESTNAME SKIP – Driver module $DRIVER_MOD not loaded"
87+
echo "$TESTNAME SKIP" >"$RES_FILE"
88+
exit 0
89+
fi
90+
91+
if scan_dmesg_errors "$SCRIPT_DIR" "$DMESG_MODULES" "$DMESG_EXCLUDE"; then
92+
log_skip "$TESTNAME SKIP – $DRIVER_MOD probe errors detected in dmesg"
93+
echo "$TESTNAME SKIP" >"$RES_FILE"
94+
exit 0
95+
fi
96+
97+
# --------- Dependency Checks ---------
98+
check_dependencies media-ctl yavta python3 v4l2-ctl || {
99+
log_skip "$TESTNAME SKIP – Required tools missing"
100+
echo "$TESTNAME SKIP" >"$RES_FILE"
101+
exit 0
102+
}
103+
104+
# --------- Media Node Detection ---------
105+
MEDIA_NODE=$(detect_media_node)
106+
if [ -z "$MEDIA_NODE" ]; then
107+
log_skip "$TESTNAME SKIP – Media node not found"
108+
echo "$TESTNAME SKIP" >"$RES_FILE"
109+
exit 0
110+
fi
111+
log_info "Detected media node: $MEDIA_NODE"
112+
113+
# --------- Pipeline Detection ---------
114+
TOPO_FILE=$(mktemp "/tmp/${TESTNAME}_topo.XXXXXX")
115+
TMP_PIPELINES_FILE=$(mktemp "/tmp/${TESTNAME}_blocks.XXXXXX")
116+
trap 'rm -f "$TOPO_FILE" "$TMP_PIPELINES_FILE"' EXIT
117+
118+
media-ctl -p -d "$MEDIA_NODE" >"$TOPO_FILE" 2>/dev/null
119+
PYTHON_PIPELINES=$(run_camera_pipeline_parser "$TOPO_FILE")
120+
if [ -z "$PYTHON_PIPELINES" ]; then
121+
log_skip "$TESTNAME SKIP – No valid pipelines found"
122+
echo "$TESTNAME SKIP" >"$RES_FILE"
123+
exit 0
124+
fi
125+
126+
printf "%s\n" "$PYTHON_PIPELINES" > "$TMP_PIPELINES_FILE"
127+
128+
log_info "User format override: ${USER_FORMAT:-<none>}"
129+
log_info "Frame count per pipeline: $FRAMES"
130+
131+
# --------- Pipeline Processing ---------
132+
PASS=0; FAIL=0; SKIP=0; COUNT=0
133+
block=""
134+
135+
while IFS= read -r line || [ -n "$line" ]; do
136+
if [ "$line" = "--" ]; then
137+
COUNT=$((COUNT+1))
138+
TMP="/tmp/cam_block.$$.$COUNT"
139+
printf "%s\n" "$block" > "$TMP"
140+
141+
# Parses block and sets SENSOR, VIDEO, YAVTA_DEV, FMT, etc
142+
parse_pipeline_block "$TMP"
143+
rm -f "$TMP"
144+
145+
# -------- Multi-format support (POSIX style, no arrays) --------
146+
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
151+
152+
OLD_IFS="$IFS"
153+
IFS=','
154+
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"
158+
159+
log_info "----- Pipeline $COUNT: ${SENSOR:-unknown} $VIDEO $TARGET_FORMAT -----"
160+
161+
if [ -z "$VIDEO" ] || [ "$VIDEO" = "None" ] || [ -z "$YAVTA_DEV" ]; then
162+
log_skip "$SENSOR: Invalid pipeline – skipping"
163+
SKIP=$((SKIP+1))
164+
continue
165+
fi
166+
167+
configure_pipeline_block "$MEDIA_NODE" "$TARGET_FORMAT"
168+
execute_capture_block "$FRAMES" "$TARGET_FORMAT"
169+
RET=$?
170+
171+
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+
;;
188+
esac
189+
done
190+
IFS="$OLD_IFS"
191+
block=""
192+
else
193+
if [ -z "$block" ]; then
194+
block="$line"
195+
else
196+
block="$block
197+
$line"
198+
fi
199+
fi
200+
done < "$TMP_PIPELINES_FILE"
201+
202+
log_info "Test Summary: Passed: $PASS, Failed: $FAIL, Skipped: $SKIP"
203+
if [ "$PASS" -gt 0 ]; then
204+
echo "$TESTNAME PASS" >"$RES_FILE"
205+
elif [ "$FAIL" -gt 0 ]; then
206+
echo "$TESTNAME FAIL" >"$RES_FILE"
207+
else
208+
echo "$TESTNAME SKIP" >"$RES_FILE"
209+
fi
210+
211+
exit 0

0 commit comments

Comments
 (0)