PerformanceRecorder.cpp (7561B)
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 #include "PerformanceRecorder.h" 8 9 #include "base/process_util.h" 10 #include "mozilla/Logging.h" 11 #include "mozilla/gfx/Types.h" 12 #include "nsPrintfCString.h" 13 14 namespace mozilla { 15 16 TrackingId::TrackingId() : mSource(Source::Unimplemented), mUniqueInProcId(0) {} 17 18 TrackingId::TrackingId( 19 Source aSource, uint32_t aUniqueInProcId, 20 TrackAcrossProcesses aTrack /* = TrackAcrossProcesses::NO */) 21 : mSource(aSource), 22 mUniqueInProcId(aUniqueInProcId), 23 mProcId(aTrack == TrackAcrossProcesses::Yes 24 ? Some(base::GetCurrentProcId()) 25 : Nothing()) {} 26 27 nsCString TrackingId::ToString() const { 28 if (mProcId) { 29 return nsPrintfCString("%s-%u-%u", EnumValueToString(mSource), *mProcId, 30 mUniqueInProcId); 31 } 32 return nsPrintfCString("%s-%u", EnumValueToString(mSource), mUniqueInProcId); 33 } 34 35 static void AppendMediaInfoFlagToName(nsCString& aName, MediaInfoFlag aFlag) { 36 if (aFlag & MediaInfoFlag::KeyFrame) { 37 aName.Append("kf,"); 38 } 39 // Decoding 40 if (aFlag & MediaInfoFlag::SoftwareDecoding) { 41 aName.Append("sw,"); 42 } else if (aFlag & MediaInfoFlag::HardwareDecoding) { 43 aName.Append("hw,"); 44 } 45 // Codec type 46 if (aFlag & MediaInfoFlag::VIDEO_AV1) { 47 aName.Append("av1,"); 48 } else if (aFlag & MediaInfoFlag::VIDEO_H264) { 49 aName.Append("h264,"); 50 } else if (aFlag & MediaInfoFlag::VIDEO_VP8) { 51 aName.Append("vp8,"); 52 } else if (aFlag & MediaInfoFlag::VIDEO_VP9) { 53 aName.Append("vp9,"); 54 } else if (aFlag & MediaInfoFlag::VIDEO_HEVC) { 55 aName.Append("hevc,"); 56 } 57 } 58 59 static void AppendImageFormatToName(nsCString& aName, 60 DecodeStage::ImageFormat aFormat) { 61 aName.AppendPrintf("%s,", DecodeStage::EnumValueToString(aFormat)); 62 } 63 64 static void AppendYUVColorSpaceToName(nsCString& aName, 65 gfx::YUVColorSpace aSpace) { 66 aName.Append([&] { 67 switch (aSpace) { 68 case gfx::YUVColorSpace::BT601: 69 return "space=BT.601,"; 70 case gfx::YUVColorSpace::BT709: 71 return "space=BT.709,"; 72 case gfx::YUVColorSpace::BT2020: 73 return "space=BT.2020,"; 74 case gfx::YUVColorSpace::Identity: 75 return "space=Identity,"; 76 } 77 MOZ_ASSERT_UNREACHABLE("Unhandled gfx::YUVColorSpace"); 78 return ""; 79 }()); 80 } 81 82 static void AppendColorRangeToName(nsCString& aName, gfx::ColorRange aRange) { 83 aName.Append([&] { 84 switch (aRange) { 85 case gfx::ColorRange::LIMITED: 86 return "range=Limited,"; 87 case gfx::ColorRange::FULL: 88 return "range=Full,"; 89 } 90 MOZ_ASSERT_UNREACHABLE("Unhandled gfx::ColorRange"); 91 return ""; 92 }()); 93 } 94 95 static void AppendColorDepthToName(nsCString& aName, gfx::ColorDepth aDepth) { 96 aName.Append([&] { 97 switch (aDepth) { 98 case gfx::ColorDepth::COLOR_8: 99 return "depth=8,"; 100 case gfx::ColorDepth::COLOR_10: 101 return "depth=10,"; 102 case gfx::ColorDepth::COLOR_12: 103 return "depth=12,"; 104 case gfx::ColorDepth::COLOR_16: 105 return "depth=16,"; 106 } 107 MOZ_ASSERT_UNREACHABLE("Unhandled gfx::ColorDepth"); 108 return ""; 109 }()); 110 } 111 112 /* static */ 113 const char* FindMediaResolution(int32_t aHeight) { 114 static const struct { 115 const int32_t mH; 116 const nsCString mRes; 117 } sResolutions[] = {{0, "A:0"_ns}, // other followings are for video 118 {240, "V:0<h<=240"_ns}, 119 {480, "V:240<h<=480"_ns}, 120 {576, "V:480<h<=576"_ns}, 121 {720, "V:576<h<=720"_ns}, 122 {1080, "V:720<h<=1080"_ns}, 123 {1440, "V:1080<h<=1440"_ns}, 124 {2160, "V:1440<h<=2160"_ns}, 125 {INT_MAX, "V:h>2160"_ns}}; 126 const char* resolution = sResolutions[0].mRes.get(); 127 for (auto&& res : sResolutions) { 128 if (aHeight <= res.mH) { 129 resolution = res.mRes.get(); 130 break; 131 } 132 } 133 return resolution; 134 } 135 136 /* static */ 137 bool PerformanceRecorderBase::IsMeasurementEnabled() { 138 return profiler_thread_is_being_profiled_for_markers() || 139 PerformanceRecorderBase::sEnableMeasurementForTesting; 140 } 141 142 /* static */ 143 TimeStamp PerformanceRecorderBase::GetCurrentTimeForMeasurement() { 144 // The system call to get the clock is rather expensive on Windows. As we 145 // only report the measurement report via markers, if the marker isn't enabled 146 // then we won't do any measurement in order to save CPU time. 147 return IsMeasurementEnabled() ? TimeStamp::Now() : TimeStamp(); 148 } 149 150 ProfilerString8View PlaybackStage::Name() const { 151 if (!mName) { 152 mName.emplace(EnumValueToString(mStage)); 153 mName->Append(":"); 154 mName->Append(FindMediaResolution(mHeight)); 155 mName->Append(":"); 156 AppendMediaInfoFlagToName(*mName, mFlag); 157 } 158 return *mName; 159 } 160 161 void PlaybackStage::AddMarker(MarkerOptions&& aOption) { 162 if (mStartAndEndTimeUs) { 163 auto& pair = *mStartAndEndTimeUs; 164 profiler_add_marker(Name(), Category(), 165 std::forward<MarkerOptions&&>(aOption), 166 geckoprofiler::markers::MediaSampleMarker{}, pair.first, 167 pair.second, 1 /* queue length */); 168 } else { 169 profiler_add_marker(Name(), Category(), 170 std::forward<MarkerOptions&&>(aOption)); 171 } 172 } 173 174 void PlaybackStage::AddFlag(MediaInfoFlag aFlag) { mFlag |= aFlag; } 175 176 ProfilerString8View CaptureStage::Name() const { 177 if (!mName) { 178 mName = Some(nsPrintfCString( 179 "CaptureVideoFrame %s %dx%d %s %s", mSource.Data(), mWidth, mHeight, 180 EnumValueToString(mImageType), mTrackingId.ToString().get())); 181 } 182 return *mName; 183 } 184 185 ProfilerString8View CopyVideoStage::Name() const { 186 if (!mName) { 187 mName = 188 Some(nsPrintfCString("CopyVideoFrame %s %dx%d %s", mSource.Data(), 189 mWidth, mHeight, mTrackingId.ToString().get())); 190 } 191 return *mName; 192 } 193 194 ProfilerString8View DecodeStage::Name() const { 195 if (!mName) { 196 nsCString extras; 197 AppendMediaInfoFlagToName(extras, mFlag); 198 mImageFormat.apply( 199 [&](ImageFormat aFormat) { AppendImageFormatToName(extras, aFormat); }); 200 mColorDepth.apply([&](gfx::ColorDepth aDepth) { 201 AppendColorDepthToName(extras, aDepth); 202 }); 203 mColorRange.apply([&](gfx::ColorRange aRange) { 204 AppendColorRangeToName(extras, aRange); 205 }); 206 mYUVColorSpace.apply([&](gfx::YUVColorSpace aColorSpace) { 207 AppendYUVColorSpaceToName(extras, aColorSpace); 208 }); 209 mName = Some(nsPrintfCString("DecodeFrame %s %dx%d %s %s", mSource.Data(), 210 mWidth.valueOr(-1), mHeight.valueOr(-1), 211 extras.get(), mTrackingId.ToString().get())); 212 } 213 return *mName; 214 } 215 216 void DecodeStage::AddMarker(MarkerOptions&& aOption) { 217 if (mStartAndEndTimeUs) { 218 auto& pair = *mStartAndEndTimeUs; 219 profiler_add_marker(Name(), Category(), 220 std::forward<MarkerOptions&&>(aOption), 221 geckoprofiler::markers::MediaSampleMarker{}, pair.first, 222 pair.second, 1 /* queue length */); 223 } else { 224 profiler_add_marker(Name(), Category(), 225 std::forward<MarkerOptions&&>(aOption)); 226 } 227 } 228 229 } // namespace mozilla