Merge lp:~bladernr/checkbox/1100594-fix-camera_test-new-gir1.2 into lp:checkbox

Proposed by Jeff Lane 
Status: Merged
Approved by: Brendan Donegan
Approved revision: 2104
Merged at revision: 2101
Proposed branch: lp:~bladernr/checkbox/1100594-fix-camera_test-new-gir1.2
Merge into: lp:checkbox
Diff against target: 279 lines (+79/-47)
3 files modified
debian/changelog (+3/-0)
jobs/camera.txt.in (+0/-1)
scripts/camera_test (+76/-46)
To merge this branch: bzr merge lp:~bladernr/checkbox/1100594-fix-camera_test-new-gir1.2
Reviewer Review Type Date Requested Status
Brendan Donegan (community) Approve
Jeff Lane  Needs Resubmitting
Review via email: mp+162209@code.launchpad.net

Description of the change

fixes camera test by adding bits to determine what version of gst we're using and then set the plugin and video type appropriately for either 0.10 or 1.x. This resolves a problem when fswebcam is not present and we fall back to gst.

Fixed the error handling for the fswebcam call to avoid having nested tracebacks that can be confusing. Now if the call to fswebcam fails, we instead trap the error and run the fallback code outside the exception. If THAT fails, we'll get a less confusing traceback now.

Removed an extraneous line in the requires for one of the camera test jobs (listed gir1.2 twice)

To post a comment you must log in.
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

There seem to be some pep8 errors in your code related to spacing between ',' mainly. I can't remember for certain but I think this may cause Tarmac to reject the submission. Also I'm curious about the comment about fswebcam above - I have fswebcam installed on my system and still get this error. Is there a further problem in the script related to that? Probably best to check it out now.

review: Needs Fixing
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

- package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'

This is a bit wrong in general (not the actual change but stuff really required). Anything that uses gir needs to depend on python3-gi

2099. By Jeff Lane 

"[r=zkrynicki][bug=1103647][author=bladernr] automatic merge by tarmac"

2100. By Brendan Donegan

"[r=zkrynicki][bug=1093718][author=brendan-donegan] automatic merge by tarmac"

2101. By Jeff Lane 

Fixed camera_test to work with both gir1.2-0.10 and gir1.2-1.x

2102. By Jeff Lane 

Removed an exraneous requires line in one of the camera test jobs

2103. By Jeff Lane 

Fixed problems with camera_test in Raring with gir1.2-1.0.6 changes

2104. By Jeff Lane 

Fixed a problem where running camera_test without a test specified resulted in a traceback. A lot of PEP8 fixes

Revision history for this message
Jeff Lane  (bladernr) wrote :

Brendan: fixed my two pep8 errors (spaces) the rest are original to sylvain's code. I've fixed all of those but one because no matter what I tried, I couldn't keep it from generating several more pep8 problems that were seemingly unsolvable. But this one remaining one has been in the test for a long while now so it shouldn't affect things, I hope.

As for fswebcam, it's not specifically the lack of fswebcam, that just brought it to the attention of the guy who reported the bug initially. IIRC, you mentioned the "display" test, which uses gstreamer to create the display window, so I'd expect you would see that bug there.

If this updated script doesn't resolve it on your end, there may be more going on than simply setting the right plugin and video type for gstreamer.

Zygmunt: Yeah, probably so, there are 17 scripts that rely on python3-gi, none of which list it as a requirement. I'm not going to fix those here. That said, however, python3-gi is required for installing checkbox itself, rathter than just a suggests. Then again, so are the gir1.2 packages, so really, neither of those should be required on a test by test basis, you'd think, since they're already required for installing checkbox to begin with.

Anyway, here's a new version with fixes to some problems I didn't catch the first time, and a rash of PEP8 fixes as well.

review: Needs Resubmitting
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

To me it looks fine then. I hope Tarmac doesn't get pissy about the pep8 errors - FYI only files which are modified get checked for errors, so that could be the reason why previous ones were missed, since this file hasn't been touched in a long time.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2013-05-03 10:47:13 +0000
+++ debian/changelog 2013-05-03 14:34:26 +0000
@@ -10,6 +10,9 @@
10 than define elements during parsing of /proc/cpuinfo (LP: #1111878)10 than define elements during parsing of /proc/cpuinfo (LP: #1111878)
11 * scripts/lsmod_info: Corrected error handling for the check_output() call to11 * scripts/lsmod_info: Corrected error handling for the check_output() call to
12 trap the correct error. (LP: #1103647)12 trap the correct error. (LP: #1103647)
13 * jobs/camera.txt.in: removed an extraneous requres line for gir1.2
14 scripts/camera_test: added code to determine what version of gst we're
15 using and set video type and plugin accordingly. (LP: #1100594)
1316
14 [ Sylvain Pineau ]17 [ Sylvain Pineau ]
15 * jobs/suspend.txt.in, scripts/gpu_test: Remove the need of running the script18 * jobs/suspend.txt.in, scripts/gpu_test: Remove the need of running the script
1619
=== modified file 'jobs/camera.txt.in'
--- jobs/camera.txt.in 2012-11-06 17:11:49 +0000
+++ jobs/camera.txt.in 2013-05-03 14:34:26 +0000
@@ -9,7 +9,6 @@
9name: camera/display9name: camera/display
10depends: camera/detect10depends: camera/detect
11requires:11requires:
12 package.name == 'gir1.2-gst-plugins-base-0.10' or package.name == 'gir1.2-gst-plugins-base-1.0'
13 device.category == 'CAPTURE'12 device.category == 'CAPTURE'
14command: camera_test display13command: camera_test display
15_description:14_description:
1615
=== modified file 'scripts/camera_test'
--- scripts/camera_test 2012-11-01 11:58:46 +0000
+++ scripts/camera_test 2013-05-03 14:34:26 +0000
@@ -162,11 +162,13 @@
162 """162 """
163 A simple class that displays a test image via GStreamer.163 A simple class that displays a test image via GStreamer.
164 """164 """
165 def __init__(self, args):165 def __init__(self, args, gst_plugin=None, gst_video_type=None):
166 self.args = args166 self.args = args
167 self._mainloop = GObject.MainLoop()167 self._mainloop = GObject.MainLoop()
168 self._width = 640168 self._width = 640
169 self._height = 480169 self._height = 480
170 self._gst_plugin = gst_plugin
171 self._gst_video_type = gst_video_type
170172
171 def detect(self):173 def detect(self):
172 """174 """
@@ -186,19 +188,25 @@
186 print(" name : %s" % cp.card.decode('UTF-8'))188 print(" name : %s" % cp.card.decode('UTF-8'))
187 print(" driver : %s" % cp.driver.decode('UTF-8'))189 print(" driver : %s" % cp.driver.decode('UTF-8'))
188 print(" version: %s.%s.%s"190 print(" version: %s.%s.%s"
189 % (cp.version >> 16, (cp.version >> 8) & 0xff, cp.version & 0xff))191 % (cp.version >> 16,
192 (cp.version >> 8) & 0xff,
193 cp.version & 0xff))
190 print(" flags : 0x%x [" % cp.capabilities,194 print(" flags : 0x%x [" % cp.capabilities,
191 ' CAPTURE' if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE else '',195 ' CAPTURE' if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE
192 ' OVERLAY' if cp.capabilities & V4L2_CAP_VIDEO_OVERLAY else '',196 else '',
193 ' READWRITE' if cp.capabilities & V4L2_CAP_READWRITE else '',197 ' OVERLAY' if cp.capabilities & V4L2_CAP_VIDEO_OVERLAY
194 ' STREAMING' if cp.capabilities & V4L2_CAP_STREAMING else '',198 else '',
195 ' ]', sep="")199 ' READWRITE' if cp.capabilities & V4L2_CAP_READWRITE
200 else '',
201 ' STREAMING' if cp.capabilities & V4L2_CAP_STREAMING
202 else '',
203 ' ]', sep="")
196204
197 resolutions = self._get_supported_resolutions(device)205 resolutions = self._get_supported_resolutions(device)
198 print(' ',206 print(' ',
199 self._supported_resolutions_to_string(resolutions).replace(207 self._supported_resolutions_to_string(resolutions).replace(
200 "\n", " "),208 "\n", " "),
201 sep="")209 sep="")
202210
203 if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE:211 if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE:
204 cap_status = 0212 cap_status = 0
@@ -209,10 +217,12 @@
209 Activate camera (switch on led), but don't display any output217 Activate camera (switch on led), but don't display any output
210 """218 """
211 pipespec = ("v4l2src device=%(device)s "219 pipespec = ("v4l2src device=%(device)s "
212 "! video/x-raw-yuv "220 "! %(type)s "
213 "! ffmpegcolorspace "221 "! %(plugin)s "
214 "! testsink"222 "! testsink"
215 % {'device': self.args.device})223 % {'device': self.args.device,
224 'type': self._gst_video_type,
225 'plugin': self._gst_plugin})
216 self._pipeline = Gst.parse_launch(pipespec)226 self._pipeline = Gst.parse_launch(pipespec)
217 self._pipeline.set_state(Gst.State.PLAYING)227 self._pipeline.set_state(Gst.State.PLAYING)
218 time.sleep(10)228 time.sleep(10)
@@ -223,12 +233,14 @@
223 Displays the preview window233 Displays the preview window
224 """234 """
225 pipespec = ("v4l2src device=%(device)s "235 pipespec = ("v4l2src device=%(device)s "
226 "! video/x-raw-yuv,width=%(width)d,height=%(height)d "236 "! %(type)s,width=%(width)d,height=%(height)d "
227 "! ffmpegcolorspace "237 "! %(plugin)s "
228 "! autovideosink"238 "! autovideosink"
229 % {'device': self.args.device,239 % {'device': self.args.device,
240 'type': self._gst_video_type,
230 'width': self._width,241 'width': self._width,
231 'height': self._height})242 'height': self._height,
243 'plugin': self._gst_plugin})
232 self._pipeline = Gst.parse_launch(pipespec)244 self._pipeline = Gst.parse_launch(pipespec)
233 self._pipeline.set_state(Gst.State.PLAYING)245 self._pipeline.set_state(Gst.State.PLAYING)
234 time.sleep(10)246 time.sleep(10)
@@ -240,11 +252,11 @@
240 """252 """
241 if self.args.filename:253 if self.args.filename:
242 self._still_helper(self.args.filename, self._width, self._height,254 self._still_helper(self.args.filename, self._width, self._height,
243 self.args.quiet)255 self.args.quiet)
244 else:256 else:
245 with NamedTemporaryFile(prefix='camera_test_', suffix='.jpg') as f:257 with NamedTemporaryFile(prefix='camera_test_', suffix='.jpg') as f:
246 self._still_helper(f.name, self._width, self._height,258 self._still_helper(f.name, self._width, self._height,
247 self.args.quiet)259 self.args.quiet)
248260
249 def _still_helper(self, filename, width, height, quiet, pixelformat=None):261 def _still_helper(self, filename, width, height, quiet, pixelformat=None):
250 """262 """
@@ -253,25 +265,30 @@
253 user (quiet = True means do not display image).265 user (quiet = True means do not display image).
254 """266 """
255 command = ["fswebcam", "-S 3", "--no-banner",267 command = ["fswebcam", "-S 3", "--no-banner",
256 "-d", self.args.device,268 "-d", self.args.device,
257 "-r", "%dx%d"269 "-r", "%dx%d"
258 % (width, height), filename]270 % (width, height), filename]
271 use_gstreamer = False
259 if pixelformat:272 if pixelformat:
260 command.extend(["-p", pixelformat])273 command.extend(["-p", pixelformat])
261274
262 try:275 try:
263 check_call(command, stdout=open(os.devnull, 'w'), stderr=STDOUT)276 check_call(command, stdout=open(os.devnull, 'w'), stderr=STDOUT)
264 except (CalledProcessError, OSError):277 except (CalledProcessError, OSError):
265 pipespec = \278 use_gstreamer = True
266 ("v4l2src device=%(device)s "279
267 "! video/x-raw-yuv,width=%(width)d,height=%(height)d "280 if use_gstreamer:
268 "! ffmpegcolorspace "281 pipespec = ("v4l2src device=%(device)s "
269 "! jpegenc "282 "! %(type)s,width=%(width)d,height=%(height)d "
270 "! filesink location=%(filename)s"283 "! %(plugin)s "
271 % {'device': self.args.device,284 "! jpegenc "
272 'width': width,285 "! filesink location=%(filename)s"
273 'height': height,286 % {'device': self.args.device,
274 'filename': filename})287 'type': self._gst_video_type,
288 'width': width,
289 'height': height,
290 'plugin': self._gst_plugin,
291 'filename': filename})
275 self._pipeline = Gst.parse_launch(pipespec)292 self._pipeline = Gst.parse_launch(pipespec)
276 self._pipeline.set_state(Gst.State.PLAYING)293 self._pipeline.set_state(Gst.State.PLAYING)
277 time.sleep(3)294 time.sleep(3)
@@ -290,7 +307,7 @@
290 ret = ""307 ret = ""
291 for resolution in supported_resolutions:308 for resolution in supported_resolutions:
292 ret += "Format: %s (%s)\n" % (resolution['pixelformat'],309 ret += "Format: %s (%s)\n" % (resolution['pixelformat'],
293 resolution['description'])310 resolution['description'])
294 ret += "Resolutions: "311 ret += "Resolutions: "
295 for res in resolution['resolutions']:312 for res in resolution['resolutions']:
296 ret += "%sx%s," % (res[0], res[1])313 ret += "%sx%s," % (res[0], res[1])
@@ -314,13 +331,13 @@
314 resolution = resolutions[0]331 resolution = resolutions[0]
315 if resolution:332 if resolution:
316 print("Taking multiple images using the %s format"333 print("Taking multiple images using the %s format"
317 % resolution['pixelformat'])334 % resolution['pixelformat'])
318 for res in resolution['resolutions']:335 for res in resolution['resolutions']:
319 w = res[0]336 w = res[0]
320 h = res[1]337 h = res[1]
321 f = NamedTemporaryFile(prefix='camera_test_%s%sx%s' %338 f = NamedTemporaryFile(prefix='camera_test_%s%sx%s' %
322 (resolution['pixelformat'], w, h), suffix='.jpg',339 (resolution['pixelformat'], w, h),
323 delete=False)340 suffix='.jpg', delete=False)
324 print("Taking a picture at %sx%s" % (w, h))341 print("Taking a picture at %sx%s" % (w, h))
325 self._still_helper(f.name, w, h, True,342 self._still_helper(f.name, w, h, True,
326 pixelformat=resolution['pixelformat'])343 pixelformat=resolution['pixelformat'])
@@ -329,7 +346,7 @@
329 os.remove(f.name)346 os.remove(f.name)
330 else:347 else:
331 print("Failed to validate image %s" % f.name,348 print("Failed to validate image %s" % f.name,
332 file=sys.stderr)349 file=sys.stderr)
333 os.remove(f.name)350 os.remove(f.name)
334 return 1351 return 1
335 return 0352 return 0
@@ -354,9 +371,9 @@
354 pixelformat['pixelformat_int'] = fmt.pixelformat371 pixelformat['pixelformat_int'] = fmt.pixelformat
355 pixelformat['pixelformat'] = "%s%s%s%s" % \372 pixelformat['pixelformat'] = "%s%s%s%s" % \
356 (chr(fmt.pixelformat & 0xFF),373 (chr(fmt.pixelformat & 0xFF),
357 chr((fmt.pixelformat >> 8) & 0xFF),374 chr((fmt.pixelformat >> 8) & 0xFF),
358 chr((fmt.pixelformat >> 16) & 0xFF),375 chr((fmt.pixelformat >> 16) & 0xFF),
359 chr((fmt.pixelformat >> 24) & 0xFF))376 chr((fmt.pixelformat >> 24) & 0xFF))
360 pixelformat['description'] = fmt.description.decode()377 pixelformat['description'] = fmt.description.decode()
361 supported_formats.append(pixelformat)378 supported_formats.append(pixelformat)
362 fmt.index = fmt.index + 1379 fmt.index = fmt.index + 1
@@ -404,16 +421,18 @@
404 framesize) == 0:421 framesize) == 0:
405 if framesize.type == V4L2_FRMSIZE_TYPE_DISCRETE:422 if framesize.type == V4L2_FRMSIZE_TYPE_DISCRETE:
406 resolutions.append([framesize.discrete.width,423 resolutions.append([framesize.discrete.width,
407 framesize.discrete.height])424 framesize.discrete.height])
408 # for continuous and stepwise, let's just use min and425 # for continuous and stepwise, let's just use min and
409 # max they use the same structure and only return426 # max they use the same structure and only return
410 # one result427 # one result
411 elif framesize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS or\428 elif framesize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS or\
412 framesize.type == V4L2_FRMSIZE_TYPE_STEPWISE:429 framesize.type == V4L2_FRMSIZE_TYPE_STEPWISE:
413 resolutions.append([framesize.stepwise.min_width,430 resolutions.append([framesize.stepwise.min_width,
414 framesize.stepwise.min_height])431 framesize.stepwise.min_height]
432 )
415 resolutions.append([framesize.stepwise.max_width,433 resolutions.append([framesize.stepwise.max_width,
416 framesize.stepwise.max_height])434 framesize.stepwise.max_height]
435 )
417 break436 break
418 framesize.index = framesize.index + 1437 framesize.index = framesize.index + 1
419 except IOError as e:438 except IOError as e:
@@ -455,11 +474,11 @@
455474
456 if outw != width:475 if outw != width:
457 print("Image width does not match, was %s should be %s" %476 print("Image width does not match, was %s should be %s" %
458 (outw, width), file=sys.stderr)477 (outw, width), file=sys.stderr)
459 return False478 return False
460 if outh != height:479 if outh != height:
461 print("Image width does not match, was %s should be %s" %480 print("Image width does not match, was %s should be %s" %
462 (outh, height), file=sys.stderr)481 (outh, height), file=sys.stderr)
463 return False482 return False
464483
465 return True484 return True
@@ -519,10 +538,21 @@
519if __name__ == "__main__":538if __name__ == "__main__":
520 args = parse_arguments(sys.argv[1:])539 args = parse_arguments(sys.argv[1:])
521540
541 if not args.test:
542 args.test = 'detect'
543
522 # Import Gst only for the test cases that will need it544 # Import Gst only for the test cases that will need it
523 if args.test in ['display', 'still', 'led', 'resolutions']:545 if args.test in ['display', 'still', 'led', 'resolutions']:
524 from gi.repository import Gst546 from gi.repository import Gst
547 if Gst.version()[0] > 0:
548 gst_plugin = 'videoconvert'
549 gst_video_type = 'video/x-raw'
550 else:
551 gst_plugin = 'ffmpegcolorspace'
552 gst_video_type = 'video/x-raw-yuv'
525 Gst.init(None)553 Gst.init(None)
554 camera = CameraTest(args, gst_plugin, gst_video_type)
555 else:
556 camera = CameraTest(args)
526557
527 camera = CameraTest(args)
528 sys.exit(getattr(camera, args.test)())558 sys.exit(getattr(camera, args.test)())

Subscribers

People subscribed via source and target branches