Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: chrome/test/functional/media/media_jerky.py

Issue 222873002: Remove pyauto tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: sync Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Jerkiness performance test for video playback.
7
8 Uses jerky tool, (http://go/jerky), to record a jerkiness metric for videos
9 sensitive to jerkiness.
10
11 Jerkiness is defined as a percentage of the average on screen frame time by the
12 formula below. Where smoothed_frame_time[i] represents a frame's on screen time
13 plus amortized measurement gap error (time taken to capture each frame).
14
15 sqrt(average((avg_frame_time - smoothed_frame_time[i])^2, i=m..n))
16 ------------------------------------------------------------------
17 avg_frame_time
18
19 Currently, only the Linux binaries are checked in for this test since we only
20 have a Linux performance bot. The current binary is a custom build with some
21 fixes from veganjerky (http://go/veganjerky) for timing, waiting, and stdout
22 flushing.
23
24 TODO(dalecurtis): Move Jerky tool sources into the Chromium tree.
25
26 TODO(dalecurtis): Jerky tool uses a questionable method for determining torn
27 frames, determine if it is actually worth recording.
28 """
29
30 import glob
31 import logging
32 import os
33 import re
34 import subprocess
35 import tempfile
36
37 import pyauto_media
38 import pyauto
39 import pyauto_utils
40
41 # HTML test path; relative to src/chrome/test/data.
42 _TEST_HTML_PATH = os.path.join('media', 'html', 'media_jerky.html')
43
44 # Path under data path for test files.
45 _TEST_MEDIA_PATH = os.path.join('pyauto_private', 'media', 'birds')
46
47 # Path to Jerky tool executable.
48 _JERKY_PATH = os.path.join('pyauto_private', 'media', 'tools', 'jerky')
49
50 # Regular expression for extracting jerkiness percentage. Sample line:
51 # using 1:9 title 'test.log (35.36% jerky, 0 teared frames)' lw 2 with lines
52 _JERKY_LOG_REGEX = re.compile(
53 r'\((\d{0,3}\.?\d{0,2})% jerky, (\d+) teared frames\)')
54
55 # Regular expression for extracting computed fps. Sample line:
56 # INFO: 33797 us per frame => 29.6 fps.
57 _JERKY_LOG_FPS_REGEX = re.compile(r' => (\d+\.\d+) fps')
58
59 # Minimum and maximum number of iterations for each test. Due to timing issues
60 # the jerky tool may not always calculate the fps correctly. When invalid
61 # results are detected, the test is rerun up to the maxium # of times set below.
62 _JERKY_ITERATIONS_MIN = 3
63 _JERKY_ITERATIONS_MAX = 10
64
65 # The media files used for testing. Each entry represents a tuple of (filename,
66 # width, height, fps). The width and height are used to create a calibration
67 # pattern for jerky tool. The fps is used to ensure Jerky tool computed a valid
68 # result.
69 _TEST_VIDEOS = [('birds540.webm', 960, 540, 29.9)]
70
71
72 def GetTempFilename():
73 """Returns an absolute path to an empty temp file."""
74 f, path = tempfile.mkstemp(prefix='jerky_tmp')
75 os.close(f)
76 return path
77
78
79 class MediaJerkyPerfTest(pyauto.PyUITest):
80 """PyAuto test container. See file doc string for more information."""
81
82 def StartJerkyCapture(self):
83 """Starts jerky tool in capture mode and waits until its ready to capture.
84
85 Returns:
86 A tuple of the jerky process and an absolute path to the capture log.
87 """
88 jerky_log = GetTempFilename()
89 logging.debug('Logging data to %s', jerky_log)
90 process = subprocess.Popen(
91 [os.path.join(self.DataDir(), _JERKY_PATH),
92 'capture', '--log', jerky_log],
93 stdout=subprocess.PIPE)
94
95 # Set the jerky tool process to soft-realtime w/ round-robin scheduling.
96 subprocess.check_call(['sudo', 'chrt', '-r', '-p', str(process.pid)])
97
98 # Wait for server to start up.
99 line = True
100 while line:
101 line = process.stdout.readline()
102 if 'Waiting for calibration pattern to disappear' in line:
103 return process, jerky_log
104 self.fail('Failed to launch Jerky tool.')
105
106 def AnalyzeJerkyCapture(self, jerky_log):
107 """Run jerky analyze on the specified log and return various metrics.
108
109 Once analyze has completed, the jerky_log and associated outputs will be
110 removed.
111
112 Args:
113 jerky_log: Absolute path to the capture log.
114
115 Returns:
116 Tuple of fps, jerkiness, and torn frames.
117 """
118 results_log_base = GetTempFilename()
119 process = subprocess.Popen(
120 [os.path.join(self.DataDir(), _JERKY_PATH),
121 'analyze', '--ref', jerky_log, '--out', results_log_base],
122 stdout=subprocess.PIPE)
123
124 # Wait for process to end w/o risking deadlock.
125 stdout = process.communicate()[0]
126 self.assertEquals(process.returncode, 0)
127
128 # Scrape out the calculated FPS.
129 fps_match = None
130 for line in stdout.splitlines():
131 fps_match = _JERKY_LOG_FPS_REGEX.search(line)
132 if fps_match:
133 break
134
135 # Open *.error.gnuplot and scrape out jerkiness.
136 jerky_match = None
137 with open('%s.error.gnuplot' % results_log_base) as results:
138 for line in results:
139 jerky_match = _JERKY_LOG_REGEX.search(line)
140 if jerky_match:
141 break
142
143 # Cleanup all the temp and results files jerky spits out.
144 for log in glob.glob('%s*' % results_log_base) + [jerky_log]:
145 os.unlink(log)
146
147 if fps_match and jerky_match:
148 return (float(fps_match.group(1)), float(jerky_match.group(1)),
149 int(jerky_match.group(2)))
150 return None, None, None
151
152 def testMediaJerkyPerformance(self):
153 """Launches Jerky tool and records jerkiness for HTML5 videos.
154
155 For each video, the test starts up jerky tool then plays until the Jerky
156 tool collects enough information. Next the capture log is analyzed using
157 Jerky's analyze command. If the computed fps matches the expected fps the
158 jerkiness metric is recorded.
159
160 The test will run up to _JERKY_ITERATIONS_MAX times in an attempt to get at
161 least _JERKY_ITERATIONS_MIN valid values. The results are recorded under
162 the 'jerkiness' variable for graphing on the bots.
163 """
164 self.NavigateToURL(self.GetFileURLForDataPath(_TEST_HTML_PATH))
165
166 # Xvfb on the bots is restricted to 1024x768 at present. Ensure we're using
167 # all of the real estate we can. Jerky tool needs a clear picture of every
168 # frame, so we can't clip the video in any way.
169 self.SetWindowDimensions(0, 0, 1024, 768)
170
171 for name, width, height, expected_fps in _TEST_VIDEOS:
172 jerkiness = []
173 torn_frames = []
174 file_url = self.GetFileURLForDataPath(
175 os.path.join(_TEST_MEDIA_PATH, name))
176
177 # Initialize the calibration area for Jerky tool.
178 self.assertTrue(self.ExecuteJavascript(
179 'initializeTest(%d, %d);' % (width, height)))
180
181 runs_left = _JERKY_ITERATIONS_MIN
182 runs_total = 0
183 while runs_left > 0 and runs_total < _JERKY_ITERATIONS_MAX:
184 runs_total += 1
185 logging.info('Running Jerky perf test #%d for %s.', runs_total, name)
186
187 # Startup Jerky tool in capture mode.
188 jerky_process, jerky_log = self.StartJerkyCapture()
189
190 # Start playback of the test video.
191 self.assertTrue(self.ExecuteJavascript("startTest('%s');" % file_url))
192
193 # Wait for jerky tool to finish if it hasn't already.
194 self.assertTrue(jerky_process.wait() == 0)
195
196 # Stop playback of the test video so the next run can cleanly find the
197 # calibration zone.
198 self.assertTrue(self.ExecuteJavascript('stopTest();'))
199
200 # Analyze the results.
201 jerky_fps, jerky_percent, jerky_torn_frames = self.AnalyzeJerkyCapture(
202 jerky_log)
203 if (jerky_fps is None or jerky_percent is None or
204 jerky_torn_frames is None):
205 logging.error('No metrics recorded for this run.')
206 continue
207
208 # Ensure the results for this run are valid.
209 if jerky_fps != expected_fps:
210 logging.error(
211 'Invalid fps detected (actual: %f, expected: %f, jerkiness: %f). '
212 'Discarding results for this run.', jerky_fps, expected_fps,
213 jerky_percent)
214 continue
215
216 jerkiness.append(jerky_percent)
217 torn_frames.append(jerky_torn_frames)
218 runs_left -= 1
219
220 pyauto_utils.PrintPerfResult('jerkiness', name, jerkiness, '%')
221
222
223 if __name__ == '__main__':
224 pyauto_media.Main()
OLDNEW
« no previous file with comments | « chrome/test/functional/media/media_constrained_network_perf.py ('k') | chrome/test/functional/media/media_scrub_perf.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698