Merge lp:~brendan-donegan/checkbox/add_camera_tests into lp:checkbox

Proposed by Brendan Donegan
Status: Merged
Merged at revision: 923
Proposed branch: lp:~brendan-donegan/checkbox/add_camera_tests
Merge into: lp:checkbox
Diff against target: 200 lines (+191/-0)
2 files modified
jobs/camera.txt (+48/-0)
scripts/camera_test (+143/-0)
To merge this branch: bzr merge lp:~brendan-donegan/checkbox/add_camera_tests
Reviewer Review Type Date Requested Status
Marc Tardif (community) Approve
Review via email: mp+64399@code.launchpad.net

Description of the change

As part of the story coming up to kill checkbox-certification and compatibility once and for all, this a proposal to shift the camera tests from compatibility to base checkbox. The tests take up a minimal amount of space (6KB between the job file and the script) and perform very useful tests, so would be ideal to include in base checkbox directly (rather than any kind of 'enhanced' package for more obscure tests used mainly be this certification team)

There is a corresponding changeset to remove the same test from compatibility.

To post a comment you must log in.
Revision history for this message
Marc Tardif (cr3) wrote :

Looks good, merging.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'jobs/camera.txt'
2--- jobs/camera.txt 1970-01-01 00:00:00 +0000
3+++ jobs/camera.txt 2011-06-13 12:51:03 +0000
4@@ -0,0 +1,48 @@
5+plugin: shell
6+name: camera/detect
7+requires:
8+ package.name == 'xawtv'
9+ device.category == 'CAPTURE'
10+command: camera_test -t detect
11+description: Automated test case that attempts to detect a camera
12+
13+plugin: manual
14+name: camera/display
15+depends: camera/detect
16+requires:
17+ package.name == 'python-gst0.10'
18+ device.category == 'CAPTURE'
19+command: camera_test -t display
20+description:
21+ Select Test to display a video capture from the camera
22+ .
23+ Did you see the video capture?
24+
25+plugin: manual
26+name: camera/still
27+depends: camera/detect
28+requires:
29+ package.name == 'python-gst0.10'
30+ package.name == 'eog'
31+ package.name == 'xawtv'
32+ device.category == 'CAPTURE'
33+command: camera_test -t still
34+description:
35+ Select Test to display a still image from the camera
36+ .
37+ Did you see the image?
38+
39+plugin: manual
40+name: camera/video
41+depends: camera/detect
42+requires:
43+ package.name == 'python-gst0.10'
44+ package.name == 'totem'
45+ device.category == 'CAPTURE'
46+command: camera_test -t video
47+description:
48+ Select Test to capture video to a file and open it in totem.
49+ Please make sure that both audio and video is captured.
50+ .
51+ Did you see/hear the capture?
52+
53
54=== added file 'scripts/camera_test'
55--- scripts/camera_test 1970-01-01 00:00:00 +0000
56+++ scripts/camera_test 2011-06-13 12:51:03 +0000
57@@ -0,0 +1,143 @@
58+#!/usr/bin/python
59+
60+import sys, time, tempfile, re
61+from subprocess import check_call as call
62+from subprocess import CalledProcessError, Popen, PIPE, STDOUT
63+
64+from optparse import OptionParser
65+
66+import gobject
67+
68+class CameraTest:
69+ """
70+ A simple class that displays a test image via GStreamer.
71+ """
72+ def __init__(self):
73+ self._mainloop = gobject.MainLoop()
74+ self._width = 640
75+ self._height = 480
76+
77+
78+ def detect(self):
79+ """
80+ Display information regarding webcam hardware
81+ """
82+ process = Popen(["xawtv", "-hwscan"], stdout=PIPE, stderr=STDOUT)
83+ (output, _) = process.communicate()
84+
85+ output = "\n".join([line for line in output.splitlines()[2:]
86+ if line])
87+ print output
88+
89+ if re.search('^/dev/video\d+:\s+OK', output, re.M):
90+ return 0
91+ else:
92+ return 1
93+
94+
95+ def led(self):
96+ """
97+ Activate camera (switch on led), but don't display any output
98+ """
99+ pipespec=("autovideosrc "
100+ "! video/x-raw-yuv "
101+ "! ffmpegcolorspace "
102+ "! testsink")
103+ self._pipeline = gst.parse_launch(pipespec)
104+ self._pipeline.set_state(gst.STATE_PLAYING)
105+ time.sleep(3)
106+ self._pipeline.set_state(gst.STATE_READY)
107+
108+
109+ def display(self):
110+ """
111+ Displays the preview window
112+ """
113+ pipespec=("autovideosrc "
114+ "! video/x-raw-yuv,width=%(width)d,height=%(height)d "
115+ "! ffmpegcolorspace "
116+ "! autovideosink"
117+ % {'width': self._width,
118+ 'height': self._height})
119+ self._pipeline = gst.parse_launch(pipespec)
120+ self._pipeline.set_state(gst.STATE_PLAYING)
121+ time.sleep(3)
122+ self._pipeline.set_state(gst.STATE_READY)
123+
124+
125+ def still(self):
126+ """
127+ Captures an image to a file
128+ """
129+ with tempfile.NamedTemporaryFile(prefix='camera_test_',
130+ suffix='.jpg',
131+ delete=True) as file:
132+ try:
133+ call(["v4lctl", "snap", "jpeg",
134+ "%dx%d" % (self._width, self._height), file.name])
135+ call(["eog", file.name])
136+ except CalledProcessError:
137+ pipespec=("autovideosrc "
138+ "! video/x-raw-yuv,width=%(width)d,height=%(height)d "
139+ "! ffmpegcolorspace "
140+ "! jpegenc "
141+ "! filesink location=%(filename)s"
142+ % {'width': self._width,
143+ 'height': self._height,
144+ 'filename': file.name})
145+ self._pipeline = gst.parse_launch(pipespec)
146+ self._pipeline.set_state(gst.STATE_PLAYING)
147+ time.sleep(3)
148+ self._pipeline.set_state(gst.STATE_READY)
149+ call(["eog", file.name])
150+
151+
152+ def video(self, duration=5):
153+ """
154+ Captures a short movie to a file
155+ """
156+ with tempfile.NamedTemporaryFile(prefix='camera_test_',
157+ suffix='.avi',
158+ delete=True) as file:
159+ pipespec=("autoaudiosrc "
160+ "! audio/x-raw-int,rate=44100,channels=2 "
161+ "! multiqueue ! mux. "
162+ "autovideosrc "
163+ "! video/x-raw-yuv,width=%(width)d,height=%(height)d "
164+ "! multiqueue ! mux. "
165+ "avimux name=mux "
166+ "! filesink location=%(filename)s"
167+ % {'width': self._width,
168+ 'height': self._height,
169+ 'filename': file.name})
170+ self._pipeline = gst.parse_launch(pipespec)
171+ self._pipeline.set_state(gst.STATE_PLAYING)
172+ time.sleep(duration)
173+ self._pipeline.set_state(gst.STATE_READY)
174+ call(["totem", file.name])
175+
176+
177+def parse_arguments(argv):
178+ """
179+ Parse command line arguments
180+ """
181+ tests = ['detect', 'display', 'still', 'video', 'led']
182+ parser = OptionParser(description = "Run a camera-related test")
183+ parser.add_option("-t", "--test", choices=tests,
184+ default=tests[0],
185+ help=("Test to execute (available choices: %s or %s)"
186+ % (", ".join(tests[:-1]), tests[-1])))
187+ return parser.parse_args(argv)[0]
188+
189+
190+if __name__ == "__main__":
191+ options = parse_arguments(sys.argv[1:])
192+
193+ # Import gst only for the test cases that will need it
194+ if options.test in ['display', 'still', 'video', 'led']:
195+ import pygst
196+ pygst.require("0.10")
197+ import gst
198+
199+ camera = CameraTest()
200+ sys.exit(getattr(camera, options.test)())

Subscribers

People subscribed via source and target branches