Bug 1873394 - part2 : add telemetry probe to record error and crash. r=jolin,chutten

Differential Revision: https://phabricator.services.mozilla.com/D198110
This commit is contained in:
alwu 2024-02-08 18:38:30 +00:00
Родитель 1e0c17c84c
Коммит 55fe15a99b
7 изменённых файлов: 147 добавлений и 19 удалений

Просмотреть файл

@ -15,7 +15,9 @@
#include "mozilla/ProfilerLabels.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/glean/GleanMetrics.h"
#include "nsThreadUtils.h"
#include "VideoUtils.h"
namespace mozilla {
@ -248,6 +250,7 @@ void ExternalEngineStateMachine::OnEngineInitFailure() {
state->mEngineInitRequest.Complete();
state->mInitPromise = nullptr;
// TODO : Should fallback to the normal playback with media engine.
ReportTelemetry(NS_ERROR_DOM_MEDIA_FATAL_ERR);
DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__));
}
@ -276,14 +279,16 @@ void ExternalEngineStateMachine::OnMetadataRead(MetadataHolder&& aMetadata) {
if (!IsFormatSupportedByExternalEngine(*mInfo)) {
// The external engine doesn't support the type, try to notify the decoder
// to use our own state machine again.
// to use our own state machine again. Not a real "error", because it would
// fallback to another state machine.
DecodeError(
MediaResult(NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR));
return;
}
#ifdef MOZ_WMF_MEDIA_ENGINE
// Only support encrypted playback.
// Only support encrypted playback. Not a real "error", because it would
// fallback to another state machine.
if (!mInfo->IsEncrypted() &&
StaticPrefs::media_wmf_media_engine_enabled() == 2) {
LOG("External engine only supports encrypted playback by the pref");
@ -331,6 +336,7 @@ void ExternalEngineStateMachine::OnMetadataNotRead(const MediaResult& aError) {
MOZ_ASSERT(mState.IsReadingMetadata());
LOGE("Decode metadata failed, shutting down decoder");
mState.AsReadingMetadata()->mMetadataRequest.Complete();
ReportTelemetry(aError);
DecodeError(aError);
}
@ -466,6 +472,7 @@ void ExternalEngineStateMachine::OnSeekRejected(
MOZ_ASSERT(NS_FAILED(aReject.mError),
"Cancels should also disconnect mSeekRequest");
state->RejectIfExists(__func__);
ReportTelemetry(aReject.mError);
DecodeError(aReject.mError);
}
@ -838,6 +845,7 @@ void ExternalEngineStateMachine::OnRequestAudio() {
// so here just silently ignore this.
break;
default:
ReportTelemetry(aError);
DecodeError(aError);
}
})
@ -914,6 +922,7 @@ void ExternalEngineStateMachine::OnRequestVideo() {
// so here just silently ignore this.
break;
default:
ReportTelemetry(aError);
DecodeError(aError);
}
})
@ -1100,11 +1109,14 @@ void ExternalEngineStateMachine::NotifyErrorInternal(
if (aError == NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR) {
// The external engine doesn't support the type, try to notify the decoder
// to use our own state machine again.
ReportTelemetry(NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR);
DecodeError(
MediaResult(NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR));
} else if (aError == NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_MF_CDM_ERR) {
ReportTelemetry(NS_ERROR_DOM_MEDIA_REMOTE_DECODER_CRASHED_MF_CDM_ERR);
RecoverFromCDMProcessCrashIfNeeded();
} else {
ReportTelemetry(aError);
DecodeError(aError);
}
}
@ -1190,7 +1202,8 @@ RefPtr<SetCDMPromise> ExternalEngineStateMachine::SetCDMProxy(
}
// TODO : set CDM proxy again if we recreate the media engine after crash.
LOG("SetCDMProxy=%p", aProxy);
mKeySystem = NS_ConvertUTF16toUTF8(aProxy->KeySystem());
LOG("SetCDMProxy=%p (key-system=%s)", aProxy, mKeySystem.get());
MOZ_DIAGNOSTIC_ASSERT(mEngine);
if (!mEngine->SetCDMProxy(aProxy)) {
LOG("Failed to set CDM proxy on the engine");
@ -1216,6 +1229,45 @@ bool ExternalEngineStateMachine::IsCDMProxySupported(CDMProxy* aProxy) {
#endif
}
void ExternalEngineStateMachine::ReportTelemetry(const MediaResult& aError) {
glean::mfcdm::ErrorExtra extraData;
extraData.errorName = Some(aError.ErrorName());
nsAutoCString resolution;
if (mInfo) {
if (mInfo->HasAudio()) {
extraData.audioCodec = Some(mInfo->mAudio.mMimeType);
}
if (mInfo->HasVideo()) {
extraData.videoCodec = Some(mInfo->mVideo.mMimeType);
DetermineResolutionForTelemetry(*mInfo, resolution);
extraData.resolution = Some(resolution);
}
}
if (!mKeySystem.IsEmpty()) {
extraData.keySystem = Some(mKeySystem);
}
glean::mfcdm::error.Record(Some(extraData));
if (MOZ_LOG_TEST(gMediaDecoderLog, LogLevel::Debug)) {
nsPrintfCString logMessage{"MFCDM Error event, error=%s",
aError.ErrorName().get()};
if (mInfo) {
if (mInfo->HasAudio()) {
logMessage.Append(
nsPrintfCString{", audio=%s", mInfo->mAudio.mMimeType.get()});
}
if (mInfo->HasVideo()) {
logMessage.Append(nsPrintfCString{", video=%s, resolution=%s",
mInfo->mVideo.mMimeType.get(),
resolution.get()});
}
}
if (!mKeySystem.IsEmpty()) {
logMessage.Append(nsPrintfCString{", keySystem=%s", mKeySystem.get()});
}
LOG("%s", logMessage.get());
}
}
#undef FMT
#undef LOG
#undef LOGV

Просмотреть файл

@ -291,6 +291,8 @@ class ExternalEngineStateMachine final
void RecoverFromCDMProcessCrashIfNeeded();
void ReportTelemetry(const MediaResult& aError);
UniquePtr<ExternalPlaybackEngine> mEngine;
bool mHasEnoughAudio = false;
@ -304,6 +306,9 @@ class ExternalEngineStateMachine final
// It would be zero for audio-only playback.
gfx::IntSize mVideoDisplay;
// It would be set if playback is encrypted.
nsCString mKeySystem;
};
class ExternalPlaybackEngine {

Просмотреть файл

@ -1225,4 +1225,28 @@ bool IsWaveMimetype(const nsACString& aMimeType) {
aMimeType.EqualsLiteral("audio/wave; codecs=65534");
}
void DetermineResolutionForTelemetry(const MediaInfo& aInfo,
nsCString& aResolutionOut) {
if (aInfo.HasAudio()) {
aResolutionOut.AppendASCII("AV,");
} else {
aResolutionOut.AppendASCII("V,");
}
static const struct {
int32_t mH;
const char* mRes;
} sResolutions[] = {{240, "0<h<=240"}, {480, "240<h<=480"},
{576, "480<h<=576"}, {720, "576<h<=720"},
{1080, "720<h<=1080"}, {2160, "1080<h<=2160"}};
const char* resolution = "h>2160";
int32_t height = aInfo.mVideo.mDisplay.height;
for (const auto& res : sResolutions) {
if (height <= res.mH) {
resolution = res.mRes;
break;
}
}
aResolutionOut.AppendASCII(resolution);
}
} // end namespace mozilla

Просмотреть файл

@ -578,6 +578,9 @@ inline gfx::YUVColorSpace DefaultColorSpace(const gfx::IntSize& aSize) {
bool IsWaveMimetype(const nsACString& aMimeType);
void DetermineResolutionForTelemetry(const MediaInfo& aInfo,
nsCString& aResolutionOut);
} // end namespace mozilla
#endif

Просмотреть файл

@ -48,3 +48,41 @@ mfcdm:
type: quantity
expires: 130
telemetry_mirror: Mfcdm_EmePlayback_Gecko
error:
type: event
description:
Record the error or crash happened while using the media engine playback.
The value of this event is the name of error. This probe covers both EME
and non-EME playback.
metadata:
tags:
- 'Core :: Audio/Video: Playback'
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1873394
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1873394#c7
data_sensitivity:
- technical
notification_emails:
- media-alerts@mozilla.com
extra_keys:
error_name:
description: The name of the error
type: string
current_state:
description: The state of the external state machine was being used when the error or crash happened
type: string
audio_codec:
description: The audio codec was being used when the error or crash happened
type: string
video_codec:
description: The video codec was being used when the error or crash happened
type: string
resolution:
description: The video resolution was being used when the error or crash happened
type: string
key_system:
description: The key system was being used when the error or crash happened
type: string
expires: 130
telemetry_mirror: Mfcdm_Error_Gecko

Просмотреть файл

@ -436,22 +436,8 @@ void TelemetryProbesReporter::ReportResultForVideo() {
// Keyed by audio+video or video alone, and by a resolution range.
const MediaInfo& info = mOwner->GetMediaInfo();
nsCString key(info.HasAudio() ? "AV," : "V,");
static const struct {
int32_t mH;
const char* mRes;
} sResolutions[] = {{240, "0<h<=240"}, {480, "240<h<=480"},
{576, "480<h<=576"}, {720, "576<h<=720"},
{1080, "720<h<=1080"}, {2160, "1080<h<=2160"}};
const char* resolution = "h>2160";
int32_t height = info.mVideo.mDisplay.height;
for (const auto& res : sResolutions) {
if (height <= res.mH) {
resolution = res.mRes;
break;
}
}
key.AppendASCII(resolution);
nsCString key;
DetermineResolutionForTelemetry(info, key);
auto visiblePlayTimeS = totalVideoPlayTimeS - invisiblePlayTimeS;
LOG("VIDEO_VISIBLE_PLAY_TIME = %f, keys: '%s' and 'All'", visiblePlayTimeS,

Просмотреть файл

@ -3506,6 +3506,26 @@ mfcdm:
played_time: The amount of time the EME content has been played (in seconds)
rendered_frames: The amount of video frames has been rendered
dropped_frames: The amount of video frames don't get rendered but dropped
error:
objects: ["gecko"]
bug_numbers: [1873394]
description:
Record the error or crash happened while using the media engine playback.
The value of this event is the name of error.
products:
- firefox
record_in_processes: ["all"]
release_channel_collection: opt-out
expiry_version: "130"
notification_emails:
- media-alerts@mozilla.com
extra_keys:
error_name: The name of the error
current_state: The state of the external state machine was being used when the error or crash happened
video_codec: The video codec was being used when the error or crash happened
audio_codec: The audio codec was being used when the error or crash happened
resolution: The video resolution was being used when the error or crash happened
key_system: The key system was being used when the error or crash happened
installation:
first_seen: