| 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.')
|
|
|