/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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/. */ #ifndef DecoderDoctorDiagnostics_h_ #define DecoderDoctorDiagnostics_h_ #include "MediaResult.h" #include "mozilla/DefineEnum.h" #include "mozilla/EnumSet.h" #include "mozilla/EnumTypeTraits.h" #include "mozilla/dom/DecoderDoctorNotificationBinding.h" #include "nsString.h" namespace mozilla { namespace dom { class Document; } struct DecoderDoctorEvent { enum Domain { eAudioSinkStartup, } mDomain; nsresult mResult; }; // DecoderDoctorDiagnostics class, used to gather data from PDMs/DecoderTraits, // and then notify the user about issues preventing (or worsening) playback. // // The expected usage is: // 1. Instantiate a DecoderDoctorDiagnostics in a function (close to the point // where a webpage is trying to know whether some MIME types can be played, // or trying to play a media file). // 2. Pass a pointer to the DecoderDoctorDiagnostics structure to one of the // CanPlayStatus/IsTypeSupported/(others?). During that call, some PDMs may // add relevant diagnostic information. // 3. Analyze the collected diagnostics, and optionally dispatch an event to the // UX, to notify the user about potential playback issues and how to resolve // them. // // This class' methods must be called from the main thread. class DecoderDoctorDiagnostics { friend struct IPC::ParamTraits; public: // Store the diagnostic information collected so far on a document for a // given format. All diagnostics for a document will be analyzed together // within a short timeframe. // Should only be called once. void StoreFormatDiagnostics(dom::Document* aDocument, const nsAString& aFormat, bool aCanPlay, const char* aCallSite); void StoreMediaKeySystemAccess(dom::Document* aDocument, const nsAString& aKeySystem, bool aIsSupported, const char* aCallSite); void StoreEvent(dom::Document* aDocument, const DecoderDoctorEvent& aEvent, const char* aCallSite); void StoreDecodeError(dom::Document* aDocument, const MediaResult& aError, const nsString& aMediaSrc, const char* aCallSite); void StoreDecodeWarning(dom::Document* aDocument, const MediaResult& aWarning, const nsString& aMediaSrc, const char* aCallSite); enum DiagnosticsType { eUnsaved, eFormatSupportCheck, eMediaKeySystemAccessRequest, eEvent, eDecodeError, eDecodeWarning }; DiagnosticsType Type() const { return mDiagnosticsType; } // Description string, for logging purposes; only call on stored diags. nsCString GetDescription() const; // Methods to record diagnostic information: MOZ_DEFINE_ENUM_CLASS_AT_CLASS_SCOPE( Flags, (CanPlay, WMFFailedToLoad, FFmpegNotFound, LibAVCodecUnsupported, GMPPDMFailedToStartup, VideoNotSupported, AudioNotSupported)); using FlagsSet = mozilla::EnumSet; const nsAString& Format() const { return mFormat; } bool CanPlay() const { return mFlags.contains(Flags::CanPlay); } void SetFailureFlags(const FlagsSet& aFlags) { mFlags = aFlags; } void SetWMFFailedToLoad() { mFlags += Flags::WMFFailedToLoad; } bool DidWMFFailToLoad() const { return mFlags.contains(Flags::WMFFailedToLoad); } void SetFFmpegNotFound() { mFlags += Flags::FFmpegNotFound; } bool DidFFmpegNotFound() const { return mFlags.contains(Flags::FFmpegNotFound); } void SetLibAVCodecUnsupported() { mFlags += Flags::LibAVCodecUnsupported; } bool IsLibAVCodecUnsupported() const { return mFlags.contains(Flags::LibAVCodecUnsupported); } void SetGMPPDMFailedToStartup() { mFlags += Flags::GMPPDMFailedToStartup; } bool DidGMPPDMFailToStartup() const { return mFlags.contains(Flags::GMPPDMFailedToStartup); } void SetVideoNotSupported() { mFlags += Flags::VideoNotSupported; } void SetAudioNotSupported() { mFlags += Flags::AudioNotSupported; } void SetGMP(const nsACString& aGMP) { mGMP = aGMP; } const nsACString& GMP() const { return mGMP; } const nsAString& KeySystem() const { return mKeySystem; } bool IsKeySystemSupported() const { return mIsKeySystemSupported; } enum KeySystemIssue { eUnset, eWidevineWithNoWMF }; void SetKeySystemIssue(KeySystemIssue aKeySystemIssue) { mKeySystemIssue = aKeySystemIssue; } KeySystemIssue GetKeySystemIssue() const { return mKeySystemIssue; } DecoderDoctorEvent event() const { return mEvent; } const MediaResult& DecodeIssue() const { return mDecodeIssue; } const nsString& DecodeIssueMediaSrc() const { return mDecodeIssueMediaSrc; } // This method is only used for testing. void SetDecoderDoctorReportType(const dom::DecoderDoctorReportType& aType); private: // Currently-known type of diagnostics. Set from one of the 'Store...' // methods. This helps ensure diagnostics are only stored once, and makes it // easy to know what information they contain. DiagnosticsType mDiagnosticsType = eUnsaved; nsString mFormat; FlagsSet mFlags; nsCString mGMP; nsString mKeySystem; bool mIsKeySystemSupported = false; KeySystemIssue mKeySystemIssue = eUnset; DecoderDoctorEvent mEvent; MediaResult mDecodeIssue = NS_OK; nsString mDecodeIssueMediaSrc; }; // Used for IPDL serialization. // The 'value' have to be the biggest enum from DecoderDoctorDiagnostics::Flags. template <> struct MaxEnumValue<::mozilla::DecoderDoctorDiagnostics::Flags> { static constexpr unsigned int value = static_cast(DecoderDoctorDiagnostics::sFlagsCount); }; } // namespace mozilla #endif