Merge lp:~fboucault/camera-app/video_quality into lp:camera-app

Proposed by Florian Boucault
Status: Merged
Approved by: Bill Filler
Approved revision: 445
Merged at revision: 458
Proposed branch: lp:~fboucault/camera-app/video_quality
Merge into: lp:camera-app
Diff against target: 531 lines (+281/-19)
9 files modified
CameraApp/advancedcamerasettings.cpp (+39/-1)
CameraApp/advancedcamerasettings.h (+6/-0)
ViewFinderOverlay.qml (+66/-0)
debian/changelog (+7/-0)
debian/control (+1/-0)
po/camera-app.pot (+17/-17)
tests/autopilot/camera_app/emulators/main_window.py (+4/-0)
tests/autopilot/camera_app/emulators/panel.py (+1/-1)
tests/autopilot/camera_app/tests/test_capture.py (+140/-0)
To merge this branch: bzr merge lp:~fboucault/camera-app/video_quality
Reviewer Review Type Date Requested Status
Bill Filler (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Arthur Mello (community) Approve
Review via email: mp+244042@code.launchpad.net

Commit message

New option to select recording resolution in video mode.

To post a comment you must log in.
438. By Florian Boucault

Fix naming.

Revision history for this message
Arthur Mello (artmello) wrote :

lgtm

review: Approve
439. By Florian Boucault

Added autopilot tests.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
440. By Florian Boucault

Merged from trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
441. By Florian Boucault

Merged from trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
442. By Florian Boucault

Added failing autopilot test

443. By Florian Boucault

Set video resolution when switching cameras. Fixes failing AP test.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Bill Filler (bfiller) wrote :

working pretty well, only found 2 issues:

1) when recording at 480p with front camera on krillin, the resulting video aspect ratio seems incorrect. The video looks squashed. Using the back camera at this resolution doesn't have the same issue.

2) Not specific to this MR but perhaps we should fix in this MR: the bottom edge should be disabled when recording in progress to ensure no changes are made to the video quality, etc.

444. By Florian Boucault

Disable bottom edge while recording.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
445. By Florian Boucault

Workaround for stretched videos: do not allow recording at 640x480 with the front camera. Ref.: https://bugs.launchpad.net/ubuntu/+source/libhybris/+bug/1408650

Revision history for this message
Florian Boucault (fboucault) wrote :

> working pretty well, only found 2 issues:
>
> 1) when recording at 480p with front camera on krillin, the resulting video
> aspect ratio seems incorrect. The video looks squashed. Using the back camera
> at this resolution doesn't have the same issue.
>

Workarounded in this MR. Bug reported: https://bugs.launchpad.net/ubuntu/+source/libhybris/+bug/1408650

> 2) Not specific to this MR but perhaps we should fix in this MR: the bottom
> edge should be disabled when recording in progress to ensure no changes are
> made to the video quality, etc.

Fixed in this MR.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Bill Filler (bfiller) wrote :

approved

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CameraApp/advancedcamerasettings.cpp'
2--- CameraApp/advancedcamerasettings.cpp 2014-12-03 19:33:49 +0000
3+++ CameraApp/advancedcamerasettings.cpp 2015-01-08 13:44:43 +0000
4@@ -39,7 +39,8 @@
5 m_viewFinderControl(0),
6 m_cameraFlashControl(0),
7 m_cameraExposureControl(0),
8- m_imageEncoderControl(0)
9+ m_imageEncoderControl(0),
10+ m_videoEncoderControl(0)
11 {
12 }
13
14@@ -164,6 +165,17 @@
15 return imageEncoderControl;
16 }
17
18+QVideoEncoderSettingsControl* AdvancedCameraSettings::videoEncoderControlFromCamera(QCamera *camera) const
19+{
20+ QMediaControl *control = mediaControlFromCamera(camera, QVideoEncoderSettingsControl_iid);
21+ QVideoEncoderSettingsControl *videoEncoderControl = qobject_cast<QVideoEncoderSettingsControl*>(control);
22+
23+ if (videoEncoderControl == 0) {
24+ qWarning() << "No video encoder settings control support";
25+ }
26+
27+ return videoEncoderControl;
28+}
29
30 QObject* AdvancedCameraSettings::camera() const
31 {
32@@ -221,12 +233,14 @@
33 }
34
35 m_imageEncoderControl = imageEncoderControlFromCamera(m_camera);
36+ m_videoEncoderControl = videoEncoderControlFromCamera(m_camera);
37
38 Q_EMIT resolutionChanged();
39 Q_EMIT hasFlashChanged();
40 Q_EMIT hasHdrChanged();
41 Q_EMIT hdrEnabledChanged();
42 Q_EMIT encodingQualityChanged();
43+ Q_EMIT videoSupportedResolutionsChanged();
44 }
45
46 void AdvancedCameraSettings::onCameraStateChanged()
47@@ -246,6 +260,7 @@
48 Q_EMIT activeCameraIndexChanged();
49 Q_EMIT resolutionChanged();
50 Q_EMIT hasFlashChanged();
51+ Q_EMIT videoSupportedResolutionsChanged();
52 }
53 }
54
55@@ -261,6 +276,29 @@
56 return QSize();
57 }
58
59+QStringList AdvancedCameraSettings::videoSupportedResolutions() const
60+{
61+ if (m_videoEncoderControl) {
62+ QList<QSize> sizes = m_videoEncoderControl->supportedResolutions(
63+ m_videoEncoderControl->videoSettings());
64+ QStringList sizesAsStrings;
65+ Q_FOREACH(QSize size, sizes) {
66+ // Workaround for bug https://bugs.launchpad.net/ubuntu/+source/libhybris/+bug/1408650
67+ // When using the front camera on krillin, using resolution 640x480 does
68+ // not work properly and results in stretched videos. Remove it from
69+ // the list of supported resolutions.
70+ if (activeCameraIndex() == 1 && size.width() == 640 && size.height() == 480) {
71+ continue;
72+ }
73+ sizesAsStrings.append(QString("%1x%2").arg(size.width()).arg(size.height()));
74+ }
75+ return sizesAsStrings;
76+ } else {
77+ return QStringList();
78+ }
79+}
80+
81+
82 bool AdvancedCameraSettings::hasFlash() const
83 {
84 if (m_cameraFlashControl) {
85
86=== modified file 'CameraApp/advancedcamerasettings.h'
87--- CameraApp/advancedcamerasettings.h 2014-12-03 19:33:49 +0000
88+++ CameraApp/advancedcamerasettings.h 2015-01-08 13:44:43 +0000
89@@ -28,6 +28,7 @@
90 #include <QtMultimedia/QCameraExposureControl>
91 #include <QtMultimedia/QMediaControl>
92 #include <QtMultimedia/QImageEncoderControl>
93+#include <QtMultimedia/QVideoEncoderSettingsControl>
94
95 class QCameraControl;
96 class QCameraFlashControl;
97@@ -39,6 +40,7 @@
98 Q_PROPERTY (int activeCameraIndex READ activeCameraIndex WRITE setActiveCameraIndex
99 NOTIFY activeCameraIndexChanged)
100 Q_PROPERTY (QSize resolution READ resolution NOTIFY resolutionChanged)
101+ Q_PROPERTY (QStringList videoSupportedResolutions READ videoSupportedResolutions NOTIFY videoSupportedResolutionsChanged)
102 Q_PROPERTY (bool hasFlash READ hasFlash NOTIFY hasFlashChanged)
103 Q_PROPERTY (bool hdrEnabled READ hdrEnabled WRITE setHdrEnabled NOTIFY hdrEnabledChanged)
104 Q_PROPERTY (bool hasHdr READ hasHdr NOTIFY hasHdrChanged)
105@@ -51,6 +53,7 @@
106 void setCamera(QObject* camera);
107 void setActiveCameraIndex(int index);
108 QSize resolution() const;
109+ QStringList videoSupportedResolutions() const;
110 bool hasFlash() const;
111 bool hasHdr() const;
112 bool hdrEnabled() const;
113@@ -67,6 +70,7 @@
114 void hasHdrChanged();
115 void hdrEnabledChanged();
116 void encodingQualityChanged();
117+ void videoSupportedResolutionsChanged();
118
119 private Q_SLOTS:
120 void onCameraStateChanged();
121@@ -81,6 +85,7 @@
122 QCamera* cameraFromCameraObject(QObject* cameraObject) const;
123 QMediaControl* mediaControlFromCamera(QCamera *camera, const char* iid) const;
124 QImageEncoderControl* imageEncoderControlFromCamera(QCamera *camera) const;
125+ QVideoEncoderSettingsControl* videoEncoderControlFromCamera(QCamera *camera) const;
126
127 QObject* m_cameraObject;
128 QCamera* m_camera;
129@@ -91,6 +96,7 @@
130 QCameraFlashControl* m_cameraFlashControl;
131 QCameraExposureControl* m_cameraExposureControl;
132 QImageEncoderControl* m_imageEncoderControl;
133+ QVideoEncoderSettingsControl* m_videoEncoderControl;
134 };
135
136 #endif // ADVANCEDCAMERASETTINGS_H
137
138=== modified file 'ViewFinderOverlay.qml'
139--- ViewFinderOverlay.qml 2014-12-11 12:24:25 +0000
140+++ ViewFinderOverlay.qml 2015-01-08 13:44:43 +0000
141@@ -47,6 +47,7 @@
142 property int encodingQuality: 2 // QMultimedia.NormalQuality
143 property bool gridEnabled: false
144 property bool preferRemovableStorage: false
145+ property string videoResolution: "1920x1080"
146 }
147
148 Binding {
149@@ -75,6 +76,57 @@
150 value: settings.encodingQuality
151 }
152
153+ Binding {
154+ target: camera.videoRecorder
155+ property: "resolution"
156+ value: settings.videoResolution
157+ }
158+
159+ function resolutionToLabel(resolution) {
160+ // takes in a resolution string (e.g. "1920x1080") and returns a nicer
161+ // form of it for display in the UI: "1080p"
162+ return resolution.split("x").pop() + "p";
163+ }
164+
165+ function updateVideoResolutionOptions() {
166+ // Clear and refill videoResolutionOptionsModel with available resolutions
167+ // Try to only display well known resolutions: 1080p, 720p and 480p
168+ videoResolutionOptionsModel.clear();
169+ var supported = camera.advanced.videoSupportedResolutions;
170+ var wellKnown = ["1920x1080", "1280x720", "640x480"];
171+ for (var i=0; i<supported.length; i++) {
172+ var resolution = supported[i];
173+ if (wellKnown.indexOf(resolution) !== -1) {
174+ var option = {"icon": "",
175+ "label": resolutionToLabel(resolution),
176+ "value": resolution};
177+ videoResolutionOptionsModel.insert(0, option);
178+ }
179+ }
180+
181+ // If resolution setting chosen is not supported select the highest available resolution
182+ if (supported.indexOf(settings.videoResolution) == -1) {
183+ settings.videoResolution = supported[supported.length - 1];
184+ }
185+ }
186+
187+ Component.onCompleted: {
188+ updateVideoResolutionOptions();
189+ }
190+
191+ Connections {
192+ target: camera.advanced
193+ onVideoSupportedResolutionsChanged: updateVideoResolutionOptions();
194+ }
195+
196+ Connections {
197+ target: camera.advanced
198+ onActiveCameraIndexChanged: {
199+ updateVideoResolutionOptions();
200+ camera.videoRecorder.resolution = settings.videoResolution;
201+ }
202+ }
203+
204 Connections {
205 target: camera.imageCapture
206 onReadyChanged: {
207@@ -111,6 +163,8 @@
208 }
209 height: optionsOverlayLoader.height
210 onOpenedChanged: optionsOverlayLoader.item.closeValueSelector()
211+ enabled: camera.videoRecorder.recorderState == CameraRecorder.StoppedState
212+ opacity: enabled ? 1.0 : 0.3
213
214 Item {
215 /* Use the 'trigger' feature of Panel so that tapping on the Panel
216@@ -319,6 +373,18 @@
217 label: QT_TR_NOOP("Save internally")
218 value: false
219 }
220+ },
221+ ListModel {
222+ id: videoResolutionOptionsModel
223+
224+ property string settingsProperty: "videoResolution"
225+ property string icon: ""
226+ property string label: "HD"
227+ property bool isToggle: false
228+ property int selectedIndex: bottomEdge.indexForValue(videoResolutionOptionsModel, settings.videoResolution)
229+ property bool available: true
230+ property bool visible: camera.captureMode == Camera.CaptureVideo
231+ property bool showInIndicators: false
232 }
233 ]
234
235
236=== modified file 'debian/changelog'
237--- debian/changelog 2014-12-11 16:24:50 +0000
238+++ debian/changelog 2015-01-08 13:44:43 +0000
239@@ -30,6 +30,13 @@
240
241 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 09 Dec 2014 21:48:24 +0000
242
243+camera-app (3.0.0+15.04.20141205-0ubuntu2) UNRELEASED; urgency=medium
244+
245+ [ Florian Boucault ]
246+ * Add dependency on python3-mediainfodll to camera-app-autopilot
247+
248+ -- Florian Boucault <florian.boucault@canonical.com> Wed, 10 Dec 2014 15:16:28 -0200
249+
250 camera-app (3.0.0+15.04.20141205-0ubuntu1) vivid; urgency=low
251
252 [ Ubuntu daily release ]
253
254=== modified file 'debian/control'
255--- debian/control 2014-12-03 18:18:05 +0000
256+++ debian/control 2015-01-08 13:44:43 +0000
257@@ -58,5 +58,6 @@
258 ${shlibs:Depends},
259 python3-autopilot,
260 python3-wand,
261+ python3-mediainfodll,
262 Description: Test package for the camera app
263 Autopilot tests for the camera-app package
264
265=== modified file 'po/camera-app.pot'
266--- po/camera-app.pot 2014-12-11 12:24:25 +0000
267+++ po/camera-app.pot 2015-01-08 13:44:43 +0000
268@@ -8,7 +8,7 @@
269 msgstr ""
270 "Project-Id-Version: camera-app\n"
271 "Report-Msgid-Bugs-To: \n"
272-"POT-Creation-Date: 2014-12-11 10:23-0200\n"
273+"POT-Creation-Date: 2014-12-15 08:50-0200\n"
274 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
275 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
276 "Language-Team: LANGUAGE <LL@li.org>\n"
277@@ -49,55 +49,55 @@
278 msgid "Share"
279 msgstr ""
280
281-#: ../ViewFinderOverlay.qml:141 ../ViewFinderOverlay.qml:164
282-#: ../ViewFinderOverlay.qml:192 ../ViewFinderOverlay.qml:215
283-#: ../ViewFinderOverlay.qml:292
284+#: ../ViewFinderOverlay.qml:185 ../ViewFinderOverlay.qml:208
285+#: ../ViewFinderOverlay.qml:236 ../ViewFinderOverlay.qml:259
286+#: ../ViewFinderOverlay.qml:336
287 msgid "On"
288 msgstr ""
289
290-#: ../ViewFinderOverlay.qml:146 ../ViewFinderOverlay.qml:174
291-#: ../ViewFinderOverlay.qml:197 ../ViewFinderOverlay.qml:220
292-#: ../ViewFinderOverlay.qml:239 ../ViewFinderOverlay.qml:297
293+#: ../ViewFinderOverlay.qml:190 ../ViewFinderOverlay.qml:218
294+#: ../ViewFinderOverlay.qml:241 ../ViewFinderOverlay.qml:264
295+#: ../ViewFinderOverlay.qml:283 ../ViewFinderOverlay.qml:341
296 msgid "Off"
297 msgstr ""
298
299-#: ../ViewFinderOverlay.qml:169
300+#: ../ViewFinderOverlay.qml:213
301 msgid "Auto"
302 msgstr ""
303
304-#: ../ViewFinderOverlay.qml:206
305+#: ../ViewFinderOverlay.qml:250
306 msgid "HDR"
307 msgstr ""
308
309-#: ../ViewFinderOverlay.qml:244
310+#: ../ViewFinderOverlay.qml:288
311 msgid "5 seconds"
312 msgstr ""
313
314-#: ../ViewFinderOverlay.qml:249
315+#: ../ViewFinderOverlay.qml:293
316 msgid "15 seconds"
317 msgstr ""
318
319-#: ../ViewFinderOverlay.qml:266
320+#: ../ViewFinderOverlay.qml:310
321 msgid "Fine Quality"
322 msgstr ""
323
324-#: ../ViewFinderOverlay.qml:270
325+#: ../ViewFinderOverlay.qml:314
326 msgid "Normal Quality"
327 msgstr ""
328
329-#: ../ViewFinderOverlay.qml:274
330+#: ../ViewFinderOverlay.qml:318
331 msgid "Basic Quality"
332 msgstr ""
333
334-#: ../ViewFinderOverlay.qml:306
335+#: ../ViewFinderOverlay.qml:350
336 msgid "SD"
337 msgstr ""
338
339-#: ../ViewFinderOverlay.qml:314
340+#: ../ViewFinderOverlay.qml:358
341 msgid "Save to SD Card"
342 msgstr ""
343
344-#: ../ViewFinderOverlay.qml:319
345+#: ../ViewFinderOverlay.qml:363
346 msgid "Save internally"
347 msgstr ""
348
349
350=== modified file 'tests/autopilot/camera_app/emulators/main_window.py'
351--- tests/autopilot/camera_app/emulators/main_window.py 2014-12-08 12:04:21 +0000
352+++ tests/autopilot/camera_app/emulators/main_window.py 2015-01-08 13:44:43 +0000
353@@ -77,6 +77,10 @@
354 """Returns the grid lines toggle button of the camera"""
355 return self.get_option_button("gridEnabled")
356
357+ def get_video_resolution_button(self):
358+ """Returns the video resolution button of the camera"""
359+ return self.get_option_button("videoResolution")
360+
361 def get_stop_watch(self):
362 """Returns the stop watch when using the record button of the camera"""
363 return self.app.wait_select_single("StopWatch")
364
365=== modified file 'tests/autopilot/camera_app/emulators/panel.py'
366--- tests/autopilot/camera_app/emulators/panel.py 2014-06-26 11:49:31 +0000
367+++ tests/autopilot/camera_app/emulators/panel.py 2015-01-08 13:44:43 +0000
368@@ -51,7 +51,7 @@
369
370 def _drag_to_close(self):
371 x, y, _, _ = self.globalRect
372- line_x = x + self.width * 0.50
373+ line_x = x
374 start_y = y
375 stop_y = y + self.height - 1
376
377
378=== modified file 'tests/autopilot/camera_app/tests/test_capture.py'
379--- tests/autopilot/camera_app/tests/test_capture.py 2014-12-03 18:18:05 +0000
380+++ tests/autopilot/camera_app/tests/test_capture.py 2015-01-08 13:44:43 +0000
381@@ -11,6 +11,7 @@
382 from autopilot.platform import model
383 from testtools.matchers import Equals, NotEquals
384 from wand.image import Image
385+from MediaInfoDLL3 import MediaInfo, Stream
386
387 from camera_app.tests import CameraAppTestCase
388
389@@ -253,3 +254,142 @@
390 self.pointing_device.click()
391
392 bottom_edge.close()
393+
394+ """Test recording videos at a set resolution and switching cameras"""
395+ def test_video_resolution_setting_switching_cameras(self):
396+ # switch to video recording and empty video folder
397+ self.switch_to_video_recording()
398+ self.delete_all_videos()
399+
400+ # select the first resolution for the current camera
401+ resolutions = self.get_available_video_resolutions()
402+ initial_resolution = resolutions[0]
403+ self.set_video_resolution(initial_resolution)
404+
405+ # switch cameras and select the last resolution for the current camera
406+ self.switch_cameras()
407+ resolutions = self.get_available_video_resolutions()
408+ expected_resolution = resolutions[-1]
409+ self.assertThat(expected_resolution, NotEquals(initial_resolution))
410+ self.set_video_resolution(expected_resolution)
411+
412+ # switch back to the initial camera and record a video
413+ self.switch_cameras()
414+ self.record_video(2)
415+ video_file = self.get_first_video()
416+ height = self.read_video_height(video_file)
417+ expected_height = self.height_from_resolution_label(expected_resolution)
418+ self.assertThat(height, Equals(expected_height))
419+
420+ def switch_cameras(self):
421+ # Swap cameras and wait for camera to settle
422+ shoot_button = self.main_window.get_exposure_button()
423+ swap_camera_button = self.main_window.get_swap_camera_button()
424+ self.pointing_device.move_to_object(swap_camera_button)
425+ self.pointing_device.click()
426+ self.assertThat(shoot_button.enabled, Eventually(Equals(True)))
427+
428+ """Test recording videos at various resolutions"""
429+ def test_video_resolution_setting(self):
430+ self.switch_to_video_recording()
431+ resolutions = self.get_available_video_resolutions()
432+
433+ for resolution_label in resolutions:
434+ self.delete_all_videos()
435+ self.set_video_resolution(resolution_label)
436+ self.record_video(2)
437+ video_file = self.get_first_video()
438+ height = self.read_video_height(video_file)
439+ expected_height = self.height_from_resolution_label(resolution_label)
440+ self.assertThat(height, Equals(expected_height))
441+ self.dismiss_first_photo_hint()
442+
443+ def switch_to_video_recording(self):
444+ record_control = self.main_window.get_record_control()
445+ # Wait for the camera overlay to be loaded
446+ self.assertThat(record_control.enabled, Eventually(Equals(True)))
447+ self.assertThat(record_control.width, Eventually(NotEquals(0)))
448+ self.assertThat(record_control.height, Eventually(NotEquals(0)))
449+
450+ self.pointing_device.move_to_object(record_control)
451+ self.pointing_device.click()
452+
453+ def get_available_video_resolutions(self):
454+ # open bottom edge
455+ bottom_edge = self.main_window.get_bottom_edge()
456+ bottom_edge.open()
457+
458+ # open video resolution option value selector showing the possible values
459+ video_resolution_button = self.main_window.get_video_resolution_button()
460+ self.pointing_device.move_to_object(video_resolution_button)
461+ self.pointing_device.click()
462+ option_value_selector = self.main_window.get_option_value_selector()
463+ self.assertThat(option_value_selector.visible, Eventually(Equals(True)))
464+ optionButtons = option_value_selector.select_many("OptionValueButton")
465+ resolutions = [button.label for button in optionButtons]
466+
467+ bottom_edge.close()
468+ return resolutions
469+
470+ def delete_all_videos(self):
471+ video_files = os.listdir(self.videos_dir)
472+ for f in video_files:
473+ os.remove(os.path.join(self.videos_dir, f))
474+
475+ def set_video_resolution(self, resolution_label="720p"):
476+ # open bottom edge
477+ bottom_edge = self.main_window.get_bottom_edge()
478+ bottom_edge.open()
479+
480+ # open video resolution option value selector showing the possible values
481+ video_resolution_button = self.main_window.get_video_resolution_button()
482+ self.pointing_device.move_to_object(video_resolution_button)
483+ self.pointing_device.click()
484+ option_value_selector = self.main_window.get_option_value_selector()
485+ self.assertThat(option_value_selector.visible, Eventually(Equals(True)))
486+
487+ # tap on chosen video resolution option
488+ option = self.main_window.get_option_value_button(resolution_label)
489+ self.pointing_device.move_to_object(option)
490+ self.pointing_device.click()
491+
492+ bottom_edge.close()
493+
494+ def record_video(self, duration):
495+ exposure_button = self.main_window.get_exposure_button()
496+
497+ # Click the exposure button to start recording
498+ self.pointing_device.move_to_object(exposure_button)
499+ self.assertThat(exposure_button.enabled, Eventually(Equals(True)))
500+ self.assertThat(exposure_button.width, Eventually(NotEquals(0)))
501+ self.assertThat(exposure_button.height, Eventually(NotEquals(0)))
502+ self.pointing_device.click()
503+
504+ # Record video for duration seconds
505+ time.sleep(duration)
506+ self.pointing_device.click()
507+
508+ stop_watch = self.main_window.get_stop_watch()
509+ self.assertThat(stop_watch.opacity, Eventually(Equals(0.0)))
510+
511+ def get_first_video(self, timeout=10):
512+ videos = []
513+ for i in range(0, timeout):
514+ videos = os.listdir(self.videos_dir)
515+ if len(videos) != 0:
516+ break
517+ time.sleep(1)
518+
519+ video_file = os.path.join(self.videos_dir, videos[0])
520+ return video_file
521+
522+ def read_video_height(self, video_file):
523+ MI = MediaInfo()
524+ MI.Open(video_file)
525+ height = MI.Get(Stream.Video, 0, "Height")
526+ MI.Close()
527+ return height
528+
529+ def height_from_resolution_label(self, resolution_label):
530+ # remove last character from label (always 'p')
531+ return resolution_label[:-1]

Subscribers

People subscribed via source and target branches