15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// FPSObserver observes a <video> and reports decoded FPS, dropped FPS, and
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// total dropped frames during the video playback.
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)var FPSObserver = new function() {
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.video_ = null;
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.decodedFrames_ = 0;
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.droppedFrames_ = 0;
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.startTime_ = 0;
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.intID_ = null;
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FPSObserver.observe = function(video) {
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.video_ = video;
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var observer = this;
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.video_.addEventListener('playing', function() {
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    observer.onVideoPlaying();
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  });
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.video_.addEventListener('error', function() {
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    observer.endTest();
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  });
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.video_.addEventListener('ended', function() {
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    observer.endTest();
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  });
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FPSObserver.onVideoPlaying = function() {
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.decodedFrames_ = 0;
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.droppedFrames_ = 0;
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.startTime_ = window.performance.now();
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.endTest(true);
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var observer = this;
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.intID_ = window.setInterval(function() {
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      observer.calculateStats();}, 1000);
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FPSObserver.calculateStats = function() {
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (this.video_.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA ||
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      this.video_.paused || this.video_.ended)
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var currentTime = window.performance.now();
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var deltaTime = (currentTime - this.startTime_) / 1000;
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.startTime_ = currentTime;
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Calculate decoded frames per sec.
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  var fps = (this.video_.webkitDecodedFrameCount - this.decodedFrames_) /
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)             deltaTime;
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.decodedFrames_ = this.video_.webkitDecodedFrameCount;
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fps = fps.toFixed(2);
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  decodedFPSElement.innerHTML = fps;
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Calculate dropped frames per sec.
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fps = (this.video_.webkitDroppedFrameCount - this.droppedFrames_) / deltaTime;
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  this.droppedFrames_ = this.video_.webkitDroppedFrameCount;
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  fps = fps.toFixed(2);
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  droppedFPSElement.innerHTML = fps;
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  droppedFramesElement.innerHTML = this.droppedFrames_;
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FPSObserver.endTest = function() {
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  window.clearInterval(this.intID_);
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
68