blob: 2500057320aa6c9e650604a1faaee2873728b431 [file] [log] [blame]
mandermoed582f72017-01-23 07:55:42 -08001#!/usr/bin/env python
2# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3#
4# Use of this source code is governed by a BSD-style license
5# that can be found in the LICENSE file in the root of the source
6# tree. An additional intellectual property rights grant can be found
7# in the file PATENTS. All contributing project authors may
8# be found in the AUTHORS file in the root of the source tree.
9
10"""
11This script is the wrapper that starts a loopback call with stubbed video in
12and out. It then analyses the video quality of the output video against the
13reference input video.
14
15It expect to be given the webrtc output build directory as the first argument
16all other arguments are optional.
17
18It assumes you have a Android device plugged in.
19"""
20
21import argparse
oprypin30cda5e2017-04-24 04:15:13 -070022import atexit
mandermoed582f72017-01-23 07:55:42 -080023import logging
24import os
25import shutil
26import subprocess
27import sys
28import tempfile
oprypin30cda5e2017-04-24 04:15:13 -070029import time
mandermoed582f72017-01-23 07:55:42 -080030
31
32SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
kjellander30292102017-02-09 01:05:54 -080033SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir,
34 os.pardir))
oprypin30cda5e2017-04-24 04:15:13 -070035WEBRTC_DEPS_INSTRUCTIONS = """Please add a solution to your .gclient file like
36this and run gclient sync:
37{
38 "name": "webrtc.DEPS",
39 "url": "https://chromium.googlesource.com/chromium/deps/webrtc/webrtc.DEPS",
40},
41"""
42
43
44class Error(Exception):
45 pass
46
47
48class VideoQualityTestError(Error):
49 pass
mandermoed582f72017-01-23 07:55:42 -080050
51
ehmaldonadod103f4b2017-02-16 07:20:26 -080052def _RunCommand(argv, cwd=SRC_DIR, **kwargs):
mandermoed582f72017-01-23 07:55:42 -080053 logging.info('Running %r', argv)
ehmaldonadod103f4b2017-02-16 07:20:26 -080054 subprocess.check_call(argv, cwd=cwd, **kwargs)
mandermoed582f72017-01-23 07:55:42 -080055
56
oprypin30cda5e2017-04-24 04:15:13 -070057def _RunCommandWithOutput(argv, cwd=SRC_DIR, **kwargs):
58 logging.info('Running %r', argv)
59 return subprocess.check_output(argv, cwd=cwd, **kwargs)
60
61
62def _RunBackgroundCommand(argv, cwd=SRC_DIR):
63 logging.info('Running %r', argv)
64 process = subprocess.Popen(argv, cwd=cwd)
65 atexit.register(process.terminate)
66 time.sleep(0.5)
67 status = process.poll()
68 if status: # is not None or 0
69 raise subprocess.CalledProcessError(status, argv)
70 return process
71
72
mandermoed582f72017-01-23 07:55:42 -080073def _ParseArgs():
74 parser = argparse.ArgumentParser(description='Start loopback video analysis.')
mandermoed582f72017-01-23 07:55:42 -080075 parser.add_argument('build_dir_android',
76 help='The path to the build directory for Android.')
77 parser.add_argument('--build_dir_x86',
78 help='The path to the build directory for building locally.')
79 parser.add_argument('--temp_dir',
80 help='A temporary directory to put the output.')
oprypin30cda5e2017-04-24 04:15:13 -070081 parser.add_argument('--adb-path', help='Path to adb binary.', default='adb')
mandermoed582f72017-01-23 07:55:42 -080082
83 args = parser.parse_args()
84 return args
85
86
87def main():
88 logging.basicConfig(level=logging.INFO)
89
90 args = _ParseArgs()
91
mandermoed582f72017-01-23 07:55:42 -080092 build_dir_android = args.build_dir_android
93 build_dir_x86 = args.build_dir_x86
94 temp_dir = args.temp_dir
oprypin30cda5e2017-04-24 04:15:13 -070095 adb_path = args.adb_path
mandermoed582f72017-01-23 07:55:42 -080096 if not temp_dir:
97 temp_dir = tempfile.mkdtemp()
98 else:
99 if not os.path.exists(temp_dir):
100 os.makedirs(temp_dir)
101
102 if not build_dir_x86:
103 build_dir_x86 = os.path.join(temp_dir, 'LocalBuild')
104 _RunCommand(['gn', 'gen', build_dir_x86])
105 _RunCommand(['ninja', '-C', build_dir_x86, 'frame_analyzer'])
106
Henrik Kjellander90fd7d82017-05-09 08:30:10 +0200107 tools_dir = os.path.join(SRC_DIR, 'tools_webrtc')
oprypin3b2fb202017-03-06 02:23:34 -0800108 toolchain_dir = os.path.join(tools_dir, 'video_quality_toolchain')
mandermoed582f72017-01-23 07:55:42 -0800109
110 # Download ffmpeg and zxing.
oprypin3b2fb202017-03-06 02:23:34 -0800111 download_script = os.path.join(tools_dir, 'download_tools.py')
112 _RunCommand([sys.executable, download_script, toolchain_dir])
mandermoed582f72017-01-23 07:55:42 -0800113
oprypin30cda5e2017-04-24 04:15:13 -0700114 # Select an Android device in case multiple are connected
115 for line in _RunCommandWithOutput([adb_path, 'devices']).splitlines():
116 if line.endswith('\tdevice'):
117 android_device = line.split('\t')[0]
118 break
119 else:
120 raise VideoQualityTestError('Cannot find any connected Android device.')
121
122 # Start AppRTC Server
123 dev_appserver = os.path.join(SRC_DIR, 'out', 'apprtc', 'google_appengine',
124 'dev_appserver.py')
125 if not os.path.isfile(dev_appserver):
126 raise VideoQualityTestError('Cannot find %s.\n%s' %
127 (dev_appserver, WEBRTC_DEPS_INSTRUCTIONS))
128 appengine_dir = os.path.join(SRC_DIR, 'out', 'apprtc', 'out', 'app_engine')
129 _RunBackgroundCommand(['python', dev_appserver, appengine_dir,
130 '--port=9999', '--admin_port=9998',
131 '--skip_sdk_update_check', '--clear_datastore=yes'])
132
133 # Start Collider
134 collider_path = os.path.join(SRC_DIR, 'out', 'go-workspace', 'bin',
135 'collidermain')
136 if not os.path.isfile(collider_path):
137 raise VideoQualityTestError('Cannot find %s.\n%s' %
138 (collider_path, WEBRTC_DEPS_INSTRUCTIONS))
139 _RunBackgroundCommand([collider_path, '-tls=false',
140 '-port=8089', '-room-server=http://localhost:9999'])
141
142 # Start adb reverse forwarder
143 reverseforwarder_path = os.path.join(
144 SRC_DIR, 'build', 'android', 'adb_reverse_forwarder.py')
145 _RunBackgroundCommand([reverseforwarder_path, '--device', android_device,
146 '9999', '9999', '8089', '8089'])
147
mandermoed582f72017-01-23 07:55:42 -0800148 # Run the Espresso code.
149 test_script = os.path.join(build_dir_android,
150 'bin', 'run_AppRTCMobileTestStubbedVideoIO')
oprypin30cda5e2017-04-24 04:15:13 -0700151 _RunCommand([test_script, '--device', android_device])
mandermoed582f72017-01-23 07:55:42 -0800152
153 # Pull the output video.
154 test_video = os.path.join(temp_dir, 'test_video.y4m')
oprypin30cda5e2017-04-24 04:15:13 -0700155 _RunCommand([adb_path, '-s', android_device,
156 'pull', '/sdcard/output.y4m', test_video])
mandermoed582f72017-01-23 07:55:42 -0800157
158 test_video_yuv = os.path.join(temp_dir, 'test_video.yuv')
159
160 ffmpeg_path = os.path.join(toolchain_dir, 'linux', 'ffmpeg')
161
kjellanderc88b5d52017-04-05 06:42:43 -0700162 def ConvertVideo(input_video, output_video):
mandermoed582f72017-01-23 07:55:42 -0800163 _RunCommand([ffmpeg_path, '-y', '-i', input_video, output_video])
164
kjellanderc88b5d52017-04-05 06:42:43 -0700165 ConvertVideo(test_video, test_video_yuv)
mandermoed582f72017-01-23 07:55:42 -0800166
ehmaldonadod103f4b2017-02-16 07:20:26 -0800167 reference_video = os.path.join(SRC_DIR,
mandermoed582f72017-01-23 07:55:42 -0800168 'resources', 'reference_video_640x360_30fps.y4m')
169
170 reference_video_yuv = os.path.join(temp_dir,
171 'reference_video_640x360_30fps.yuv')
172
kjellanderc88b5d52017-04-05 06:42:43 -0700173 ConvertVideo(reference_video, reference_video_yuv)
mandermoed582f72017-01-23 07:55:42 -0800174
175 # Run compare script.
oprypin30cda5e2017-04-24 04:15:13 -0700176 compare_script = os.path.join(SRC_DIR, 'webrtc', 'tools', 'compare_videos.py')
mandermoed582f72017-01-23 07:55:42 -0800177 zxing_path = os.path.join(toolchain_dir, 'linux', 'zxing')
178
179 # The frame_analyzer binary should be built for local computer and not for
180 # Android
181 frame_analyzer = os.path.join(build_dir_x86, 'frame_analyzer')
182
183 frame_width = 640
184 frame_height = 360
185
186 stats_file_ref = os.path.join(temp_dir, 'stats_ref.txt')
187 stats_file_test = os.path.join(temp_dir, 'stats_test.txt')
188
189 _RunCommand([
190 sys.executable, compare_script, '--ref_video', reference_video_yuv,
191 '--test_video', test_video_yuv, '--yuv_frame_width', str(frame_width),
192 '--yuv_frame_height', str(frame_height),
193 '--stats_file_ref', stats_file_ref,
194 '--stats_file_test', stats_file_test, '--frame_analyzer', frame_analyzer,
195 '--ffmpeg_path', ffmpeg_path, '--zxing_path', zxing_path])
196
197 shutil.rmtree(temp_dir)
198
199
200if __name__ == '__main__':
201 sys.exit(main())
202