| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from telemetry.core import bitmap | 5 from telemetry.core import bitmap |
| 6 from telemetry.core import web_contents | 6 from telemetry.core import web_contents |
| 7 | 7 |
| 8 DEFAULT_TAB_TIMEOUT = 60 | 8 DEFAULT_TAB_TIMEOUT = 60 |
| 9 | 9 |
| 10 | 10 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 | 135 |
| 136 Args: | 136 Args: |
| 137 min_bitrate_mbps: The minimum caputre bitrate in MegaBits Per Second. | 137 min_bitrate_mbps: The minimum caputre bitrate in MegaBits Per Second. |
| 138 The platform is free to deliver a higher bitrate if it can do so | 138 The platform is free to deliver a higher bitrate if it can do so |
| 139 without increasing overhead. | 139 without increasing overhead. |
| 140 """ | 140 """ |
| 141 self.Highlight(bitmap.WEB_PAGE_TEST_ORANGE) | 141 self.Highlight(bitmap.WEB_PAGE_TEST_ORANGE) |
| 142 self.browser.platform.StartVideoCapture(min_bitrate_mbps) | 142 self.browser.platform.StartVideoCapture(min_bitrate_mbps) |
| 143 self.ClearHighlight(bitmap.WEB_PAGE_TEST_ORANGE) | 143 self.ClearHighlight(bitmap.WEB_PAGE_TEST_ORANGE) |
| 144 | 144 |
| 145 def _FindHighlightBoundingBox(self, bmp, color): | 145 def _FindHighlightBoundingBox(self, bmp, color, bounds_tolerance=4, |
| 146 color_tolerance=8): |
| 146 """Returns the bounding box of the content highlight of the given color. | 147 """Returns the bounding box of the content highlight of the given color. |
| 147 | 148 |
| 148 Raises: | 149 Raises: |
| 149 BoundingBoxNotFoundException if the hightlight could not be found. | 150 BoundingBoxNotFoundException if the hightlight could not be found. |
| 150 """ | 151 """ |
| 151 content_box, pixel_count = bmp.GetBoundingBox(color, tolerance=8) | 152 content_box, pixel_count = bmp.GetBoundingBox(color, |
| 153 tolerance=color_tolerance) |
| 152 | 154 |
| 153 if not content_box: | 155 if not content_box: |
| 154 raise BoundingBoxNotFoundException('Failed to find tab contents.') | 156 return None |
| 155 | 157 |
| 156 # We assume arbitrarily that tabs are all larger than 200x200. If this | 158 # We assume arbitrarily that tabs are all larger than 200x200. If this |
| 157 # fails it either means that assumption has changed or something is | 159 # fails it either means that assumption has changed or something is |
| 158 # awry with our bounding box calculation. | 160 # awry with our bounding box calculation. |
| 159 if content_box[2] < 200 or content_box[3] < 200: | 161 if content_box[2] < 200 or content_box[3] < 200: |
| 160 raise BoundingBoxNotFoundException('Unexpectedly small tab contents.') | 162 raise BoundingBoxNotFoundException('Unexpectedly small tab contents.') |
| 161 | 163 |
| 162 # TODO(tonyg): Can this threshold be increased? | 164 # TODO(tonyg): Can this threshold be increased? |
| 163 if pixel_count < 0.9 * content_box[2] * content_box[3]: | 165 if pixel_count < 0.9 * content_box[2] * content_box[3]: |
| 164 raise BoundingBoxNotFoundException( | 166 raise BoundingBoxNotFoundException( |
| 165 'Low count of pixels in tab contents matching expected color.') | 167 'Low count of pixels in tab contents matching expected color.') |
| 166 | 168 |
| 167 # Since Telemetry doesn't know how to resize the window, we assume | 169 # Since Telemetry doesn't know how to resize the window, we assume |
| 168 # that we should always get the same content box for a tab. If this | 170 # that we should always get the same content box for a tab. If this |
| 169 # fails, it means either that assumption has changed or something is | 171 # fails, it means either that assumption has changed or something is |
| 170 # awry with our bounding box calculation. If this assumption changes, | 172 # awry with our bounding box calculation. If this assumption changes, |
| 171 # this can be removed. | 173 # this can be removed. |
| 172 # | 174 # |
| 173 # TODO(tonyg): This assert doesn't seem to work. | 175 # TODO(tonyg): This assert doesn't seem to work. |
| 174 if (self._previous_tab_contents_bounding_box and | 176 if (self._previous_tab_contents_bounding_box and |
| 175 self._previous_tab_contents_bounding_box != content_box): | 177 self._previous_tab_contents_bounding_box != content_box): |
| 176 raise BoundingBoxNotFoundException( | 178 # Check if there's just a minor variation on the bounding box. If it's |
| 177 'Unexpected change in tab contents box.') | 179 # just a few pixels, we can assume it's probably due to |
| 180 # compression artifacts. |
| 181 for i in xrange(len(content_box)): |
| 182 bounds_difference = abs(content_box[i] - |
| 183 self._previous_tab_contents_bounding_box[i]) |
| 184 if bounds_difference > bounds_tolerance: |
| 185 raise BoundingBoxNotFoundException( |
| 186 'Unexpected change in tab contents box.') |
| 178 self._previous_tab_contents_bounding_box = content_box | 187 self._previous_tab_contents_bounding_box = content_box |
| 179 | 188 |
| 180 return content_box | 189 return content_box |
| 181 | 190 |
| 182 def StopVideoCapture(self): | 191 def StopVideoCapture(self): |
| 183 """Stops recording video of the tab's contents. | 192 """Stops recording video of the tab's contents. |
| 184 | 193 |
| 185 This looks for the initial color flash in the first frame to establish the | 194 This looks for the initial color flash in the first frame to establish the |
| 186 tab content boundaries and then omits all frames displaying the flash. | 195 tab content boundaries and then omits all frames displaying the flash. |
| 187 | 196 |
| 188 Yields: | 197 Yields: |
| 189 (time_ms, bitmap) tuples representing each video keyframe. Only the first | 198 (time_ms, bitmap) tuples representing each video keyframe. Only the first |
| 190 frame in a run of sequential duplicate bitmaps is typically included. | 199 frame in a run of sequential duplicate bitmaps is typically included. |
| 191 time_ms is milliseconds since navigationStart. | 200 time_ms is milliseconds since navigationStart. |
| 192 bitmap is a telemetry.core.Bitmap. | 201 bitmap is a telemetry.core.Bitmap. |
| 193 """ | 202 """ |
| 194 frame_generator = self.browser.platform.StopVideoCapture() | 203 frame_generator = self.browser.platform.StopVideoCapture() |
| 195 | 204 |
| 196 # Flip through frames until we find the initial tab contents flash. | 205 # Flip through frames until we find the initial tab contents flash. |
| 197 content_box = None | 206 content_box = None |
| 198 for _, bmp in frame_generator: | 207 for _, bmp in frame_generator: |
| 199 try: | 208 content_box = self._FindHighlightBoundingBox( |
| 200 content_box = self._FindHighlightBoundingBox( | 209 bmp, bitmap.WEB_PAGE_TEST_ORANGE) |
| 201 bmp, bitmap.WEB_PAGE_TEST_ORANGE) | 210 if content_box: |
| 202 break | 211 break |
| 203 except BoundingBoxNotFoundException: | |
| 204 pass | |
| 205 | 212 |
| 206 if not content_box: | 213 if not content_box: |
| 207 raise BoundingBoxNotFoundException( | 214 raise BoundingBoxNotFoundException( |
| 208 'Failed to identify tab contents in video capture.') | 215 'Failed to identify tab contents in video capture.') |
| 209 | 216 |
| 210 # Flip through frames until the flash goes away and emit that as frame 0. | 217 # Flip through frames until the flash goes away and emit that as frame 0. |
| 211 timestamp = 0 | 218 timestamp = 0 |
| 212 for timestamp, bmp in frame_generator: | 219 for timestamp, bmp in frame_generator: |
| 213 try: | 220 if not self._FindHighlightBoundingBox(bmp, bitmap.WEB_PAGE_TEST_ORANGE): |
| 214 self._FindHighlightBoundingBox(bmp, bitmap.WEB_PAGE_TEST_ORANGE) | |
| 215 except BoundingBoxNotFoundException: | |
| 216 yield 0, bmp.Crop(*content_box) | 221 yield 0, bmp.Crop(*content_box) |
| 217 break | 222 break |
| 218 | 223 |
| 219 start_time = timestamp | 224 start_time = timestamp |
| 220 for timestamp, bmp in frame_generator: | 225 for timestamp, bmp in frame_generator: |
| 221 yield timestamp - start_time, bmp.Crop(*content_box) | 226 yield timestamp - start_time, bmp.Crop(*content_box) |
| 222 | 227 |
| 223 def PerformActionAndWaitForNavigate( | 228 def PerformActionAndWaitForNavigate( |
| 224 self, action_function, timeout=DEFAULT_TAB_TIMEOUT): | 229 self, action_function, timeout=DEFAULT_TAB_TIMEOUT): |
| 225 """Executes action_function, and waits for the navigation to complete. | 230 """Executes action_function, and waits for the navigation to complete. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 244 def GetCookieByName(self, name, timeout=DEFAULT_TAB_TIMEOUT): | 249 def GetCookieByName(self, name, timeout=DEFAULT_TAB_TIMEOUT): |
| 245 """Returns the value of the cookie by the given |name|.""" | 250 """Returns the value of the cookie by the given |name|.""" |
| 246 return self._inspector_backend.GetCookieByName(name, timeout) | 251 return self._inspector_backend.GetCookieByName(name, timeout) |
| 247 | 252 |
| 248 def CollectGarbage(self): | 253 def CollectGarbage(self): |
| 249 self._inspector_backend.CollectGarbage() | 254 self._inspector_backend.CollectGarbage() |
| 250 | 255 |
| 251 def ClearCache(self): | 256 def ClearCache(self): |
| 252 """Clears the browser's HTTP disk cache and the tab's HTTP memory cache.""" | 257 """Clears the browser's HTTP disk cache and the tab's HTTP memory cache.""" |
| 253 self._inspector_backend.ClearCache() | 258 self._inspector_backend.ClearCache() |
| OLD | NEW |