Home | History | Annotate | Download | only in video
      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 
      5 import logging
      6 import time
      7 
      8 from autotest_lib.client.bin import utils
      9 from autotest_lib.client.common_lib import error
     10 from autotest_lib.client.cros.graphics import graphics_utils
     11 
     12 
     13 PLAYBACK_TEST_TIME_S = 10
     14 PLAYER_ENDED_STATE = 'Ended'
     15 PLAYER_PAUSE_STATE = 'Paused'
     16 PLAYER_PLAYING_STATE = 'Playing'
     17 WAIT_TIMEOUT_S = 20
     18 
     19 
     20 class 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