summaryrefslogtreecommitdiffstats
path: root/dom/media/utils/PerformanceRecorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/utils/PerformanceRecorder.cpp')
-rw-r--r--dom/media/utils/PerformanceRecorder.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/dom/media/utils/PerformanceRecorder.cpp b/dom/media/utils/PerformanceRecorder.cpp
new file mode 100644
index 0000000000..d6124e8cf6
--- /dev/null
+++ b/dom/media/utils/PerformanceRecorder.cpp
@@ -0,0 +1,308 @@
+/* -*- 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/. */
+
+#include "PerformanceRecorder.h"
+
+#include "base/process_util.h"
+#include "mozilla/Logging.h"
+#include "mozilla/gfx/Types.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+
+static const char* SourceToStr(TrackingId::Source aSource) {
+ switch (aSource) {
+ case TrackingId::Source::Unimplemented:
+ MOZ_ASSERT_UNREACHABLE("Unimplemented TrackingId Source");
+ return "Unimplemented";
+ case TrackingId::Source::AudioDestinationNode:
+ return "AudioDestinationNode";
+ case TrackingId::Source::Camera:
+ return "CameraCapture";
+ case TrackingId::Source::Canvas:
+ return "CanvasCapture";
+ case TrackingId::Source::ChannelDecoder:
+ return "ChannelDecoder";
+ case TrackingId::Source::HLSDecoder:
+ return "HLSDecoder";
+ case TrackingId::Source::MediaCapabilities:
+ return "MediaCapabilities";
+ case TrackingId::Source::MediaElementDecoder:
+ return "MediaElementDecoderCapture";
+ case TrackingId::Source::MediaElementStream:
+ return "MediaElementStreamCapture";
+ case TrackingId::Source::MSEDecoder:
+ return "MSEDecoder";
+ case TrackingId::Source::RTCRtpReceiver:
+ return "RTCRtpReceiver";
+ case TrackingId::Source::Screen:
+ return "ScreenCapture";
+ case TrackingId::Source::Tab:
+ return "TabCapture";
+ case TrackingId::Source::Window:
+ return "WindowCapture";
+ case TrackingId::Source::LAST:
+ MOZ_ASSERT_UNREACHABLE("Invalid TrackingId Source");
+ return "Invalid";
+ }
+ MOZ_ASSERT_UNREACHABLE("Unexpected TrackingId Source");
+ return "Unexpected";
+}
+
+TrackingId::TrackingId() : mSource(Source::Unimplemented), mUniqueInProcId(0) {}
+
+TrackingId::TrackingId(
+ Source aSource, uint32_t aUniqueInProcId,
+ TrackAcrossProcesses aTrack /* = TrackAcrossProcesses::NO */)
+ : mSource(aSource),
+ mUniqueInProcId(aUniqueInProcId),
+ mProcId(aTrack == TrackAcrossProcesses::Yes
+ ? Some(base::GetCurrentProcId())
+ : Nothing()) {}
+
+nsCString TrackingId::ToString() const {
+ if (mProcId) {
+ return nsPrintfCString("%s-%u-%u", SourceToStr(mSource), *mProcId,
+ mUniqueInProcId);
+ }
+ return nsPrintfCString("%s-%u", SourceToStr(mSource), mUniqueInProcId);
+}
+
+static const char* StageToStr(MediaStage aStage) {
+ switch (aStage) {
+ case MediaStage::RequestData:
+ return "RequestData";
+ case MediaStage::RequestDemux:
+ return "RequestDemux";
+ case MediaStage::CopyDemuxedData:
+ return "CopyDemuxedData";
+ case MediaStage::RequestDecode:
+ return "RequestDecode";
+ case MediaStage::CopyDecodedVideo:
+ return "CopyDecodedVideo";
+ default:
+ return "InvalidStage";
+ }
+}
+
+static void AppendMediaInfoFlagToName(nsCString& aName, MediaInfoFlag aFlag) {
+ if (aFlag & MediaInfoFlag::KeyFrame) {
+ aName.Append("kf,");
+ }
+ // Decoding
+ if (aFlag & MediaInfoFlag::SoftwareDecoding) {
+ aName.Append("sw,");
+ } else if (aFlag & MediaInfoFlag::HardwareDecoding) {
+ aName.Append("hw,");
+ }
+ // Codec type
+ if (aFlag & MediaInfoFlag::VIDEO_AV1) {
+ aName.Append("av1,");
+ } else if (aFlag & MediaInfoFlag::VIDEO_H264) {
+ aName.Append("h264,");
+ } else if (aFlag & MediaInfoFlag::VIDEO_VP8) {
+ aName.Append("vp8,");
+ } else if (aFlag & MediaInfoFlag::VIDEO_VP9) {
+ aName.Append("vp9,");
+ } else if (aFlag & MediaInfoFlag::VIDEO_THEORA) {
+ aName.Append("theora,");
+ }
+}
+
+static void AppendImageFormatToName(nsCString& aName,
+ DecodeStage::ImageFormat aFormat) {
+ aName.Append([&] {
+ switch (aFormat) {
+ case DecodeStage::YUV420P:
+ return "yuv420p,";
+ case DecodeStage::YUV422P:
+ return "yuv422p,";
+ case DecodeStage::YUV444P:
+ return "yuv444p,";
+ case DecodeStage::NV12:
+ return "nv12,";
+ case DecodeStage::YV12:
+ return "yv12,";
+ case DecodeStage::NV21:
+ return "nv21,";
+ case DecodeStage::P010:
+ return "p010,";
+ case DecodeStage::P016:
+ return "p016,";
+ case DecodeStage::RGBA32:
+ return "rgba32,";
+ case DecodeStage::RGB24:
+ return "rgb24,";
+ case DecodeStage::GBRP:
+ return "gbrp,";
+ case DecodeStage::ANDROID_SURFACE:
+ return "android.Surface,";
+ }
+ MOZ_ASSERT_UNREACHABLE("Unhandled DecodeStage::ImageFormat");
+ return "";
+ }());
+}
+
+static void AppendYUVColorSpaceToName(nsCString& aName,
+ gfx::YUVColorSpace aSpace) {
+ aName.Append([&] {
+ switch (aSpace) {
+ case gfx::YUVColorSpace::BT601:
+ return "space=BT.601,";
+ case gfx::YUVColorSpace::BT709:
+ return "space=BT.709,";
+ case gfx::YUVColorSpace::BT2020:
+ return "space=BT.2020,";
+ case gfx::YUVColorSpace::Identity:
+ return "space=Identity,";
+ }
+ MOZ_ASSERT_UNREACHABLE("Unhandled gfx::YUVColorSpace");
+ return "";
+ }());
+}
+
+static void AppendColorRangeToName(nsCString& aName, gfx::ColorRange aRange) {
+ aName.Append([&] {
+ switch (aRange) {
+ case gfx::ColorRange::LIMITED:
+ return "range=Limited,";
+ case gfx::ColorRange::FULL:
+ return "range=Full,";
+ }
+ MOZ_ASSERT_UNREACHABLE("Unhandled gfx::ColorRange");
+ return "";
+ }());
+}
+
+static void AppendColorDepthToName(nsCString& aName, gfx::ColorDepth aDepth) {
+ aName.Append([&] {
+ switch (aDepth) {
+ case gfx::ColorDepth::COLOR_8:
+ return "depth=8,";
+ case gfx::ColorDepth::COLOR_10:
+ return "depth=10,";
+ case gfx::ColorDepth::COLOR_12:
+ return "depth=12,";
+ case gfx::ColorDepth::COLOR_16:
+ return "depth=16,";
+ }
+ MOZ_ASSERT_UNREACHABLE("Unhandled gfx::ColorDepth");
+ return "";
+ }());
+}
+
+/* static */
+const char* FindMediaResolution(int32_t aHeight) {
+ static const struct {
+ const int32_t mH;
+ const nsCString mRes;
+ } sResolutions[] = {{0, "A:0"_ns}, // other followings are for video
+ {240, "V:0<h<=240"_ns},
+ {480, "V:240<h<=480"_ns},
+ {576, "V:480<h<=576"_ns},
+ {720, "V:576<h<=720"_ns},
+ {1080, "V:720<h<=1080"_ns},
+ {1440, "V:1080<h<=1440"_ns},
+ {2160, "V:1440<h<=2160"_ns},
+ {INT_MAX, "V:h>2160"_ns}};
+ const char* resolution = sResolutions[0].mRes.get();
+ for (auto&& res : sResolutions) {
+ if (aHeight <= res.mH) {
+ resolution = res.mRes.get();
+ break;
+ }
+ }
+ return resolution;
+}
+
+/* static */
+bool PerformanceRecorderBase::IsMeasurementEnabled() {
+ return profiler_thread_is_being_profiled_for_markers() ||
+ PerformanceRecorderBase::sEnableMeasurementForTesting;
+}
+
+/* static */
+TimeStamp PerformanceRecorderBase::GetCurrentTimeForMeasurement() {
+ // The system call to get the clock is rather expensive on Windows. As we
+ // only report the measurement report via markers, if the marker isn't enabled
+ // then we won't do any measurement in order to save CPU time.
+ return IsMeasurementEnabled() ? TimeStamp::Now() : TimeStamp();
+}
+
+ProfilerString8View PlaybackStage::Name() const {
+ if (!mName) {
+ mName.emplace(StageToStr(mStage));
+ mName->Append(":");
+ mName->Append(FindMediaResolution(mHeight));
+ mName->Append(":");
+ AppendMediaInfoFlagToName(*mName, mFlag);
+ }
+ return *mName;
+}
+
+ProfilerString8View CaptureStage::Name() const {
+ if (!mName) {
+ auto imageTypeToStr = [](ImageType aType) -> const char* {
+ switch (aType) {
+ case ImageType::I420:
+ return "I420";
+ case ImageType::YUY2:
+ return "YUY2";
+ case ImageType::YV12:
+ return "YV12";
+ case ImageType::UYVY:
+ return "UYVY";
+ case ImageType::NV12:
+ return "NV12";
+ case ImageType::NV21:
+ return "NV21";
+ case ImageType::MJPEG:
+ return "MJPEG";
+ case ImageType::Unknown:
+ return "(unknown image type)";
+ default:
+ return "(unimplemented image type)";
+ };
+ };
+ mName = Some(nsPrintfCString(
+ "CaptureVideoFrame %s %dx%d %s %s", mSource.Data(), mWidth, mHeight,
+ imageTypeToStr(mImageType), mTrackingId.ToString().get()));
+ }
+ return *mName;
+}
+
+ProfilerString8View CopyVideoStage::Name() const {
+ if (!mName) {
+ mName =
+ Some(nsPrintfCString("CopyVideoFrame %s %dx%d %s", mSource.Data(),
+ mWidth, mHeight, mTrackingId.ToString().get()));
+ }
+ return *mName;
+}
+
+ProfilerString8View DecodeStage::Name() const {
+ if (!mName) {
+ nsCString extras;
+ AppendMediaInfoFlagToName(extras, mFlag);
+ mImageFormat.apply(
+ [&](ImageFormat aFormat) { AppendImageFormatToName(extras, aFormat); });
+ mColorDepth.apply([&](gfx::ColorDepth aDepth) {
+ AppendColorDepthToName(extras, aDepth);
+ });
+ mColorRange.apply([&](gfx::ColorRange aRange) {
+ AppendColorRangeToName(extras, aRange);
+ });
+ mYUVColorSpace.apply([&](gfx::YUVColorSpace aColorSpace) {
+ AppendYUVColorSpaceToName(extras, aColorSpace);
+ });
+ mName = Some(nsPrintfCString("DecodeFrame %s %dx%d %s %s", mSource.Data(),
+ mWidth.valueOr(-1), mHeight.valueOr(-1),
+ extras.get(), mTrackingId.ToString().get()));
+ }
+ return *mName;
+}
+
+} // namespace mozilla