2017-06-19 07:50:09 +00:00
|
|
|
/* -*- 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 "MediaDecoder.h"
|
2017-06-20 10:10:56 +00:00
|
|
|
#include "MediaResourceCallback.h"
|
2017-10-04 14:30:32 +00:00
|
|
|
#include "MediaChannelStatistics.h"
|
2017-06-19 07:50:09 +00:00
|
|
|
|
2017-06-21 09:30:56 +00:00
|
|
|
class nsIChannel;
|
2017-06-23 06:12:41 +00:00
|
|
|
class nsIStreamListener;
|
2017-06-21 09:30:56 +00:00
|
|
|
|
2017-06-19 07:50:09 +00:00
|
|
|
namespace mozilla {
|
|
|
|
|
2017-08-04 06:52:22 +00:00
|
|
|
class BaseMediaResource;
|
|
|
|
|
Bug 1407810 - Use DDLogger in media stack - r=jwwang
Mostly-mechanical additions:
- Log constructions&destructions, usually by just inheriting from
DecoderDoctorLifeLogger, otherwise with explicit log commands (for internal
classes for which DecoderDoctorTraits can't be specialized),
- Log links between most objects, e.g.: Media element -> decoder -> state
machine -> reader -> demuxer -> resource, etc.
And logging some important properties and events (JS events, duration change,
frames being decoded, etc.)
More will be added later on, from just converting MOZ_LOGs, and as needed.
MozReview-Commit-ID: KgNhHSz35t0
--HG--
extra : rebase_source : dd7206e350e32671adc6f3b9e54ebf777251de2c
2017-10-10 06:55:27 +00:00
|
|
|
DDLoggedTypeDeclNameAndBase(ChannelMediaDecoder, MediaDecoder);
|
|
|
|
|
|
|
|
class ChannelMediaDecoder
|
|
|
|
: public MediaDecoder,
|
|
|
|
public DecoderDoctorLifeLogger<ChannelMediaDecoder> {
|
2017-06-20 10:10:56 +00:00
|
|
|
// 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:
|
Bug 1407810 - Use DDLogger in media stack - r=jwwang
Mostly-mechanical additions:
- Log constructions&destructions, usually by just inheriting from
DecoderDoctorLifeLogger, otherwise with explicit log commands (for internal
classes for which DecoderDoctorTraits can't be specialized),
- Log links between most objects, e.g.: Media element -> decoder -> state
machine -> reader -> demuxer -> resource, etc.
And logging some important properties and events (JS events, duration change,
frames being decoded, etc.)
More will be added later on, from just converting MOZ_LOGs, and as needed.
MozReview-Commit-ID: KgNhHSz35t0
--HG--
extra : rebase_source : dd7206e350e32671adc6f3b9e54ebf777251de2c
2017-10-10 06:55:27 +00:00
|
|
|
~ResourceCallback();
|
|
|
|
|
2017-06-20 10:10:56 +00:00
|
|
|
/* MediaResourceCallback functions */
|
2017-09-06 07:12:34 +00:00
|
|
|
AbstractThread* AbstractMainThread() const override;
|
2017-06-20 10:10:56 +00:00
|
|
|
MediaDecoderOwner* GetMediaOwner() const override;
|
2017-11-17 03:07:30 +00:00
|
|
|
void NotifyNetworkError(const MediaResult& aError) override;
|
2017-06-20 10:10:56 +00:00
|
|
|
void NotifyDataArrived() override;
|
|
|
|
void NotifyDataEnded(nsresult aStatus) override;
|
|
|
|
void NotifyPrincipalChanged() override;
|
2017-08-23 06:32:51 +00:00
|
|
|
void NotifySuspendedStatusChanged(bool aSuspendedByCache) override;
|
2017-06-20 10:10:56 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2017-06-30 02:11:42 +00:00
|
|
|
protected:
|
2017-12-01 02:33:44 +00:00
|
|
|
void OnPlaybackEvent(MediaPlaybackEvent&& aEvent) override;
|
2017-08-07 05:23:43 +00:00
|
|
|
void DurationChanged() override;
|
2017-08-09 03:06:29 +00:00
|
|
|
void MetadataLoaded(UniquePtr<MediaInfo> aInfo, UniquePtr<MetadataTags> aTags,
|
|
|
|
MediaDecoderEventVisibility aEventVisibility) override;
|
2018-03-01 01:08:30 +00:00
|
|
|
void NotifyPrincipalChanged() override;
|
2017-08-09 03:06:29 +00:00
|
|
|
|
2017-06-20 10:10:56 +00:00
|
|
|
RefPtr<ResourceCallback> mResourceCallback;
|
2017-08-04 06:52:22 +00:00
|
|
|
RefPtr<BaseMediaResource> mResource;
|
2017-06-20 10:10:56 +00:00
|
|
|
|
2017-06-19 07:50:09 +00:00
|
|
|
explicit ChannelMediaDecoder(MediaDecoderInit& aInit);
|
2017-06-20 10:10:27 +00:00
|
|
|
|
2019-05-27 16:15:33 +00:00
|
|
|
void GetDebugInfo(dom::MediaDecoderDebugInfo& aInfo);
|
2017-10-25 05:57:39 +00:00
|
|
|
|
2017-10-16 20:55:26 +00:00
|
|
|
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);
|
|
|
|
|
2017-06-20 10:10:56 +00:00
|
|
|
void Shutdown() override;
|
|
|
|
|
2017-08-04 07:29:55 +00:00
|
|
|
bool CanClone();
|
|
|
|
|
2017-06-20 10:10:27 +00:00
|
|
|
// Create a new decoder of the same type as this one.
|
2017-08-03 09:39:55 +00:00
|
|
|
already_AddRefed<ChannelMediaDecoder> Clone(MediaDecoderInit& aInit);
|
2017-06-21 09:30:56 +00:00
|
|
|
|
2017-08-03 09:48:26 +00:00
|
|
|
nsresult Load(nsIChannel* aChannel, bool aIsPrivateBrowsing,
|
|
|
|
nsIStreamListener** aStreamListener);
|
2017-06-23 06:12:41 +00:00
|
|
|
|
2017-08-24 09:35:24 +00:00
|
|
|
void AddSizeOfResources(ResourceSizes* aSizes) override;
|
2017-08-24 08:58:06 +00:00
|
|
|
already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
|
2019-06-04 06:32:37 +00:00
|
|
|
bool HadCrossOriginRedirects() override;
|
2017-08-23 16:06:23 +00:00
|
|
|
bool IsTransportSeekable() override;
|
2017-08-07 10:09:56 +00:00
|
|
|
void SetLoadInBackground(bool aLoadInBackground) override;
|
|
|
|
void Suspend() override;
|
|
|
|
void Resume() override;
|
|
|
|
|
2017-06-23 06:12:41 +00:00
|
|
|
private:
|
2017-11-30 03:21:14 +00:00
|
|
|
void DownloadProgressed();
|
2017-08-17 07:41:22 +00:00
|
|
|
|
2017-08-15 04:37:00 +00:00
|
|
|
// Create a new state machine to run this decoder.
|
|
|
|
MediaDecoderStateMachine* CreateStateMachine();
|
|
|
|
|
2017-08-04 06:52:22 +00:00
|
|
|
nsresult Load(BaseMediaResource* aOriginal);
|
2017-08-04 08:02:40 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2018-02-06 06:50:00 +00:00
|
|
|
bool CanPlayThroughImpl() final;
|
2017-08-07 03:48:43 +00:00
|
|
|
|
2017-12-01 07:05:25 +00:00
|
|
|
struct PlaybackRateInfo {
|
|
|
|
uint32_t mRate; // Estimate of the current playback rate (bytes/second).
|
|
|
|
bool mReliable; // True if mRate is a reliable estimate.
|
|
|
|
};
|
2017-08-07 05:23:43 +00:00
|
|
|
// The actual playback rate computation.
|
2017-12-05 07:21:45 +00:00
|
|
|
static PlaybackRateInfo ComputePlaybackRate(
|
|
|
|
const MediaChannelStatistics& aStats, BaseMediaResource* aResource,
|
|
|
|
double aDuration);
|
2017-08-07 05:23:43 +00:00
|
|
|
|
|
|
|
// Something has changed that could affect the computed playback rate,
|
|
|
|
// so recompute it.
|
2017-12-05 06:13:22 +00:00
|
|
|
static void UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
|
|
|
|
BaseMediaResource* aResource);
|
2017-08-07 05:23:43 +00:00
|
|
|
|
|
|
|
// Return statistics. This is used for progress events and other things.
|
|
|
|
// This can be called from any thread. It's only a snapshot of the
|
|
|
|
// current state, since other threads might be changing the state
|
|
|
|
// at any time.
|
2017-12-05 07:06:34 +00:00
|
|
|
static MediaStatistics GetStatistics(const PlaybackRateInfo& aInfo,
|
|
|
|
BaseMediaResource* aRes,
|
|
|
|
int64_t aPlaybackPosition);
|
2017-08-07 05:23:43 +00:00
|
|
|
|
2017-12-01 06:36:35 +00:00
|
|
|
bool ShouldThrottleDownload(const MediaStatistics& aStats);
|
2017-08-07 05:23:43 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2017-12-01 03:26:03 +00:00
|
|
|
// Current playback position in the stream. This is (approximately)
|
|
|
|
// where we're up to playing back the stream. This is not adjusted
|
|
|
|
// during decoder seek operations, but it's updated at the end when we
|
|
|
|
// start playing back again.
|
|
|
|
int64_t mPlaybackPosition = 0;
|
2017-12-05 07:06:34 +00:00
|
|
|
|
|
|
|
bool mCanPlayThrough = false;
|
2018-03-01 01:08:30 +00:00
|
|
|
|
|
|
|
// True if we've been notified that the ChannelMediaResource has
|
|
|
|
// a principal.
|
|
|
|
bool mInitialChannelPrincipalKnown = false;
|
2017-06-19 07:50:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // ChannelMediaDecoder_h_
|