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, time
      6 
      7 from autotest_lib.client.bin import utils
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.cros.graphics import graphics_utils
     10 
     11 
     12 PLAYBACK_TEST_TIME_S = 10
     13 PLAYER_ENDED_STATE = 'Ended'
     14 PLAYER_PAUSE_STATE = 'Paused'
     15 PLAYER_PLAYING_STATE = 'Playing'
     16 WAIT_TIMEOUT_S = 20
     17 
     18 
     19 class YouTubeHelper(object):
     20     """A helper class contains YouTube related utility functions.
     21 
     22        To use this class, please call wait_for_player_state(playing) as below
     23        before calling set_video_duration. Please note that set_video_duration
     24        must be called in order to access few functions which uses the video
     25        length member variable.
     26 
     27        yh = youtube_helper.YouTubeHelper(tab)
     28        yh.wait_for_player_state(PLAYER_PLAYING_STATE)
     29        yh.set_video_duration()
     30 
     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 
     45     def video_current_time(self):
     46         """Returns video's current playback time.
     47 
     48         Returns:
     49             returns the current playback location in seconds (int).
     50 
     51         """
     52         return int(self._tab.EvaluateJavaScript('player.getCurrentTime()'))
     53 
     54 
     55     def get_player_status(self):
     56         """Returns the player status."""
     57         return self._tab.EvaluateJavaScript(
     58                 '(typeof playerStatus !== \'undefined\') && '
     59                 'playerStatus.innerHTML')
     60 
     61 
     62     def set_playback_quality(self, quality):
     63         """Set the video quality to the quality passed in the arg.
     64 
     65         @param quality: video quality to set.
     66 
     67         """
     68         self._tab.ExecuteJavaScript(
     69                 'player.setPlaybackQuality("%s")' % quality)
     70 
     71 
     72     def get_playback_quality(self):
     73         """Returns the playback quality."""
     74         return self._tab.EvaluateJavaScript('player.getPlaybackQuality()')
     75 
     76 
     77     def wait_for_player_state(self, expected_status):
     78         """Wait till the player status changes to expected_status.
     79 
     80         If the status doesn't change for long, the test will time out after
     81         WAIT_TIMEOUT_S and fails.
     82 
     83         @param expected_status: status which is expected for the test
     84                                 to continue.
     85 
     86         """
     87         utils.poll_for_condition(
     88             lambda: self.get_player_status() == expected_status,
     89             exception=error.TestError(
     90                         'Video failed to load. Player expected status: %s'
     91                         ' and current status: %s.'
     92                         % (expected_status, self.get_player_status())),
     93             timeout=WAIT_TIMEOUT_S,
     94             sleep_interval=1)
     95 
     96     def verify_video_playback(self):
     97         """Verify the video playback."""
     98         logging.info('Verifying the YouTube video playback.')
     99         playback = 0 # seconds
    100         prev_playback = 0
    101         count = 0
    102         while (self.video_current_time() < self._video_duration
    103                and playback < PLAYBACK_TEST_TIME_S):
    104             time.sleep(1)
    105             if self.video_current_time() <= prev_playback:
    106                 if count < 2:
    107                     logging.info('Retrying to video playback test.')
    108                     self._tab.ExecuteJavaScript(
    109                             'player.seekTo(%d, true)'
    110                             % (self.video_current_time() + 2))
    111                     time.sleep(1)
    112                     count = count + 1
    113                 else:
    114                     player_status = self.get_player_status()
    115                     raise error.TestError(
    116                             'Video is not playing. Player status: %s.' %
    117                             player_status)
    118             prev_playback = self.video_current_time()
    119             playback = playback + 1
    120 
    121 
    122     def wait_for_expected_resolution(self, expected_quality):
    123         """Wait for some time for getting expected resolution.
    124 
    125         @param expected_quality: quality to be set.
    126 
    127         """
    128         for _ in range(WAIT_TIMEOUT_S):
    129             dummy_quality = self.get_playback_quality()
    130             if dummy_quality == expected_quality:
    131                 logging.info('Expected resolution is set.')
    132                 break
    133             else:
    134                 logging.info('Waiting for expected resolution.')
    135                 time.sleep(0.1)
    136 
    137 
    138     def verify_video_resolutions(self):
    139         """Verify available video resolutions.
    140 
    141         Video resolution should be 360p, 480p, 720p and 1080p.
    142 
    143         """
    144         logging.info('Verifying the video resolutions.')
    145         video_qualities = self._tab.EvaluateJavaScript(
    146                 'player.getAvailableQualityLevels()')
    147         logging.info('Available video resolutions: %s', video_qualities)
    148         if not video_qualities:
    149             raise error.TestError(
    150                     'Player failed to return available video qualities.')
    151         video_qualities.reverse()
    152 
    153         running_quality = self.get_playback_quality()
    154         index = video_qualities.index(running_quality)
    155         supporting_qualities = video_qualities[index :]
    156         logging.info("new video quality %s ", supporting_qualities)
    157 
    158         width, height = graphics_utils.get_internal_resolution()
    159         logging.info('checking resolution: %d width  %d height', width, height)
    160         for quality in supporting_qualities:
    161             logging.info('Playing video in %s quality.', quality)
    162             self.set_playback_quality(quality)
    163             self.wait_for_player_state(PLAYER_PLAYING_STATE)
    164             self.wait_for_expected_resolution(quality)
    165             current_quality = self.get_playback_quality()
    166 
    167             if current_quality != quality :
    168               raise error.TestError(
    169                       'Expected video quality: %s. Current video quality: %s'
    170                              % (quality, current_quality))
    171 
    172             time.sleep(1)
    173 
    174 
    175     def verify_player_states(self):
    176         """Verify the player states like play, pause, ended and seek."""
    177         logging.info('Verifying the player states.')
    178         self._tab.ExecuteJavaScript('player.pauseVideo()')
    179         self.wait_for_player_state(PLAYER_PAUSE_STATE)
    180         self._tab.ExecuteJavaScript('player.playVideo()')
    181         self.wait_for_player_state(PLAYER_PLAYING_STATE)
    182         # We are seeking the player position to (video length - 2 seconds).
    183         # Since the player waits for WAIT_TIMEOUT_S for the status change,
    184         # the video should be ended before we hit the timeout.
    185         video_end_test_duration = (self._video_duration -
    186                                    self.video_current_time() - 2)
    187         if video_end_test_duration >= WAIT_TIMEOUT_S:
    188             self._tab.ExecuteJavaScript(
    189                     'player.seekTo(%d, true)' % (self._video_duration - 5))
    190             self.wait_for_player_state(PLAYER_ENDED_STATE)
    191         else:
    192             raise error.TestError(
    193                     'Test video is not long enough for the video end test.')
    194         # Verifying seek back from the end position.
    195         self._tab.ExecuteJavaScript('player.seekTo(%d, true)'
    196                                     % (self._video_duration / 2))
    197         self.wait_for_player_state(PLAYER_PLAYING_STATE)
    198         # So the playback doesn't stay at the mid.
    199         seek_test = False
    200         for _ in range(WAIT_TIMEOUT_S):
    201             logging.info('Waiting for seek position to change.')
    202             time.sleep(1)
    203             seek_position = self.video_current_time()
    204             if (seek_position > self._video_duration / 2
    205                     and seek_position < self._video_duration):
    206                 seek_test = True
    207                 break
    208         if not seek_test:
    209             raise error.TestError(
    210                     'Seek location is wrong. '
    211                     'Video length: %d, seek position: %d.' %
    212                     (self._video_duration, seek_position))
    213