1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import time 7 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error 10from autotest_lib.client.cros.graphics import graphics_utils 11 12 13PLAYBACK_TEST_TIME_S = 10 14PLAYER_ENDED_STATE = 'Ended' 15PLAYER_PAUSE_STATE = 'Paused' 16PLAYER_PLAYING_STATE = 'Playing' 17WAIT_TIMEOUT_S = 20 18 19 20class YouTubeHelper(object): 21 """A helper class contains YouTube related utility functions. 22 23 To use this class, please call wait_for_player_state(playing) as below 24 before calling set_video_duration. Please note that set_video_duration 25 must be called in order to access few functions which uses the video 26 length member variable. 27 28 yh = youtube_helper.YouTubeHelper(tab) 29 yh.wait_for_player_state(PLAYER_PLAYING_STATE) 30 yh.set_video_duration() 31 32 """ 33 34 def __init__(self, youtube_tab): 35 self._tab = youtube_tab 36 self._video_duration = 0 37 38 39 def set_video_duration(self): 40 """Sets the video duration.""" 41 self._video_duration = (int(self._tab.EvaluateJavaScript( 42 'player.getDuration()'))) 43 44 def video_current_time(self): 45 """Returns video's current playback time. 46 47 Returns: 48 returns the current playback location in seconds (int). 49 50 """ 51 return int(self._tab.EvaluateJavaScript('player.getCurrentTime()')) 52 53 def get_player_status(self): 54 """Returns the player status.""" 55 return self._tab.EvaluateJavaScript( 56 '(typeof playerStatus !== \'undefined\') && ' 57 'playerStatus.innerHTML') 58 59 def get_playback_quality(self): 60 """Returns the playback quality.""" 61 return self._tab.EvaluateJavaScript('player.getPlaybackQuality()') 62 63 def wait_for_player_state(self, expected_status): 64 """Wait till the player status changes to expected_status. 65 66 If the status doesn't change for long, the test will time out after 67 WAIT_TIMEOUT_S and fails. 68 69 @param expected_status: status which is expected for the test 70 to continue. 71 72 """ 73 utils.poll_for_condition( 74 lambda: self.get_player_status() == expected_status, 75 exception=error.TestError( 76 'Video failed to load. Player expected status: %s' 77 ' and current status: %s.' 78 % (expected_status, self.get_player_status())), 79 timeout=WAIT_TIMEOUT_S, 80 sleep_interval=1) 81 82 def verify_video_playback(self): 83 """Verify the video playback.""" 84 logging.info('Verifying the YouTube video playback.') 85 playback = 0 # seconds 86 prev_playback = 0 87 count = 0 88 while (self.video_current_time() < self._video_duration 89 and playback < PLAYBACK_TEST_TIME_S): 90 time.sleep(1) 91 if self.video_current_time() <= prev_playback: 92 if count < 2: 93 logging.info('Retrying to video playback test.') 94 self._tab.ExecuteJavaScript( 95 'player.seekTo(%d, true)' 96 % (self.video_current_time() + 2)) 97 time.sleep(1) 98 count = count + 1 99 else: 100 player_status = self.get_player_status() 101 raise error.TestError( 102 'Video is not playing. Player status: %s.' % 103 player_status) 104 prev_playback = self.video_current_time() 105 playback = playback + 1 106 107 def verify_player_states(self): 108 """Verify the player states like play, pause, ended and seek.""" 109 logging.info('Verifying the player states.') 110 self._tab.ExecuteJavaScript('player.pauseVideo()') 111 self.wait_for_player_state(PLAYER_PAUSE_STATE) 112 self._tab.ExecuteJavaScript('player.playVideo()') 113 self.wait_for_player_state(PLAYER_PLAYING_STATE) 114 # We are seeking the player position to (video length - 2 seconds). 115 # Since the player waits for WAIT_TIMEOUT_S for the status change, 116 # the video should be ended before we hit the timeout. 117 video_end_test_duration = (self._video_duration - 118 self.video_current_time() - 2) 119 if video_end_test_duration >= WAIT_TIMEOUT_S: 120 self._tab.ExecuteJavaScript( 121 'player.seekTo(%d, true)' % (self._video_duration - 5)) 122 self.wait_for_player_state(PLAYER_ENDED_STATE) 123 else: 124 raise error.TestError( 125 'Test video is not long enough for the video end test.') 126 # Verifying seek back from the end position. 127 self._tab.ExecuteJavaScript('player.seekTo(%d, true)' 128 % (self._video_duration / 2)) 129 self.wait_for_player_state(PLAYER_PLAYING_STATE) 130 # So the playback doesn't stay at the mid. 131 seek_test = False 132 for _ in range(WAIT_TIMEOUT_S): 133 logging.info('Waiting for seek position to change.') 134 time.sleep(1) 135 seek_position = self.video_current_time() 136 if (seek_position > self._video_duration / 2 137 and seek_position < self._video_duration): 138 seek_test = True 139 break 140 if not seek_test: 141 raise error.TestError( 142 'Seek location is wrong. ' 143 'Video length: %d, seek position: %d.' % 144 (self._video_duration, seek_position)) 145