Bug 1393399 P4 - implement GPUProcessCrashTelemetryLogger helper class;
GPUProcessCrashTelemetryLogger is used to report telemetry of the time used to recover a decoder from GPU crash.
It uses MediaDecoderOwnerID to identify which video we're dealing with.
It uses MediaDataDecoderID to make sure that the old MediaDataDecoder has been deleted and we're already recovered.
It reports two recovery times, one is calculated from GPU crashed (that is, the time when VideoDecoderChild::ActorDestory() is called) and the other is calculated from the MFR is notified with NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER error.
MozReview-Commit-ID: 82BRc2Vs3cw
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -21,16 +21,17 @@
#include "mozilla/SharedThreadPool.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
#include "nsPrintfCString.h"
#include <algorithm>
+#include <map>
#include <queue>
using namespace mozilla::media;
using mozilla::layers::Image;
using mozilla::layers::LayerManager;
using mozilla::layers::LayersBackend;
@@ -39,16 +40,97 @@ mozilla::LazyLogModule gMediaDemuxerLog(
#define LOG(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Debug, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define LOGV(arg, ...) MOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, ("MediaFormatReader(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
#define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
namespace mozilla {
+
+typedef void* MediaDataDecoderID;
+
+/**
+ * This helper class is used to report telemetry of the time used to recover a
+ * decoder from GPU crash.
+ * It uses MediaDecoderOwnerID to identify which video we're dealing with.
+ * It uses MediaDataDecoderID to make sure that the old MediaDataDecoder has
+ * been deleted and we're already recovered.
+ * It reports two recovery times, one is calculated from GPU crashed (that is,
+ * the time when VideoDecoderChild::ActorDestory() is called) and the other is
+ * calculated from the MFR is notified with NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER
+ * error.
+ */
+class GPUProcessCrashTelemetryLogger
+{
+ struct GPUCrashData
+ {
+ GPUCrashData(MediaDataDecoderID aMediaDataDecoderID,
+ mozilla::TimeStamp aGPUCrashTime,
+ mozilla::TimeStamp aErrorNotifiedTime)
+ : mMediaDataDecoderID(aMediaDataDecoderID)
+ , mGPUCrashTime(aGPUCrashTime)
+ , mErrorNotifiedTime(aErrorNotifiedTime)
+ {
+ MOZ_ASSERT(mMediaDataDecoderID);
+ MOZ_ASSERT(!mGPUCrashTime.IsNull());
+ MOZ_ASSERT(!mErrorNotifiedTime.IsNull());
+ }
+
+ MediaDataDecoderID mMediaDataDecoderID;
+ mozilla::TimeStamp mGPUCrashTime;
+ mozilla::TimeStamp mErrorNotifiedTime;
+ };
+
+public:
+ static void
+ RecordGPUCrashData(MediaDecoderOwnerID aMediaDecoderOwnerID,
+ MediaDataDecoderID aMediaDataDecoderID,
+ const TimeStamp& aGPUCrashTime,
+ const TimeStamp& aErrorNotifiedTime)
+ {
+ MOZ_ASSERT(aMediaDecoderOwnerID);
+ MOZ_ASSERT(aMediaDataDecoderID);
+ MOZ_ASSERT(!aGPUCrashTime.IsNull());
+ MOZ_ASSERT(!aErrorNotifiedTime.IsNull());
+ auto it = sGPUCrashDataMap.find(aMediaDecoderOwnerID);
+ if (it == sGPUCrashDataMap.end()) {
+ sGPUCrashDataMap.insert(std::make_pair(aMediaDecoderOwnerID,
+ GPUCrashData(aMediaDataDecoderID,
+ aGPUCrashTime,
+ aErrorNotifiedTime)));
+ }
+ }
+
+ static void
+ ReportTelemetry(MediaDecoderOwnerID aMediaDecoderOwnerID,
+ MediaDataDecoderID aMediaDataDecoderID)
+ {
+ MOZ_ASSERT(aMediaDecoderOwnerID);
+ MOZ_ASSERT(aMediaDataDecoderID);
+ auto it = sGPUCrashDataMap.find(aMediaDecoderOwnerID);
+ if (it != sGPUCrashDataMap.end() &&
+ it->second.mMediaDataDecoderID != aMediaDataDecoderID) {
+ Telemetry::AccumulateTimeDelta(
+ Telemetry::VIDEO_HW_DECODER_CRASH_RECOVERY_TIME_SINCE_GPU_CRASHED_MS,
+ it->second.mGPUCrashTime);
+ Telemetry::AccumulateTimeDelta(
+ Telemetry::VIDEO_HW_DECODER_CRASH_RECOVERY_TIME_SINCE_MFR_NOTIFIED_MS,
+ it->second.mErrorNotifiedTime);
+ sGPUCrashDataMap.erase(aMediaDecoderOwnerID);
+ }
+ }
+
+private:
+ static std::map<MediaDecoderOwnerID, GPUCrashData> sGPUCrashDataMap;
+};
+
+std::map<MediaDecoderOwnerID, GPUProcessCrashTelemetryLogger::GPUCrashData>
+GPUProcessCrashTelemetryLogger::sGPUCrashDataMap;
+
/**
* This is a singleton which controls the number of decoders that can be
* created concurrently. Before calling PDMFactory::CreateDecoder(), Alloc()
* must be called to get a token object as a permission to create a decoder.
* The token should stay alive until Shutdown() is called on the decoder.
* The destructor of the token will restore the decoder count so it is available
* for next calls of Alloc().
*/