• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, time
6
7from autotest_lib.client.bin import utils
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.cros.graphics import graphics_utils
10
11
12PLAYBACK_TEST_TIME_S = 10
13PLAYER_ENDED_STATE = 'Ended'
14PLAYER_PAUSE_STATE = 'Paused'
15PLAYER_PLAYING_STATE = 'Playing'
16WAIT_TIMEOUT_S = 20
17
18
19class 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