Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef MediaStatistics_h_
8 : #define MediaStatistics_h_
9 :
10 : namespace mozilla {
11 :
12 : struct MediaStatistics {
13 : // Estimate of the current playback rate (bytes/second).
14 : double mPlaybackRate;
15 : // Estimate of the current download rate (bytes/second). This
16 : // ignores time that the channel was paused by Gecko.
17 : double mDownloadRate;
18 : // Total length of media stream in bytes; -1 if not known
19 : int64_t mTotalBytes;
20 : // Current position of the download, in bytes. This is the offset of
21 : // the first uncached byte after the decoder position.
22 : int64_t mDownloadPosition;
23 : // Current position of decoding, in bytes (how much of the stream
24 : // has been consumed)
25 : int64_t mDecoderPosition;
26 : // Current position of playback, in bytes
27 : int64_t mPlaybackPosition;
28 : // If false, then mDownloadRate cannot be considered a reliable
29 : // estimate (probably because the download has only been running
30 : // a short time).
31 : bool mDownloadRateReliable;
32 : // If false, then mPlaybackRate cannot be considered a reliable
33 : // estimate (probably because playback has only been running
34 : // a short time).
35 : bool mPlaybackRateReliable;
36 :
37 0 : bool CanPlayThrough()
38 : {
39 : // Number of estimated seconds worth of data we need to have buffered
40 : // ahead of the current playback position before we allow the media decoder
41 : // to report that it can play through the entire media without the decode
42 : // catching up with the download. Having this margin make the
43 : // CanPlayThrough() calculation more stable in the case of
44 : // fluctuating bitrates.
45 : static const int64_t CAN_PLAY_THROUGH_MARGIN = 1;
46 :
47 0 : if ((mTotalBytes < 0 && mDownloadRateReliable) ||
48 0 : (mTotalBytes >= 0 && mTotalBytes == mDownloadPosition)) {
49 0 : return true;
50 : }
51 :
52 0 : if (!mDownloadRateReliable || !mPlaybackRateReliable) {
53 0 : return false;
54 : }
55 :
56 0 : int64_t bytesToDownload = mTotalBytes - mDownloadPosition;
57 0 : int64_t bytesToPlayback = mTotalBytes - mPlaybackPosition;
58 0 : double timeToDownload = bytesToDownload / mDownloadRate;
59 0 : double timeToPlay = bytesToPlayback / mPlaybackRate;
60 :
61 0 : if (timeToDownload > timeToPlay) {
62 : // Estimated time to download is greater than the estimated time to play.
63 : // We probably can't play through without having to stop to buffer.
64 0 : return false;
65 : }
66 :
67 : // Estimated time to download is less than the estimated time to play.
68 : // We can probably play through without having to buffer, but ensure that
69 : // we've got a reasonable amount of data buffered after the current
70 : // playback position, so that if the bitrate of the media fluctuates, or if
71 : // our download rate or decode rate estimation is otherwise inaccurate,
72 : // we don't suddenly discover that we need to buffer. This is particularly
73 : // required near the start of the media, when not much data is downloaded.
74 : int64_t readAheadMargin =
75 0 : static_cast<int64_t>(mPlaybackRate * CAN_PLAY_THROUGH_MARGIN);
76 0 : return mDownloadPosition > mPlaybackPosition + readAheadMargin;
77 : }
78 : };
79 :
80 : } // namespace mozilla
81 :
82 : #endif // MediaStatistics_h_
|