-
Notifications
You must be signed in to change notification settings - Fork 30
Ci: testing frame order and fps #329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
b8a7a7d
b7c7239
933728e
cd30c11
8b79c77
d9e3acd
c8dcd4b
f8af750
c6c1177
193b8cb
0c78331
5d81889
84c4c6f
c5c5215
5421f88
f993ef1
30bb9c3
0d66c52
7dc7fd3
f3101ae
8461377
d483738
6f2d76c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import org.jenkinsci.plugins.workflow.steps.FlowInterruptedException | ||
|
|
||
| pipeline { | ||
| agent { label 'jetson && jetpack && camera' } | ||
|
|
||
| options { | ||
| timestamps() | ||
| timeout(time: 10, unit: 'MINUTES') | ||
| } | ||
|
|
||
| stages { | ||
| stage('pytest') { | ||
| steps { | ||
| script { | ||
| sh 'pytest --tb=no test' | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [pytest] | ||
| markers = | ||
| d457: realsesne D457 camera | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this marker mean the CI will work only on D457?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declaring a marker here helps avoid a warning by pytest for a line like: @pytest.mark.d457
Kontra2B marked this conversation as resolved.
Outdated
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import subprocess | ||
| import pytest | ||
| import re | ||
|
|
||
| @pytest.mark.d457 | ||
| @pytest.mark.parametrize("frames", {20}) | ||
| @pytest.mark.parametrize("device", {'0', '2'}) | ||
| def test_fps(device, frames): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. device mean video0? so this test is testing only one stream at a time?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2 devices: /dev/video0 and /dev/video2. 2 test are executed. One for each device at a time. Can be run in parallel with pytest plugin pytest-xdist. |
||
| try: | ||
| print(f"\nDevice: {device}") | ||
| formats = get_formats(device) | ||
| for w, h in formats: | ||
| print(f"Format: {w}x{h}") | ||
| for FPS in formats[(w, h)]: | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| f"--set-fmt-video=width={w},height={h}", | ||
| ] | ||
| subprocess.check_call(cmd) | ||
| print(f"FPS/{FPS}:", end='') | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| "-p", | ||
| f"{FPS}", | ||
| ] | ||
| subprocess.check_call(cmd, stdout=subprocess.DEVNULL) | ||
| cmd = [ "v4l2-ctl", | ||
| f"-d{device}", | ||
| "--stream-mmap", | ||
| "--stream-count", | ||
| f"{frames}", | ||
| "--verbose", | ||
| ] | ||
| timeout = 5.0 * frames / FPS | ||
| output = subprocess.run(cmd, | ||
| check=True, | ||
| text=True, | ||
| capture_output=True, | ||
| timeout=timeout).stderr.splitlines() | ||
| last = None | ||
| kpi = 5 # [%] | ||
| for line in output: | ||
| m = re.search(r"cap dqbuf:.*seq:\s*(\d*)\s*bytesused:.*", line) | ||
| if m: | ||
| frame = int(m.group(1)) | ||
| print(f"{frame}", end='') | ||
| if last: | ||
| assert frame > last, f"Repeated frame: {frame}" | ||
| assert (frame - last) < 3 , f"Frames dropped between: {last} and {frame}" | ||
| m = re.search(r"cap dqbuf:.*bytesused:.*fps:\s*(\d+\.\d+)\s*.*", line) | ||
| if m: | ||
| fps = float(m.group(1)) | ||
| print(f"/{fps}", end=',') | ||
| assert fps > FPS * (1 - kpi/100), f"FPS too low: {fps}/{FPS}" | ||
| assert fps < FPS * (1 + kpi/100), f"FPS too high: {fps}/{FPS}" | ||
| else: | ||
| print(end=',') | ||
| last = frame | ||
| print() | ||
| assert last, "No frames arrived" | ||
| except subprocess.TimeoutExpired: | ||
| assert False, "No frames arrived" | ||
|
|
||
| def get_formats(device): | ||
| cmd = [ "v4l2-ctl", | ||
| "-d" + device, | ||
| "--list-formats-ext", | ||
| ] | ||
| output = subprocess.run(cmd, | ||
| check=True, | ||
| text=True, | ||
| capture_output=True | ||
| ).stdout.splitlines() | ||
| formats = {} | ||
| last = None | ||
| for line in output: | ||
| m = re.search(r"\s*Size: Discrete\s*(\d+)x(\d+)", line) | ||
| if m: | ||
| w = int(m.group(1)) | ||
| h = int(m.group(2)) | ||
| last = (w ,h) | ||
|
||
| if not last in formats: | ||
| formats[last] = set() | ||
| continue | ||
| m = re.search(r"\s*Interval: Discrete.*\((\d+\.\d+)\s+fps\)", line) | ||
| if m: | ||
| fps = float(m.group(1)) | ||
| if last: | ||
| formats[last].add(fps) | ||
| return formats | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The command uses mixed indentation (tabs). Consider using consistent indentation (spaces) to match typical Groovy/Jenkins pipeline conventions.