# Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import datetime, time from autotest_lib.client.bin import utils from autotest_lib.client.common_lib import error from autotest_lib.client.cros.video import method_logger class VideoPlayer(object): """ Provides interface to interact with and control video playback via js. Specific players such as VimeoPlayer will inherit from this class and customize its behavior. """ def __init__(self, tab, full_url, video_id, video_src_path='', event_timeout=5, polling_wait_time=1): """ @param tab: object, tab to interact with the tab in the browser. @param full_url: string, full url pointing to html file to load. @param video_src_path: path, complete path to video used for test. @param video_id: string, name of the video_id element in the html file. @param time_out_for_events_s: integer, how long to wait for an event before timing out @param time_btwn_polling_s: integer, how long to wait between one call to check a condition and the next. """ self.tab = tab self.full_url = full_url self.video_id = video_id self.video_src_path = video_src_path self.event_timeout = event_timeout self.polling_wait_time = polling_wait_time self.tab.Navigate(self.full_url) @method_logger.log def load_video(self, wait_for_canplay=True): """ Loads video into browser. @param wait_for_canplay: video will be verified before play """ self.tab.WaitForDocumentReadyStateToBeComplete() self.wait_for_script_ready() time.sleep(2) self.inject_source_file() if wait_for_canplay: self.wait_for_video_ready() def inject_source_file(self): """ Injects source file into html file if needed. Created for subclasses that need it """ pass @method_logger.log def wait_for_script_ready(self): """ Wait for Javascript variables and functions to be defined. """ exception_msg = 'Script did not ready in time.' self._wait_for_event(self.is_javascript_ready, exception_msg) @method_logger.log def wait_for_video_ready(self): """ Waits for video to signal that is ready. Each class that inherits from this will define its is_video_ready function. """ exception_msg = 'Video did not signal ready in time.' self._wait_for_event(self.is_video_ready, exception_msg) @method_logger.log def verify_video_can_play(self, duration=0): """ Plays video and ensures that reported video current time is > 0. @param duration: duration to play a video @raises: error.TestError if current time is not > 0 after time > 0s """ exception_msg = 'Expected current time >%ds.' %duration self.play() # check that video is playing self._wait_for_event( lambda : self.currentTime() > duration, exception_msg) self.pause() # seek back to the beginning of video self.seek_to(datetime.timedelta(seconds=0)) @method_logger.log def seek_to(self, timestamp): """ Uses javascript to set currentTime property of video to desired time. @param timestamp: timedelta, instance of time to navigate video to. """ self.seek_to(timestamp) @method_logger.log def wait_for_video_to_seek(self): """ Waits for video's currentTime to equal the time it was seeked to. """ exception_msg = 'Video did not complete seeking in time.' self._wait_for_event(self.has_video_finished_seeking, exception_msg) # it usually takes a little while before new frame renders, so wait time.sleep(1) @method_logger.log def _wait_for_event(self, predicate_function, exception_msg): """ Helper method to wait for a desired condition. @param predicate_function: object, function which returns true when desired condition is achieved. @param exception_msg: string, an exception message to show when desired condition is not achieved in allowed time. """ fullmsg = exception_msg + ' Waited for %ss' % self.event_timeout utils.poll_for_condition(predicate_function, error.TestError(fullmsg), self.event_timeout, self.polling_wait_time)