dom/media/MediaStatistics.h
author Timothy Guan-tin Chien <timdream@gmail.com>
Mon, 07 Jan 2019 16:00:55 +0000
changeset 506594 2046aa36055220d9187f968fca3ab070d2de7665
parent 503396 0ceae9db9ec0be18daa1a279511ad305723185d4
permissions -rw-r--r--
Bug 1516292 - Use isSameNode() to compare mozFullScreenElement and the video host element. r=edgar, a=RyanVM This does what's done in bug 1505547 but in a different way. For some reason, access shadowRoot.host in the function can trigger an assertion. this.video is a Proxy so it cannot be compared, but all its methods are proxied. Differential Revision: https://phabricator.services.mozilla.com/D15767

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef MediaStatistics_h_
#define MediaStatistics_h_

namespace mozilla {

struct MediaStatistics {
  // Estimate of the current playback rate (bytes/second).
  double mPlaybackRate;
  // Estimate of the current download rate (bytes/second). This
  // ignores time that the channel was paused by Gecko.
  double mDownloadRate;
  // Total length of media stream in bytes; -1 if not known
  int64_t mTotalBytes;
  // Current position of the download, in bytes. This is the offset of
  // the first uncached byte after the decoder position.
  int64_t mDownloadPosition;
  // Current position of playback, in bytes
  int64_t mPlaybackPosition;
  // If false, then mDownloadRate cannot be considered a reliable
  // estimate (probably because the download has only been running
  // a short time).
  bool mDownloadRateReliable;
  // If false, then mPlaybackRate cannot be considered a reliable
  // estimate (probably because playback has only been running
  // a short time).
  bool mPlaybackRateReliable;

  bool CanPlayThrough() {
    // Number of estimated seconds worth of data we need to have buffered
    // ahead of the current playback position before we allow the media decoder
    // to report that it can play through the entire media without the decode
    // catching up with the download. Having this margin make the
    // CanPlayThrough() calculation more stable in the case of
    // fluctuating bitrates.
    static const int64_t CAN_PLAY_THROUGH_MARGIN = 1;

    if ((mTotalBytes < 0 && mDownloadRateReliable) ||
        (mTotalBytes >= 0 && mTotalBytes == mDownloadPosition)) {
      return true;
    }

    if (!mDownloadRateReliable || !mPlaybackRateReliable) {
      return false;
    }

    int64_t bytesToDownload = mTotalBytes - mDownloadPosition;
    int64_t bytesToPlayback = mTotalBytes - mPlaybackPosition;
    double timeToDownload = bytesToDownload / mDownloadRate;
    double timeToPlay = bytesToPlayback / mPlaybackRate;

    if (timeToDownload > timeToPlay) {
      // Estimated time to download is greater than the estimated time to play.
      // We probably can't play through without having to stop to buffer.
      return false;
    }

    // Estimated time to download is less than the estimated time to play.
    // We can probably play through without having to buffer, but ensure that
    // we've got a reasonable amount of data buffered after the current
    // playback position, so that if the bitrate of the media fluctuates, or if
    // our download rate or decode rate estimation is otherwise inaccurate,
    // we don't suddenly discover that we need to buffer. This is particularly
    // required near the start of the media, when not much data is downloaded.
    int64_t readAheadMargin =
        static_cast<int64_t>(mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
    return mDownloadPosition > mPlaybackPosition + readAheadMargin;
  }
};

}  // namespace mozilla

#endif  // MediaStatistics_h_