1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef mozilla_PerformanceRecorder_h
8 #define mozilla_PerformanceRecorder_h
9
10 #include "mozilla/Attributes.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/TimeStamp.h"
13 #include "mozilla/TypedEnumBits.h"
14 #include "nsStringFwd.h"
15
16 namespace mozilla {
17
18 enum class MediaInfoFlag : uint16_t {
19 None = (0 << 0),
20 NonKeyFrame = (1 << 0),
21 KeyFrame = (1 << 1),
22 SoftwareDecoding = (1 << 2),
23 HardwareDecoding = (1 << 3),
24 VIDEO_AV1 = (1 << 4),
25 VIDEO_H264 = (1 << 5),
26 VIDEO_VP8 = (1 << 6),
27 VIDEO_VP9 = (1 << 7),
28 };
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MediaInfoFlag)29 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MediaInfoFlag)
30
31 /**
32 * This class is used to record the passed time on the different stages in the
33 * media playback pipeline. It needs to call `Start()` and `End()` explicitly
34 * in order to record the passed time between these two calls.
35 */
36 class PerformanceRecorder {
37 public:
38 /**
39 * This represents the different stages that a media data will go through
40 * within the playback journey.
41 *
42 * |---| |---| |------|
43 * Copy Demuxed Copy Demuxed Copy Decoded
44 * Data Data Video
45 * |------------- | |-----------------------------------|
46 * Request Demux Request Decode
47 * |-----------------------------------------------------------|
48 * Request Data
49 *
50 * RequestData : Record the time where MediaDecoderStateMachine(MDSM) starts
51 * asking for a decoded data to MDSM receives a decoded data.
52 *
53 * RequestDemux : Record the time where MediaFormatReader(MFR) starts asking
54 * a demuxed sample to MFR received a demuxed sample. This stage is a sub-
55 * stage of RequestData.
56 *
57 * CopyDemuxedData : On some situations, we will need to copy the demuxed
58 * data, which is still not decoded yet so its size is still small. This
59 * records the time which we spend on copying data. This stage could happen
60 * multiple times, either being a sub-stage of RequestDemux (in MSE case), or
61 * being a sub-stage of RequestDecode (when sending data via IPC).
62 *
63 * RequestDecode : Record the time where MFR starts asking decoder to return
64 * a decoded data to MFR receives a decoded data. As the decoder might be
65 * remote, this stage might include the time spending on IPC trips. This stage
66 * is a sub-stage of RequestData.
67 *
68 * CopyDecodedVideo : If we can't reuse same decoder texture to the
69 * compositor, then we have to copy video data to to another sharable texture.
70 * This records the time which we spend on copying data. This stage is a sub-
71 * stage of RequestDecode.
72 */
73 enum class Stage : uint8_t {
74 Invalid,
75 RequestData,
76 RequestDemux,
77 CopyDemuxedData,
78 RequestDecode,
79 CopyDecodedVideo,
80 };
81
82 explicit PerformanceRecorder(Stage aStage, int32_t aHeight = 0,
83 MediaInfoFlag aFlag = MediaInfoFlag::None)
84 : mStage(aStage), mHeight(aHeight), mFlag(aFlag) {}
85 ~PerformanceRecorder() = default;
86
87 PerformanceRecorder(PerformanceRecorder&& aRhs) noexcept {
88 mStage = aRhs.mStage;
89 mHeight = aRhs.mHeight;
90 mStartTime = std::move(aRhs.mStartTime);
91 mFlag = aRhs.mFlag;
92 aRhs.mStage = Stage::Invalid;
93 }
94
95 PerformanceRecorder& operator=(PerformanceRecorder&& aRhs) noexcept {
96 MOZ_ASSERT(&aRhs != this, "self-moves are prohibited");
97 mStage = aRhs.mStage;
98 mHeight = aRhs.mHeight;
99 mStartTime = std::move(aRhs.mStartTime);
100 mFlag = aRhs.mFlag;
101 aRhs.mStage = Stage::Invalid;
102 return *this;
103 }
104
105 PerformanceRecorder(const PerformanceRecorder&) = delete;
106 PerformanceRecorder& operator=(const PerformanceRecorder&) = delete;
107
108 void Start();
109
110 // Return the passed time if it has started and still valid. Otherwise,
111 // return 0.
112 float End();
113
114 protected:
115 void Reset();
116
117 static bool IsMeasurementEnabled();
118 static TimeStamp GetCurrentTimeForMeasurement();
119
120 // Return the resolution range for the given height. Eg. V:1080<h<=1440.
121 static const char* FindMediaResolution(int32_t aHeight);
122
123 Stage mStage = Stage::Invalid;
124 int32_t mHeight;
125 MediaInfoFlag mFlag = MediaInfoFlag::None;
126 Maybe<TimeStamp> mStartTime;
127
128 // We would enable the measurement on testing.
129 static inline bool sEnableMeasurementForTesting = false;
130 };
131
132 } // namespace mozilla
133
134 #endif // mozilla_PerformanceRecorder_h
135