Index: webrtc/tools/run_video_analysis.py |
diff --git a/webrtc/tools/run_video_analysis.py b/webrtc/tools/run_video_analysis.py |
index 350bc556fb71cd4a461639eb045d14432133a85b..29682aa02917779742ececaca52b0662a6d80546 100755 |
--- a/webrtc/tools/run_video_analysis.py |
+++ b/webrtc/tools/run_video_analysis.py |
@@ -14,10 +14,28 @@ 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") |
+ |
+class Error(Exception): |
+ pass |
+ |
+ |
+class FfmpegError(Error): |
+ pass |
+ |
+ |
+class MagewellError(Error): |
+ pass |
+ |
+ |
+class CompareVideosError(Error): |
+ pass |
+ |
+ |
def _ParseArgs(): |
"""Registers the command-line options.""" |
usage = 'usage: %prog [options]' |
@@ -111,7 +129,8 @@ def CreateRecordingDirs(options): |
Args: |
options(object): Contains all the provided command line options. |
- Return: |
+ |
+ Returns: |
record_paths(dict): key: value pair with reference and test file |
absolute paths. |
""" |
@@ -147,9 +166,12 @@ def RestartMagewellDevices(ref_video_device, test_video_device): |
This is due to Magewell capture devices have proven to be unstable after the |
first recording attempt. |
- Args: |
+ Args : |
ref_video_device(string): reference recording device path. |
test_video_device(string): test recording device path |
+ |
+ Raises: |
+ MagewellError: If no magewell devices are found. |
""" |
# Get the dev/videoN device name from the command line arguments. |
@@ -166,7 +188,6 @@ def RestartMagewellDevices(ref_video_device, test_video_device): |
# 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): |
@@ -174,17 +195,18 @@ def RestartMagewellDevices(ref_video_device, test_video_device): |
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) |
- print '\nResetting USB ports where magewell devices are connected...' |
- |
- # Use the USB bus and port ID (e.g. 4-3) to unbind and bind the USB devices |
- # (i.e. soft eject and insert). |
- try: |
+ # Abort early if no devices are found. |
+ if len(magewell_usb_ports) == 0: |
+ raise MagewellError('No magewell devices found.') |
+ else: |
+ print '\nResetting USB ports where magewell devices are connected...' |
+ # Use the USB bus and port ID (e.g. 4-3) to unbind and bind the USB devices |
+ # (i.e. soft eject and insert). |
for usb_port in magewell_usb_ports: |
echo_cmd = ['echo', usb_port] |
unbind_cmd = ['sudo', 'tee', '/sys/bus/usb/drivers/usb/unbind'] |
@@ -195,38 +217,38 @@ def RestartMagewellDevices(ref_video_device, test_video_device): |
echo_unbind = subprocess.Popen(echo_cmd, stdout=subprocess.PIPE) |
unbind = subprocess.Popen(unbind_cmd, stdin=echo_unbind.stdout) |
echo_unbind.stdout.close() |
- unbind.communicate() |
unbind.wait() |
echo_bind = subprocess.Popen(echo_cmd, stdout=subprocess.PIPE) |
bind = subprocess.Popen(bind_cmd, stdin=echo_bind.stdout) |
echo_bind.stdout.close() |
- bind.communicate() |
bind.wait() |
- except OSError as e: |
- print 'Error while resetting magewell devices: ' + e |
- raise |
+ if bind.returncode == 0: |
+ print 'Reset done!\n' |
- print 'Reset done!\n' |
- |
-def StartRecording(options, record_paths): |
+def StartRecording(options, ref_file_location, test_file_location): |
"""Starts recording from the two specified video devices. |
Args: |
options(object): Contains all the provided command line options. |
record_paths(dict): key: value pair with reference and test file |
absolute paths. |
+ |
+ Returns: |
+ recording_files_and_time(dict): key: value pair with the path to cropped |
+ test and reference video files. |
+ |
+ Raises: |
+ FfmpegError: If the ffmpeg command fails. |
""" |
ref_file_name = '%s_%s_ref.%s' % (options.app_name, CURRENT_TIME, |
options.video_container) |
- ref_file_location = os.path.join(record_paths['ref_rec_location'], |
- ref_file_name) |
+ ref_file = os.path.join(ref_file_location, ref_file_name) |
test_file_name = '%s_%s_test.%s' % (options.app_name, CURRENT_TIME, |
options.video_container) |
- test_file_location = os.path.join(record_paths['test_rec_location'], |
- test_file_name) |
+ test_file = os.path.join(test_file_location, test_file_name) |
# Reference video recorder command line. |
ref_cmd = [ |
@@ -240,7 +262,7 @@ def StartRecording(options, record_paths): |
'-s', options.frame_width + 'x' + options.frame_height, |
'-t', options.ref_duration, |
'-framerate', options.framerate, |
- ref_file_location |
+ ref_file |
] |
# Test video recorder command line. |
@@ -255,7 +277,7 @@ def StartRecording(options, record_paths): |
'-s', options.frame_width + 'x' + options.frame_height, |
'-t', options.test_duration, |
'-framerate', options.framerate, |
- test_file_location |
+ test_file |
] |
print 'Trying to record from reference recorder...' |
ref_recorder = subprocess.Popen(ref_cmd, stderr=sys.stderr) |
@@ -270,19 +292,17 @@ def StartRecording(options, record_paths): |
ref_recorder.wait() |
# ffmpeg does not abort when it fails, need to check return code. |
- assert ref_recorder.returncode == 0, ( |
- 'Ref recording failed, check ffmpeg output and device: %s' |
- % options.ref_video_device) |
- assert test_recorder.returncode == 0, ( |
- 'Test recording failed, check ffmpeg output and device: %s' |
- % options.test_video_device) |
- |
- print 'Ref file recorded to: ' + os.path.abspath(ref_file_location) |
- print 'Test file recorded to: ' + os.path.abspath(test_file_location) |
- print 'Recording done!\n' |
- return FlipAndCropRecordings(options, test_file_name, |
- record_paths['test_rec_location'], ref_file_name, |
- record_paths['ref_rec_location']) |
+ if ref_recorder.returncode != 0 or test_recorder.returncode != 0: |
+ # Cleanup recording directories. |
+ shutil.rmtree(ref_file_location) |
+ shutil.rmtree(test_file_location) |
+ raise FfmpegError('Recording failed, check ffmpeg output.') |
+ else: |
+ print 'Ref file recorded to: ' + os.path.abspath(ref_file) |
+ print 'Test file recorded to: ' + os.path.abspath(test_file) |
+ print 'Recording done!\n' |
+ return FlipAndCropRecordings(options, test_file_name, test_file_location, |
+ ref_file_name, ref_file_location) |
def FlipAndCropRecordings(options, test_file_name, test_file_location, |
@@ -298,9 +318,13 @@ def FlipAndCropRecordings(options, test_file_name, test_file_location, |
test_file_location(string): Path to the test video file recording. |
ref_file_name(string): Name of the reference video file recording. |
ref_file_location(string): Path to the reference video file recording. |
- Return: |
+ |
+ Returns: |
recording_files_and_time(dict): key: value pair with the path to cropped |
test and reference video files. |
+ |
+ Raises: |
+ FfmpegError: If the ffmpeg command fails. |
""" |
print 'Trying to crop videos...' |
@@ -336,11 +360,17 @@ def FlipAndCropRecordings(options, test_file_name, test_file_location, |
ref_crop = subprocess.Popen(ref_video_crop_cmd) |
ref_crop.wait() |
- print 'Ref file cropped to: ' + cropped_ref_file |
+ test_crop = subprocess.Popen(test_video_crop_cmd) |
+ test_crop.wait() |
- try: |
- test_crop = subprocess.Popen(test_video_crop_cmd) |
- test_crop.wait() |
+ # ffmpeg does not abort when it fails, need to check return code. |
+ if ref_crop.returncode != 0 or test_crop.returncode != 0: |
+ # Cleanup recording directories. |
+ shutil.rmtree(ref_file_location) |
+ shutil.rmtree(test_file_location) |
+ raise FfmpegError('Cropping failed, check ffmpeg output.') |
+ else: |
+ print 'Ref file cropped to: ' + cropped_ref_file |
print 'Test file cropped to: ' + cropped_test_file |
print 'Cropping done!\n' |
@@ -349,14 +379,10 @@ def FlipAndCropRecordings(options, test_file_name, test_file_location, |
'cropped_test_file' : cropped_test_file, |
'cropped_ref_file' : cropped_ref_file |
} |
- |
return cropped_recordings |
- except subprocess.CalledProcessError as e: |
- print 'Something went wrong during cropping: ' + e |
- raise |
-def CompareVideos(options, recording_result): |
+def CompareVideos(options, cropped_ref_file, cropped_test_file): |
"""Runs the compare_video.py script from src/webrtc/tools using the file path. |
Uses the path from recording_result and writes the output to a file named |
@@ -365,21 +391,22 @@ def CompareVideos(options, recording_result): |
Args: |
options(object): Contains all the provided command line options. |
- recording_files_and_time(dict): key: value pair with the path to cropped |
- test and reference video files |
+ cropped_ref_file(string): Path to cropped reference video file. |
+ cropped_test_file(string): Path to cropped test video file. |
+ |
+ Raises: |
+ CompareVideosError: If compare_videos.py fails. |
""" |
print 'Starting comparison...' |
print 'Grab a coffee, this might take a few minutes...' |
- cropped_ref_file = recording_result['cropped_ref_file'] |
- cropped_test_file = recording_result['cropped_test_file'] |
compare_videos_script = os.path.abspath(options.compare_videos_script) |
rec_path = os.path.abspath(os.path.join( |
- os.path.dirname(recording_result['cropped_ref_file']))) |
+ os.path.dirname(cropped_test_file))) |
result_file_name = os.path.join(rec_path, '%s_%s_result.txt') % ( |
options.app_name, CURRENT_TIME) |
- # Find the crop dimensions (950 and 420) in the ref crop parameter string: |
- # 'hflip, crop=950:420:130:56' |
+ # Find the crop dimensions (e.g. 950 and 420) in the ref crop parameter |
+ # string: 'hflip, crop=950:420:130:56' |
for param in options.ref_crop_parameters.split('crop'): |
if param[0] == '=': |
crop_width = param.split(':')[0].split('=')[1] |
@@ -401,15 +428,14 @@ def CompareVideos(options, recording_result): |
'--yuv_frame_width', crop_width |
] |
- try: |
- with open(result_file_name, 'w') as f: |
- compare_video_recordings = subprocess.Popen(compare_cmd, stdout=f) |
- compare_video_recordings.wait() |
- print 'Result recorded to: ' + os.path.abspath(result_file_name) |
- print 'Comparison done!' |
- except subprocess.CalledProcessError as e: |
- print 'Something went wrong when trying to compare videos: ' + e |
- raise |
+ with open(result_file_name, 'w') as f: |
+ compare_video_recordings = subprocess.Popen(compare_cmd, stdout=f) |
+ compare_video_recordings.wait() |
+ if compare_video_recordings.returncode != 0: |
+ raise CompareVideosError('Failed to perform comparison.') |
+ else: |
+ print 'Result recorded to: ' + os.path.abspath(result_file_name) |
+ print 'Comparison done!' |
def main(): |
@@ -442,11 +468,13 @@ def main(): |
options = _ParseArgs() |
RestartMagewellDevices(options.ref_video_device, options.test_video_device) |
record_paths = CreateRecordingDirs(options) |
- recording_result = StartRecording(options, record_paths) |
+ recording_result = StartRecording(options, record_paths['ref_rec_location'], |
+ record_paths['test_rec_location']) |
# Do not require compare_video.py script to run, no metrics will be generated. |
if options.compare_videos_script: |
- CompareVideos(options, recording_result) |
+ CompareVideos(options, recording_result['cropped_ref_file'], |
+ recording_result['cropped_test_file']) |
else: |
print ('Skipping compare videos step due to compare_videos flag were not ' |
'passed.') |