Improve USB device reset logic
BUG=webrtc:7203
NOTRY=True
Review-Url: https://codereview.webrtc.org/2789533002
Cr-Commit-Position: refs/heads/master@{#17656}
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index c3f2dee..efa80fa 100755
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -471,6 +471,7 @@
test_directories = [
Join('webrtc', 'tools', 'py_event_log_analyzer'),
+ Join('webrtc', 'tools'),
Join('webrtc', 'audio', 'test', 'unittests'),
] + [
root for root, _, files in os.walk(Join('tools-webrtc'))
diff --git a/webrtc/tools/run_video_analysis.py b/webrtc/tools/video_analysis.py
similarity index 89%
rename from webrtc/tools/run_video_analysis.py
rename to webrtc/tools/video_analysis.py
index 29682aa..b13543d 100755
--- a/webrtc/tools/run_video_analysis.py
+++ b/webrtc/tools/video_analysis.py
@@ -7,14 +7,14 @@
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
+import glob
import optparse
import os
+import shutil
import subprocess
import sys
import time
-import glob
-import re
-import shutil
+
# Used to time-stamp output files and directories
CURRENT_TIME = time.strftime("%d_%m_%Y-%H:%M:%S")
@@ -158,47 +158,67 @@
return record_paths
-def RestartMagewellDevices(ref_video_device, test_video_device):
- """Reset the USB ports where Magewell capture devices are connected to.
+def FindUsbPortForV4lDevices(ref_video_device, test_video_device):
+ """Tries to find the usb port for ref_video_device and test_video_device.
Tries to find the provided ref_video_device and test_video_device devices
which use video4linux and then do a soft reset by using USB unbind and bind.
+
+ Args:
+ ref_device(string): reference recording device path.
+ test_device(string): test recording device path
+
+ Returns:
+ usb_ports(list): USB ports(string) for the devices found.
+ """
+
+ # Find the device location including USB and USB Bus ID's. Use the usb1
+ # in the path since the driver folder is a symlink which contains all the
+ # usb device port mappings and it's the same in all usbN folders. Tested
+ # on Ubuntu 14.04.
+ v4l_device_path = '/sys/bus/usb/devices/usb1/1-1/driver/**/**/video4linux/'
+ v4l_ref_device = glob.glob('%s%s' % (v4l_device_path, ref_video_device))
+ v4l_test_device = glob.glob('%s%s' % (v4l_device_path, test_video_device))
+ usb_ports = []
+ paths = []
+
+ # Split on the driver folder first since we are only interested in the
+ # folders thereafter.
+ ref_path = str(v4l_ref_device).split('driver')[1].split('/')
+ test_path = str(v4l_test_device).split('driver')[1].split('/')
+ paths.append(ref_path)
+ paths.append(test_path)
+
+ for path in paths:
+ for usb_id in path:
+ # Look for : separator and then use the first element in the list.
+ # E.g 3-3.1:1.0 split on : and [0] becomes 3-3.1 which can be used
+ # for bind/unbind.
+ if ':' in usb_id:
+ usb_ports.append(usb_id.split(':')[0])
+ return usb_ports
+
+
+def RestartMagewellDevices(ref_video_device_path, test_video_device_path):
+ """Reset the USB ports where Magewell capture devices are connected to.
+
+ Performs a soft reset by using USB unbind and bind.
This is due to Magewell capture devices have proven to be unstable after the
first recording attempt.
- Args :
- ref_video_device(string): reference recording device path.
- test_video_device(string): test recording device path
+ Args:
+ ref_video_device_path(string): reference recording device path.
+ test_video_device_path(string): test recording device path
Raises:
MagewellError: If no magewell devices are found.
"""
# Get the dev/videoN device name from the command line arguments.
- ref_magewell = ref_video_device.split('/')[2]
- test_magewell = test_video_device.split('/')[2]
-
- # Find the device location including USB and USB Bus ID's.
- device_string = '/sys/bus/usb/devices/usb*/**/**/video4linux/'
- ref_magewell_device = glob.glob('%s%s' % (device_string, ref_magewell))
- test_magewell_device = glob.glob('%s%s' % (device_string, test_magewell))
-
- magewell_usb_ports = []
-
- # Figure out the USB bus and port ID for each device.
- ref_magewell_path = str(ref_magewell_device).split('/')
- for directory in ref_magewell_path:
- # Find the folder with pattern "N-N", e.g. "4-3" or \
- # "[USB bus ID]-[USB port]"
- if re.match(r'^\d-\d$', directory):
- magewell_usb_ports.append(directory)
-
- test_magewell_path = str(test_magewell_device).split('/')
- for directory in test_magewell_path:
- # Find the folder with pattern "N-N", e.g. "4-3" or \
- # "[USB bus ID]-[USB port]"
- if re.match(r'^\d-\d$', directory):
- magewell_usb_ports.append(directory)
+ ref_magewell_path = ref_video_device_path.split('/')[2]
+ test_magewell_path = test_video_device_path.split('/')[2]
+ magewell_usb_ports = FindUsbPortForV4lDevices(ref_magewell_path,
+ test_magewell_path)
# Abort early if no devices are found.
if len(magewell_usb_ports) == 0:
@@ -413,7 +433,6 @@
crop_height = param.split(':')[1]
compare_cmd = [
- sys.executable,
compare_videos_script,
'--ref_video', cropped_ref_file,
'--test_video', cropped_test_file,
diff --git a/webrtc/tools/video_analysis_test.py b/webrtc/tools/video_analysis_test.py
new file mode 100755
index 0000000..f4cd74b
--- /dev/null
+++ b/webrtc/tools/video_analysis_test.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import glob
+import unittest
+from video_analysis import FindUsbPortForV4lDevices
+
+
+class RunVideoAnalysisTest(unittest.TestCase):
+ def setGlobPath(self, path1, path2):
+ self.path1 = path1
+ self.path2 = path2
+
+ def setUp(self):
+ self.path1 = ''
+ self.path2 = ''
+ self.requestNbr = 1
+
+ def glob_mock(string):
+ # Eat incoming string.
+ del string
+ if self.requestNbr == 1:
+ self.requestNbr += 1
+ return self.path1
+ else:
+ self.requestNbr = 1
+ return self.path2
+
+ # Override the glob function with our own that returns a string set by the
+ # test.
+ glob.glob = glob_mock
+
+ # Verifies that the correct USB id is returned.
+ def testFindUSBPortForV4lDevices(self):
+ short_path1 = ('/sys/bus/usb/devices/usb1/1-1/driver/4-4/4-4:1.0/'
+ 'video4linux/video0')
+ short_path2 = ('/sys/bus/usb/devices/usb1/1-1/driver/4-3/4-3:1.0/'
+ 'video4linux/video1')
+ self.setGlobPath(short_path1, short_path2)
+ short_usb_ids = ['4-4', '4-3']
+ self.assertEqual(FindUsbPortForV4lDevices('video0', 'video1'),
+ short_usb_ids)
+
+ long_path1 = ('/sys/bus/usb/devices/usb1/1-1/driver/3-3/3-3.1:1.0/'
+ 'video4linux/video0')
+ long_path2 = ('/sys/bus/usb/devices/usb1/1-1/driver/3-2/3-2.1:1.0/'
+ 'video4linux/video1')
+ self.setGlobPath(long_path1, long_path2)
+ long_usb_ids = ['3-3.1', '3-2.1']
+ self.assertEqual(FindUsbPortForV4lDevices('video0', 'video1'), long_usb_ids)
+
+
+if __name__ == "__main__":
+ unittest.main()