summaryrefslogtreecommitdiffstats
path: root/dom/media/utils/TelemetryProbesReporter.h
blob: 0f6e18db68ab6099cc622fb2eb0d8a665cb0f0b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* 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 DOM_TelemetryProbesReporter_H_
#define DOM_TelemetryProbesReporter_H_

#include "MediaInfo.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"

namespace mozilla {
class FrameStatistics;

class TelemetryProbesReporterOwner {
 public:
  virtual Maybe<nsAutoString> GetKeySystem() const = 0;
  virtual MediaInfo GetMediaInfo() const = 0;
  virtual FrameStatistics* GetFrameStatistics() const = 0;
  virtual void DispatchAsyncTestingEvent(const nsAString& aName) = 0;
};

/**
 * This class is used for collecting and reporting telemetry probes for
 * its owner which should inherit from TelemetryProbesReporterOwner. We use it
 * for HTMLMediaElement, and each element has one corresponding reporter.
 */
class TelemetryProbesReporter final {
 public:
  explicit TelemetryProbesReporter(TelemetryProbesReporterOwner* aOwner);
  ~TelemetryProbesReporter() = default;

  enum class Visibility {
    eVisible,
    eInvisible,
  };

  void OnPlay(Visibility aVisibility);
  void OnPause(Visibility aVisibility);
  void OnVisibilityChanged(Visibility aVisibility);
  void OnDecodeSuspended();
  void OnDecodeResumed();
  void OnShutdown();

  double GetTotalPlayTimeInSeconds() const;
  double GetInvisibleVideoPlayTimeInSeconds() const;
  double GetVideoDecodeSuspendedTimeInSeconds() const;

 private:
  void StartInvisibleVideoTimeAcculator();
  void PauseInvisibleVideoTimeAcculator();
  bool HasOwnerHadValidVideo() const;
  void AssertOnMainThreadAndNotShutdown() const;

  void ReportTelemetry();
  void ReportResultForVideo();
  void ReportResultForVideoFrameStatistics(double aTotalPlayTimeS,
                                           const nsCString& key);

  // Helper class to measure times for playback telemetry stats
  class TimeDurationAccumulator {
   public:
    TimeDurationAccumulator() = default;
    void Start() {
      if (IsStarted()) {
        return;
      }
      mStartTime = TimeStamp::Now();
    }
    void Pause() {
      if (!IsStarted()) {
        return;
      }
      mSum = (TimeStamp::Now() - mStartTime);
      mStartTime = TimeStamp();
    }
    bool IsStarted() const { return !mStartTime.IsNull(); }

    double GetAndClearTotal() {
      MOZ_ASSERT(!IsStarted(), "only call this when accumulator is paused");
      double total = mSum.ToSeconds();
      mStartTime = TimeStamp();
      mSum = TimeDuration();
      return total;
    }

    double PeekTotal() const {
      if (!IsStarted()) {
        return mSum.ToSeconds();
      }
      return (TimeStamp::Now() - mStartTime).ToSeconds();
    }

   private:
    TimeStamp mStartTime;
    TimeDuration mSum;
  };

  // The owner is HTMLMediaElement that is guaranteed being always alive during
  // our whole life cycle.
  TelemetryProbesReporterOwner* mOwner;

  // Total time an element has spent on playing.
  TimeDurationAccumulator mTotalPlayTime;

  // Total time a VIDEO element has spent playing while the corresponding media
  // element is invisible.
  TimeDurationAccumulator mInvisibleVideoPlayTime;

  // Total time a VIDEO has spent in video-decode-suspend mode.
  TimeDurationAccumulator mVideoDecodeSuspendedTime;

  Visibility mMediaElementVisibility = Visibility::eInvisible;
};

}  // namespace mozilla

#endif  // DOM_TelemetryProbesReporter_H_