xref: /aosp_15_r20/external/autotest/client/cros/video/video_player.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright 2015 The Chromium OS Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Li
5*9c5db199SXin Li
6*9c5db199SXin Liimport datetime, time
7*9c5db199SXin Li
8*9c5db199SXin Lifrom autotest_lib.client.bin import utils
9*9c5db199SXin Lifrom autotest_lib.client.common_lib import error
10*9c5db199SXin Lifrom autotest_lib.client.cros.video import method_logger
11*9c5db199SXin Li
12*9c5db199SXin Li
13*9c5db199SXin Liclass VideoPlayer(object):
14*9c5db199SXin Li    """
15*9c5db199SXin Li    Provides interface to interact with and control video playback via js.
16*9c5db199SXin Li
17*9c5db199SXin Li    Specific players such as VimeoPlayer will inherit from this class and
18*9c5db199SXin Li    customize its behavior.
19*9c5db199SXin Li
20*9c5db199SXin Li    """
21*9c5db199SXin Li
22*9c5db199SXin Li
23*9c5db199SXin Li    def __init__(self, tab, full_url, video_id, video_src_path='',
24*9c5db199SXin Li                 event_timeout=5, polling_wait_time=1):
25*9c5db199SXin Li        """
26*9c5db199SXin Li        @param tab: object, tab to interact with the tab in the browser.
27*9c5db199SXin Li        @param full_url: string, full url pointing to html file to load.
28*9c5db199SXin Li        @param video_src_path: path, complete path to video used for test.
29*9c5db199SXin Li        @param video_id: string, name of the video_id element in the html file.
30*9c5db199SXin Li        @param time_out_for_events_s: integer, how long to wait for an event
31*9c5db199SXin Li                                      before timing out
32*9c5db199SXin Li        @param time_btwn_polling_s: integer, how long to wait between one call
33*9c5db199SXin Li                                    to check a condition and the next.
34*9c5db199SXin Li
35*9c5db199SXin Li        """
36*9c5db199SXin Li        self.tab = tab
37*9c5db199SXin Li        self.full_url = full_url
38*9c5db199SXin Li        self.video_id = video_id
39*9c5db199SXin Li        self.video_src_path = video_src_path
40*9c5db199SXin Li        self.event_timeout = event_timeout
41*9c5db199SXin Li        self.polling_wait_time = polling_wait_time
42*9c5db199SXin Li        self.tab.Navigate(self.full_url)
43*9c5db199SXin Li
44*9c5db199SXin Li
45*9c5db199SXin Li    @method_logger.log
46*9c5db199SXin Li    def load_video(self, wait_for_canplay=True):
47*9c5db199SXin Li        """
48*9c5db199SXin Li        Loads video into browser.
49*9c5db199SXin Li        @param wait_for_canplay: video will be verified before play
50*9c5db199SXin Li
51*9c5db199SXin Li        """
52*9c5db199SXin Li        self.tab.WaitForDocumentReadyStateToBeComplete()
53*9c5db199SXin Li        self.wait_for_script_ready()
54*9c5db199SXin Li        time.sleep(2)
55*9c5db199SXin Li        self.inject_source_file()
56*9c5db199SXin Li        if wait_for_canplay:
57*9c5db199SXin Li             self.wait_for_video_ready()
58*9c5db199SXin Li
59*9c5db199SXin Li
60*9c5db199SXin Li    def inject_source_file(self):
61*9c5db199SXin Li        """
62*9c5db199SXin Li        Injects source file into html file if needed.
63*9c5db199SXin Li
64*9c5db199SXin Li        Created for subclasses that need it
65*9c5db199SXin Li
66*9c5db199SXin Li        """
67*9c5db199SXin Li        pass
68*9c5db199SXin Li
69*9c5db199SXin Li
70*9c5db199SXin Li    @method_logger.log
71*9c5db199SXin Li    def wait_for_script_ready(self):
72*9c5db199SXin Li        """
73*9c5db199SXin Li        Wait for Javascript variables and functions to be defined.
74*9c5db199SXin Li
75*9c5db199SXin Li        """
76*9c5db199SXin Li        exception_msg = 'Script did not ready in time.'
77*9c5db199SXin Li
78*9c5db199SXin Li        self._wait_for_event(self.is_javascript_ready, exception_msg)
79*9c5db199SXin Li
80*9c5db199SXin Li
81*9c5db199SXin Li    @method_logger.log
82*9c5db199SXin Li    def wait_for_video_ready(self):
83*9c5db199SXin Li        """
84*9c5db199SXin Li        Waits for video to signal that is ready.
85*9c5db199SXin Li
86*9c5db199SXin Li        Each class that inherits from this will define its is_video_ready
87*9c5db199SXin Li        function.
88*9c5db199SXin Li
89*9c5db199SXin Li        """
90*9c5db199SXin Li        exception_msg = 'Video did not signal ready in time.'
91*9c5db199SXin Li
92*9c5db199SXin Li        self._wait_for_event(self.is_video_ready, exception_msg)
93*9c5db199SXin Li
94*9c5db199SXin Li
95*9c5db199SXin Li    @method_logger.log
96*9c5db199SXin Li    def verify_video_can_play(self, duration=0):
97*9c5db199SXin Li        """
98*9c5db199SXin Li        Plays video and ensures that reported video current time is > 0.
99*9c5db199SXin Li
100*9c5db199SXin Li        @param duration: duration to play a video
101*9c5db199SXin Li        @raises: error.TestError if current time is not > 0 after time > 0s
102*9c5db199SXin Li
103*9c5db199SXin Li        """
104*9c5db199SXin Li        exception_msg = 'Expected current time >%ds.' %duration
105*9c5db199SXin Li
106*9c5db199SXin Li        self.play()
107*9c5db199SXin Li
108*9c5db199SXin Li        # check that video is playing
109*9c5db199SXin Li        self._wait_for_event(
110*9c5db199SXin Li                  lambda : self.currentTime() > duration, exception_msg)
111*9c5db199SXin Li
112*9c5db199SXin Li        self.pause()
113*9c5db199SXin Li
114*9c5db199SXin Li        # seek back to the beginning of video
115*9c5db199SXin Li        self.seek_to(datetime.timedelta(seconds=0))
116*9c5db199SXin Li
117*9c5db199SXin Li
118*9c5db199SXin Li    @method_logger.log
119*9c5db199SXin Li    def seek_to(self, timestamp):
120*9c5db199SXin Li        """
121*9c5db199SXin Li        Uses javascript to set currentTime property of video to desired time.
122*9c5db199SXin Li
123*9c5db199SXin Li        @param timestamp: timedelta, instance of time to navigate video to.
124*9c5db199SXin Li
125*9c5db199SXin Li        """
126*9c5db199SXin Li        self.seek_to(timestamp)
127*9c5db199SXin Li
128*9c5db199SXin Li
129*9c5db199SXin Li    @method_logger.log
130*9c5db199SXin Li    def wait_for_video_to_seek(self):
131*9c5db199SXin Li        """
132*9c5db199SXin Li        Waits for video's currentTime to equal the time it was seeked to.
133*9c5db199SXin Li
134*9c5db199SXin Li        """
135*9c5db199SXin Li        exception_msg = 'Video did not complete seeking in time.'
136*9c5db199SXin Li
137*9c5db199SXin Li        self._wait_for_event(self.has_video_finished_seeking, exception_msg)
138*9c5db199SXin Li
139*9c5db199SXin Li        # it usually takes a little while before new frame renders, so wait
140*9c5db199SXin Li        time.sleep(1)
141*9c5db199SXin Li
142*9c5db199SXin Li
143*9c5db199SXin Li    @method_logger.log
144*9c5db199SXin Li    def _wait_for_event(self, predicate_function, exception_msg):
145*9c5db199SXin Li        """
146*9c5db199SXin Li         Helper method to wait for a desired condition.
147*9c5db199SXin Li
148*9c5db199SXin Li         @param predicate_function: object, function which returns true when
149*9c5db199SXin Li                                    desired condition is achieved.
150*9c5db199SXin Li         @param exception_msg: string, an exception message to show when desired
151*9c5db199SXin Li                               condition is not achieved in allowed time.
152*9c5db199SXin Li
153*9c5db199SXin Li        """
154*9c5db199SXin Li        fullmsg = exception_msg + ' Waited for %ss' % self.event_timeout
155*9c5db199SXin Li
156*9c5db199SXin Li        utils.poll_for_condition(predicate_function,
157*9c5db199SXin Li                                 error.TestError(fullmsg),
158*9c5db199SXin Li                                 self.event_timeout,
159*9c5db199SXin Li                                 self.polling_wait_time)
160