File: ChannelMediaDecoder.h

package info (click to toggle)
firefox 148.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,719,656 kB
  • sloc: cpp: 7,618,171; javascript: 6,701,506; ansic: 3,781,787; python: 1,418,364; xml: 638,647; asm: 438,962; java: 186,285; sh: 62,885; makefile: 19,010; objc: 13,092; perl: 12,763; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (186 lines) | stat: -rw-r--r-- 7,021 bytes parent folder | download | duplicates (3)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* -*- 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/. */

#ifndef ChannelMediaDecoder_h_
#define ChannelMediaDecoder_h_

#include "MediaChannelStatistics.h"
#include "MediaDecoder.h"
#include "MediaResourceCallback.h"

class nsIChannel;
class nsIStreamListener;

namespace mozilla {

class BaseMediaResource;

DDLoggedTypeDeclNameAndBase(ChannelMediaDecoder, MediaDecoder);

class ChannelMediaDecoder
    : public MediaDecoder,
      public DecoderDoctorLifeLogger<ChannelMediaDecoder> {
  // Used to register with MediaResource to receive notifications which will
  // be forwarded to MediaDecoder.
  class ResourceCallback : public MediaResourceCallback {
    // Throttle calls to MediaDecoder::NotifyDataArrived()
    // to be at most once per 500ms.
    static const uint32_t sDelay = 500;

   public:
    explicit ResourceCallback(AbstractThread* aMainThread);
    // Start to receive notifications from ResourceCallback.
    void Connect(ChannelMediaDecoder* aDecoder);
    // Called upon shutdown to stop receiving notifications.
    void Disconnect();

   private:
    ~ResourceCallback();

    /* MediaResourceCallback functions */
    AbstractThread* AbstractMainThread() const override;
    MediaDecoderOwner* GetMediaOwner() const override;
    void NotifyNetworkError(const MediaResult& aError) override;
    void NotifyDataArrived() override;
    void NotifyDataEnded(nsresult aStatus) override;
    void NotifyPrincipalChanged() override;
    void NotifySuspendedStatusChanged(bool aSuspendedByCache) override;

    static void TimerCallback(nsITimer* aTimer, void* aClosure);

    // The decoder to send notifications. Main-thread only.
    ChannelMediaDecoder* mDecoder = nullptr;
    nsCOMPtr<nsITimer> mTimer;
    bool mTimerArmed = false;
    const RefPtr<AbstractThread> mAbstractMainThread;
  };

 protected:
  void ShutdownInternal() override;
  void OnPlaybackEvent(const MediaPlaybackEvent& aEvent) override;
  void DurationChanged() override;
  void MetadataLoaded(UniquePtr<MediaInfo> aInfo, UniquePtr<MetadataTags> aTags,
                      MediaDecoderEventVisibility aEventVisibility) override;
  void NotifyPrincipalChanged() override;

  RefPtr<ResourceCallback> mResourceCallback;
  RefPtr<BaseMediaResource> mResource;

  explicit ChannelMediaDecoder(MediaDecoderInit& aInit);

  void GetDebugInfo(dom::MediaDecoderDebugInfo& aInfo);

 public:
  // Create a decoder for the given aType. Returns null if we were unable
  // to create the decoder, for example because the requested MIME type in
  // the init struct was unsupported.
  static already_AddRefed<ChannelMediaDecoder> Create(
      MediaDecoderInit& aInit, DecoderDoctorDiagnostics* aDiagnostics);

  void Shutdown() override;

  bool CanClone();

  // Create a new decoder of the same type as this one.
  already_AddRefed<ChannelMediaDecoder> Clone(MediaDecoderInit& aInit);

  nsresult Load(nsIChannel* aChannel, bool aIsPrivateBrowsing,
                nsIStreamListener** aStreamListener);

  void AddSizeOfResources(ResourceSizes* aSizes) override;
  already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
  bool HadCrossOriginRedirects() override;
  bool IsTransportSeekable() override;
  void SetLoadInBackground(bool aLoadInBackground) override;
  void Suspend() override;
  void Resume() override;

 private:
  // A snapshot of the media playback and download state used to determine if
  // playback can proceed without interruption.
  struct MediaStatistics {
    // Estimate of the current playback rate (bytes/second).
    double mPlaybackByteRate;
    // Estimate of the current download rate (bytes/second). This
    // ignores time that the channel was paused by Gecko.
    double mDownloadByteRate;
    // Total length of media stream in bytes; -1 if not known
    int64_t mTotalBytes;
    // Current position of the download, in bytes. This is the offset of
    // the first uncached byte after the decoder position.
    int64_t mDownloadBytePosition;
    // Current position of playback, in bytes
    int64_t mPlaybackByteOffset;
    // If false, then mDownloadRate cannot be considered a reliable
    // estimate (probably because the download has only been running
    // a short time).
    bool mDownloadByteRateReliable;
    // If false, then mPlaybackRate cannot be considered a reliable
    // estimate (probably because playback has only been running
    // a short time).
    bool mPlaybackByteRateReliable;

    bool CanPlayThrough() const;
    nsCString ToString() const;
  };

  void DownloadProgressed();

  // Create a new state machine to run this decoder.
  MediaDecoderStateMachineBase* CreateStateMachine(
      bool aDisableExternalEngine) override;

  nsresult Load(BaseMediaResource* aOriginal);

  // Called by MediaResource when the download has ended.
  // Called on the main thread only. aStatus is the result from OnStopRequest.
  void NotifyDownloadEnded(nsresult aStatus);

  // Called by the MediaResource to keep track of the number of bytes read
  // from the resource. Called on the main by an event runner dispatched
  // by the MediaResource read functions.
  void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset);

  bool CanPlayThroughImpl() final;

  struct PlaybackRateInfo {
    uint32_t mRate;  // Estimate of the current playback rate (bytes/second).
    bool mReliable;  // True if mRate is a reliable estimate.
  };

  // Return a PlaybackRateInfo and update the expected byte rate per second for
  // playback in the media resource, which improves cache usage prediction
  // accuracy. This can only be run off the main thread.
  static PlaybackRateInfo UpdateResourceOfPlaybackByteRate(
      const MediaChannelStatistics& aStats, BaseMediaResource* aResource,
      const media::TimeUnit& aDuration);

  bool ShouldThrottleDownload(const MediaStatistics& aStats);

  // Data needed to estimate playback data rate. The timeline used for
  // this estimate is "decode time" (where the "current time" is the
  // time of the last decoded video frame).
  MediaChannelStatistics mPlaybackStatistics;

  // Current playback byte offset in the stream. This is (approximately)
  // where we're up to playing back the stream. This is not adjusted immediately
  // after seek happens, but it will be updated when playback starts or stops.
  int64_t mPlaybackByteOffset = 0;

  bool mCanPlayThrough = false;

  // True if we've been notified that the ChannelMediaResource has
  // a principal.
  bool mInitialChannelPrincipalKnown = false;

  // Set in Shutdown() when we start closing mResource, if mResource is set.
  // Must resolve before we unregister the shutdown blocker.
  RefPtr<GenericPromise> mResourceClosePromise;
};

}  // namespace mozilla

#endif  // ChannelMediaDecoder_h_