summaryrefslogtreecommitdiffstats
path: root/dom/media/doctor/DecoderDoctorDiagnostics.h
blob: dee63a6f1ad48e64ad16d61e7851f64a26bd2809 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* -*- 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<mozilla::DecoderDoctorDiagnostics>;

 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<Flags>;

  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<unsigned int>(DecoderDoctorDiagnostics::sFlagsCount);
};

}  // namespace mozilla

#endif