Merge lp:~sylvain-pineau/checkbox/camera_test_cheese_introspection into lp:checkbox

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: 4301
Merged at revision: 4303
Proposed branch: lp:~sylvain-pineau/checkbox/camera_test_cheese_introspection
Merge into: lp:checkbox
Diff against target: 233 lines (+90/-77)
2 files modified
providers/plainbox-provider-checkbox/bin/camera_test (+86/-77)
providers/plainbox-provider-checkbox/jobs/camera.txt.in (+4/-0)
To merge this branch: bzr merge lp:~sylvain-pineau/checkbox/camera_test_cheese_introspection
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Approve
Taihsiang Ho Pending
Pierre Equoy Pending
Review via email: mp+291712@code.launchpad.net

This proposal supersedes a proposal from 2016-04-11.

Description of the change

This MR removes all gstreamer pipelines from the camera_test script. This new version relies on libcheese as creating a camera bin is not something we want to maintain in the checkbox provider.

WARNING:

DO not merge without the packaging branch update first.

To post a comment you must log in.
Revision history for this message
Taihsiang Ho (tai271828) wrote : Posted in a previous version of this proposal

"./camera still"
works well on dino2 (CID 201508-18005) besides one small inline comment (please see below)

-------------

"./camera display"
crashed. The error message is:

http://paste.ubuntu.com/15760725/

./camera_test:570: PyGIWarning: Cheese was imported without specifying a version first. Use gi.require_version('Cheese', '3.0') before import to ensure that the right version gets loaded.
  from gi.repository import Cheese
Traceback (most recent call last):
  File "./camera_test", line 575, in <module>
    sys.exit(getattr(camera, args.test)())
  File "./camera_test", line 248, in display
    camera.set_device_by_device_node(self.args.device)
AttributeError: 'Camera' object has no attribute 'set_device_by_device_node'

review: Needs Fixing
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote : Posted in a previous version of this proposal

Thnaks for the review Tai. I made a few changes to support Xenial, resubmitting for review

review: Needs Resubmitting
Revision history for this message
Taihsiang Ho (tai271828) wrote : Posted in a previous version of this proposal

on dino2 (CID 201508-18005)

* "./camera still" works well
* "./camera display" pops up a window and there is nothing (all white panel) in the window together with the following message in the console:

ubuntu@201508-18805:~/camera_test_cheese_introspection/providers/plainbox-provider-checkbox/bin$ ./camera_test display

(python3:2218): cheese-WARNING **: Internal GStreamer error: code not implemented. Please file a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer.: gstvideofilter.c(292): gst_video_filter_transform (): /GstCameraBin:camerabin/GstViewfinderBin:vf-bin/GstVideoConvert:vfbin-csp:
invalid video buffer received

(python3:2218): cheese-WARNING **: Internal GStreamer error: code not implemented. Please file a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer.: gstvideofilter.c(292): gst_video_filter_transform (): /GstCameraBin:camerabin/GstViewfinderBin:vf-bin/GstVideoConvert:vfbin-csp:
invalid video buffer received

Revision history for this message
Taihsiang Ho (tai271828) wrote : Posted in a previous version of this proposal

test on another XPS (CID 201309-14238)

both of still and display works.

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote : Posted in a previous version of this proposal

Another xenial api change... the camera constructor expects a Clutter.Actor instead of a Clutter.Texture. I changed the code to handle both cases. Tested the daily build it works for me. Could you do another round with the dino hw please?

review: Needs Resubmitting
Revision history for this message
Pierre Equoy (pieq) wrote : Posted in a previous version of this proposal

Tested successfully on:

- One Dino 2 device with Trusty
- One Dino 2 device with Xenial
- One Chiclet 15 device with Xenial

In all cases, I got the expected results for camera/detect, camera/still, camera/display and camera/multiple=resolution-images tests (from the Certification Test Plan).

review: Approve
Revision history for this message
Taihsiang Ho (tai271828) wrote : Posted in a previous version of this proposal

more info:

my above test on a XPS (CID 201309-14238) was tested on Trusty. Sorry for unclear statement.

https://code.launchpad.net/~sylvain-pineau/checkbox/camera_test_cheese_introspection/+merge/291499/comments/747099

Revision history for this message
Taihsiang Ho (tai271828) wrote : Posted in a previous version of this proposal

tested on a XPS (CID 201309-14238) with Xenial daily build (built on Apr. 7th)
both of camera still and display looks good.

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote : Posted in a previous version of this proposal
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

I'm creating a new version of the same MR in order to remove the prerequisite branch. It was a mistake a the targeted branch was not trunk but the ppa packaging branch. Tarmac didn’t like that

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'providers/plainbox-provider-checkbox/bin/camera_test'
2--- providers/plainbox-provider-checkbox/bin/camera_test 2016-02-13 13:21:18 +0000
3+++ providers/plainbox-provider-checkbox/bin/camera_test 2016-04-13 08:13:58 +0000
4@@ -164,13 +164,10 @@
5 """
6 A simple class that displays a test image via GStreamer.
7 """
8- def __init__(self, args, gst_plugin=None, gst_video_type=None):
9+ def __init__(self, args):
10 self.args = args
11- self._mainloop = GObject.MainLoop()
12 self._width = 640
13 self._height = 480
14- self._gst_plugin = gst_plugin
15- self._gst_video_type = gst_video_type
16
17 def detect(self):
18 """
19@@ -204,51 +201,62 @@
20 else '',
21 ' ]', sep="")
22
23- resolutions = self._get_supported_resolutions(device)
24- print(' ',
25- self._supported_resolutions_to_string(resolutions).replace(
26- "\n", " "),
27- sep="")
28+ resolutions = self._supported_resolutions_to_string(
29+ self._get_supported_resolutions(device))
30+ resolutions = resolutions.replace(
31+ "Resolutions:", " Resolutions:")
32+ resolutions = resolutions.replace("Format:", " Format:")
33+ print(resolutions)
34
35 if cp.capabilities & V4L2_CAP_VIDEO_CAPTURE:
36 cap_status = 0
37 return dev_status | cap_status
38
39+ def _on_destroy(self, *args):
40+ Clutter.main_quit()
41+
42+ def _take_photo(self, *args):
43+ Cheese.Camera.take_photo(self.camera, self.filename)
44+
45 def led(self):
46 """
47 Activate camera (switch on led), but don't display any output
48 """
49- pipespec = ("v4l2src device=%(device)s "
50- "! %(type)s "
51- "! %(plugin)s "
52- "! testsink"
53- % {'device': self.args.device,
54- 'type': self._gst_video_type,
55- 'plugin': self._gst_plugin})
56- logging.debug("LED test with pipeline %s", pipespec)
57- self._pipeline = Gst.parse_launch(pipespec)
58- self._pipeline.set_state(Gst.State.PLAYING)
59- time.sleep(3)
60- self._pipeline.set_state(Gst.State.NULL)
61+ Clutter.threads_add_timeout(0, 3000, self._on_destroy, None, None)
62+ video_texture = Clutter.Actor()
63+ try:
64+ camera = Cheese.Camera.new(
65+ video_texture, self.args.device, self._width, self._height)
66+ except TypeError: # libcheese < 3.18 still use Clutter.Texture
67+ video_texture = Clutter.Texture()
68+ camera = Cheese.Camera.new(
69+ video_texture, self.args.device, self._width, self._height)
70+ Cheese.Camera.setup(camera, None)
71+ Cheese.Camera.play(camera)
72+ Clutter.main()
73
74 def display(self):
75 """
76 Displays the preview window
77 """
78- pipespec = ("v4l2src device=%(device)s "
79- "! %(type)s,width=%(width)d,height=%(height)d "
80- "! %(plugin)s "
81- "! autovideosink"
82- % {'device': self.args.device,
83- 'type': self._gst_video_type,
84- 'width': self._width,
85- 'height': self._height,
86- 'plugin': self._gst_plugin})
87- logging.debug("display test with pipeline %s", pipespec)
88- self._pipeline = Gst.parse_launch(pipespec)
89- self._pipeline.set_state(Gst.State.PLAYING)
90- time.sleep(10)
91- self._pipeline.set_state(Gst.State.NULL)
92+ stage = Clutter.Stage()
93+ stage.set_title('Camera test')
94+ stage.set_size(self._width, self._height)
95+ stage.connect('destroy', self._on_destroy)
96+ Clutter.threads_add_timeout(0, 10000, self._on_destroy, None, None)
97+ video_texture = Clutter.Actor()
98+ try:
99+ camera = Cheese.Camera.new(
100+ video_texture, self.args.device, self._width, self._height)
101+ except TypeError: # libcheese < 3.18 still use Clutter.Texture
102+ video_texture = Clutter.Texture()
103+ camera = Cheese.Camera.new(
104+ video_texture, self.args.device, self._width, self._height)
105+ stage.add_actor(video_texture)
106+ Cheese.Camera.setup(camera, None)
107+ Cheese.Camera.play(camera)
108+ stage.show()
109+ Clutter.main()
110
111 def still(self):
112 """
113@@ -272,7 +280,7 @@
114 "-d", self.args.device,
115 "-r", "%dx%d"
116 % (width, height), filename]
117- use_gstreamer = False
118+ use_cheese = False
119 if pixelformat:
120 if 'MJPG' == pixelformat: # special tweak for fswebcam
121 pixelformat = 'MJPEG'
122@@ -281,40 +289,37 @@
123 try:
124 check_call(command, stdout=open(os.devnull, 'w'), stderr=STDOUT)
125 except (CalledProcessError, OSError):
126- use_gstreamer = True
127+ use_cheese = True
128
129- if use_gstreamer:
130- pipespec = ("v4l2src device=%(device)s "
131- "! %(type)s,width=%(width)d,height=%(height)d "
132- "! %(plugin)s "
133- "! jpegenc "
134- "! filesink location=%(filename)s"
135- % {'device': self.args.device,
136- 'type': self._gst_video_type,
137- 'width': width,
138- 'height': height,
139- 'plugin': self._gst_plugin,
140- 'filename': filename})
141- logging.debug("still test with gstreamer and "
142- "pipeline %s", pipespec)
143- self._pipeline = Gst.parse_launch(pipespec)
144- self._pipeline.set_state(Gst.State.PLAYING)
145- time.sleep(3)
146- self._pipeline.set_state(Gst.State.NULL)
147+ if use_cheese:
148+ stage = Clutter.Stage()
149+ stage.connect('destroy', self._on_destroy)
150+ video_texture = Clutter.Actor()
151+ try:
152+ self.camera = Cheese.Camera.new(
153+ video_texture, self.args.device, self._width, self._height)
154+ except TypeError: # libcheese < 3.18 still use Clutter.Texture
155+ video_texture = Clutter.Texture()
156+ self.camera = Cheese.Camera.new(
157+ video_texture, self.args.device, self._width, self._height)
158+ Cheese.Camera.setup(self.camera, None)
159+ Cheese.Camera.play(self.camera)
160+ self.filename = filename
161+ Clutter.threads_add_timeout(0, 3000, self._take_photo , None, None)
162+ Clutter.threads_add_timeout(0, 4000, self._on_destroy, None, None)
163+ Clutter.main()
164+ Cheese.Camera.stop(self.camera)
165
166 if not quiet:
167- import imghdr
168- image_type = imghdr.what(filename)
169- pipespec = ("filesrc location=%(filename)s ! "
170- "%(type)sdec ! "
171- "videoscale ! "
172- "imagefreeze ! autovideosink"
173- % {'filename': filename,
174- 'type': image_type})
175- self._pipeline = Gst.parse_launch(pipespec)
176- self._pipeline.set_state(Gst.State.PLAYING)
177- time.sleep(10)
178- self._pipeline.set_state(Gst.State.NULL)
179+ stage = Clutter.Stage()
180+ stage.set_title('Camera still picture test')
181+ stage.set_size(width, height)
182+ stage.connect('destroy', self._on_destroy)
183+ Clutter.threads_add_timeout(0, 10000, self._on_destroy, None, None)
184+ still_texture = Clutter.Texture.new_from_file(filename)
185+ stage.add_actor(still_texture)
186+ stage.show()
187+ Clutter.main()
188
189 def _supported_resolutions_to_string(self, supported_resolutions):
190 """
191@@ -563,16 +568,20 @@
192
193 # Import Gst only for the test cases that will need it
194 if args.test in ['display', 'still', 'led', 'resolutions']:
195+ import contextlib
196+ # Workaround to avoid "cluttervideosink missing"
197+ # See https://bugzilla.gnome.org/show_bug.cgi?id=721277
198+ with contextlib.suppress(FileNotFoundError):
199+ gst_registry = '~/.cache/gstreamer-1.0/registry.x86_64.bin'
200+ os.remove(os.path.expanduser(gst_registry))
201+ import gi
202+ gi.require_version('Gst', '1.0')
203 from gi.repository import Gst
204- if Gst.version()[0] > 0:
205- gst_plugin = 'videoconvert'
206- gst_video_type = 'video/x-raw'
207- else:
208- gst_plugin = 'ffmpegcolorspace'
209- gst_video_type = 'video/x-raw-yuv'
210+ gi.require_version('Cheese', '3.0')
211+ from gi.repository import Cheese
212+ gi.require_version('Clutter', '1.0')
213+ from gi.repository import Clutter
214 Gst.init(None)
215- camera = CameraTest(args, gst_plugin, gst_video_type)
216- else:
217- camera = CameraTest(args)
218-
219+ Clutter.init()
220+ camera = CameraTest(args)
221 sys.exit(getattr(camera, args.test)())
222
223=== modified file 'providers/plainbox-provider-checkbox/jobs/camera.txt.in'
224--- providers/plainbox-provider-checkbox/jobs/camera.txt.in 2015-09-08 22:04:46 +0000
225+++ providers/plainbox-provider-checkbox/jobs/camera.txt.in 2016-04-13 08:13:58 +0000
226@@ -1,3 +1,7 @@
227+unit: packaging meta-data
228+os-id: debian
229+Depends: gir1.2-cheese-3.0
230+
231 plugin: shell
232 category_id: 2013.com.canonical.plainbox::camera
233 id: camera/detect

Subscribers

People subscribed via source and target branches