Files
palemoon27/dom/media/mediasource/MediaSourceReader.h
T
roytam1 c7618a1247 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1128380: Make AmpleVideoFrames calculation dynamic. r=cpearce (e1e11d289)
- Bug 1161901 - Sprinkle more assertions and fix some formatting. r=jww (1a008614e)
- Bug 1152218 - Have a larger tolerance to decide if video data is low or not. r=cpearce. (72dc49d9b)
- indent fix (b6fe75862)
- Bug 1161901 - Relax assertion. r=jww (f20d88804)
- Bug 1155500: Have nsAutoPtr transfers ownership when copying related objects. r=froydnj (eddd7e87b)
- Bug 1188203 - Fix more constructors in XPCOM; r=froydnj (51eb10519)
- Bug 1179787 - part 1 - forward StorensRefPtrPassByPtr's constructor argument; r=botond (9af32af89)
- Bug 1179787 - part 2 - add template logic for smart pointer template arguments in NS_NewRunnableMethod*; r=botond (380172704)
- fix indentation (c4b2356bd)
- Bug 1162381. Part 2 - refactor DecodedStreamData::mInitialTime to be consistent with AudioSink when computing stream position. r=roc. (8574a32a1)
- Bug 1172778 - Update readyState when audio samples are popped by AudioSink. r=cpearce. (3f64e7151)
- Bug 1172392 - Align update of audio end time of decoded stream with that of AudioSink. r=roc. (01e7ba014)
- Bug 1152023 - Null check root frame when marking frames dirty in response to a user font load. r=jdaggett (e6ca132fd)
- Bug 1162366 - Fix spelling of nsPresContext::mSupressResizeReflow and associated methods. r=dholbert (35d4ce30c)
- Bug 1154148 - Create a FontFaceSet's UserFontSet eagerly. r=jdaggett (29d2b2b57)
- Bug 1154150 - Only create a FontFaceSet if we find @font-face rules. r=jdaggett (cf4b6979a)
- Bug 1144450 - Part 1: Fix a typo in test_font_loading_api.html. r=jdaggett (8117e267b)
- Bug 1144450 - Part 2: Don't replace a FontFaceSet's ready promise when there are no loading FontFaces. r=jdaggett (196fbeb2d)
- Bug 1144450 - Part 3: Replace uses of mDispatchedLoadingEvent with mStatus, as they're equivalent. r=jdaggett (bbf1e2324)
- Bug 1144450 - Part 4: Replace uses of mReadyIsResolved with mStatus, as they're equivalent. r=jdaggett (ddb5dbce4)
- Bug 1144450 - Part 5: Fix/add tests for not firing loadingdone/loadingerror when adding an already-loaded/error FontFace to a FontFaceSet. r=jdaggett (821bea9fc)
- Bug 1144977 - Part 2: Tests. r=jdaggett (14bcd5b00)
- Bug 1145937 - Don't set FontFaceSet status to Loaded between a font download completion and the document reflow. r=jdaggett (444fb88d1)
2021-03-29 10:34:24 +08:00

291 lines
9.6 KiB
C++

/* -*- 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 MOZILLA_MEDIASOURCEREADER_H_
#define MOZILLA_MEDIASOURCEREADER_H_
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "nsCOMPtr.h"
#include "nsError.h"
#include "nsString.h"
#include "nsTArray.h"
#include "MediaDecoderReader.h"
namespace mozilla {
class MediaSourceDecoder;
class SourceBufferDecoder;
class TrackBuffer;
namespace dom {
class MediaSource;
} // namespace dom
class MediaSourceReader : public MediaDecoderReader
{
public:
explicit MediaSourceReader(MediaSourceDecoder* aDecoder);
nsresult Init(MediaDecoderReader* aCloneDonor) override
{
// Although we technically don't implement anything here, we return NS_OK
// so that when the state machine initializes and calls this function
// we don't return an error code back to the media element.
return NS_OK;
}
// Indicates the point in time at which the reader should consider
// registered TrackBuffers essential for initialization.
void PrepareInitialization();
bool IsWaitingMediaResources() override;
bool IsWaitingOnCDMResource() override;
nsRefPtr<AudioDataPromise> RequestAudioData() override;
nsRefPtr<VideoDataPromise>
RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold) override;
virtual size_t SizeOfVideoQueueInFrames() override;
virtual size_t SizeOfAudioQueueInFrames() override;
virtual bool IsDormantNeeded() override;
virtual void ReleaseMediaResources() override;
void OnAudioDecoded(AudioData* aSample);
void OnAudioNotDecoded(NotDecodedReason aReason);
void OnVideoDecoded(VideoData* aSample);
void OnVideoNotDecoded(NotDecodedReason aReason);
void DoVideoSeek();
void DoAudioSeek();
void OnVideoSeekCompleted(int64_t aTime);
void OnVideoSeekFailed(nsresult aResult);
void OnAudioSeekCompleted(int64_t aTime);
void OnAudioSeekFailed(nsresult aResult);
virtual bool IsWaitForDataSupported() override { return true; }
virtual nsRefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) override;
void MaybeNotifyHaveData();
bool HasVideo() override
{
return mInfo.HasVideo();
}
bool HasAudio() override
{
return mInfo.HasAudio();
}
void NotifyTimeRangesChanged();
virtual void DisableHardwareAcceleration() override {
if (GetVideoReader()) {
GetVideoReader()->DisableHardwareAcceleration();
}
}
// We can't compute a proper start time since we won't necessarily
// have the first frame of the resource available. This does the same
// as chrome/blink and assumes that we always start at t=0.
virtual bool ForceZeroStartTime() const override { return true; }
virtual int64_t ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio) override { return 0; }
// Buffering heuristics don't make sense for MSE, because the arrival of data
// is at least partly controlled by javascript, and javascript does not expect
// us to sit on unplayed data just because it may not be enough to play
// through.
bool UseBufferingHeuristics() override { return false; }
bool IsMediaSeekable() override { return true; }
nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) override;
void ReadUpdatedMetadata(MediaInfo* aInfo) override;
nsRefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
nsresult ResetDecode() override;
// Acquires the decoder monitor, and is thus callable on any thread.
media::TimeIntervals GetBuffered() override;
already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType,
int64_t aTimestampOffset /* microseconds */);
void AddTrackBuffer(TrackBuffer* aTrackBuffer);
void RemoveTrackBuffer(TrackBuffer* aTrackBuffer);
void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
nsRefPtr<ShutdownPromise> Shutdown() override;
virtual void BreakCycles() override;
bool IsShutdown()
{
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
return mDecoder->IsShutdown();
}
// Return true if all of the active tracks contain data for the specified time.
bool TrackBuffersContainTime(int64_t aTime);
// Mark the reader to indicate that EndOfStream has been called on our MediaSource
// and that the media element has all the media data.
// If called with true, the reader will come out of ended mode.
void Ended(bool aEnded);
// Return true if reader has all of the media data.
bool IsEnded();
// Set the duration of the attached mediasource element.
void SetMediaSourceDuration(double aDuration /* seconds */);
virtual bool IsAsync() const override {
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
return (!GetAudioReader() || GetAudioReader()->IsAsync()) &&
(!GetVideoReader() || GetVideoReader()->IsAsync());
}
virtual bool VideoIsHardwareAccelerated() const override {
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
return GetVideoReader() && GetVideoReader()->VideoIsHardwareAccelerated();
}
// Returns true if aReader is a currently active audio or video
bool IsActiveReader(MediaDecoderReader* aReader);
// Returns a string describing the state of the MediaSource internal
// buffered data. Used for debugging purposes.
void GetMozDebugReaderData(nsAString& aString);
private:
// Switch the current audio/video source to the source that
// contains aTarget (or up to aTolerance after target). Both
// aTarget and aTolerance are in microseconds.
// Search can be made using a fuzz factor. Should an approximated value be
// found instead, aTarget will be updated to the actual target found.
enum SwitchSourceResult {
SOURCE_NONE = -1,
SOURCE_EXISTING = 0,
SOURCE_NEW = 1,
};
SwitchSourceResult SwitchAudioSource(int64_t* aTarget);
SwitchSourceResult SwitchVideoSource(int64_t* aTarget);
void DoAudioRequest();
void DoVideoRequest();
void CompleteAudioSeekAndDoRequest()
{
mAudioSeekRequest.Complete();
DoAudioRequest();
}
void CompleteVideoSeekAndDoRequest()
{
mVideoSeekRequest.Complete();
DoVideoRequest();
}
void CompleteAudioSeekAndRejectPromise()
{
mAudioSeekRequest.Complete();
mAudioPromise.Reject(DECODE_ERROR, __func__);
}
void CompleteVideoSeekAndRejectPromise()
{
mVideoSeekRequest.Complete();
mVideoPromise.Reject(DECODE_ERROR, __func__);
}
MediaDecoderReader* GetAudioReader() const;
MediaDecoderReader* GetVideoReader() const;
int64_t GetReaderAudioTime(int64_t aTime) const;
int64_t GetReaderVideoTime(int64_t aTime) const;
// Will reject the MediaPromise with END_OF_STREAM if mediasource has ended
// or with WAIT_FOR_DATA otherwise.
void CheckForWaitOrEndOfStream(MediaData::Type aType, int64_t aTime /* microseconds */);
// Return a decoder from the set available in aTrackDecoders that has data
// available in the range requested by aTarget.
already_AddRefed<SourceBufferDecoder> SelectDecoder(int64_t aTarget /* microseconds */,
int64_t aTolerance /* microseconds */,
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
bool HaveData(int64_t aTarget, MediaData::Type aType);
already_AddRefed<SourceBufferDecoder> FirstDecoder(MediaData::Type aType);
void AttemptSeek();
bool IsSeeking() { return mPendingSeekTime != -1; }
bool IsNearEnd(MediaData::Type aType, int64_t aTime /* microseconds */);
int64_t LastSampleTime(MediaData::Type aType);
nsRefPtr<SourceBufferDecoder> mAudioSourceDecoder;
nsRefPtr<SourceBufferDecoder> mVideoSourceDecoder;
nsTArray<nsRefPtr<TrackBuffer>> mTrackBuffers;
nsTArray<nsRefPtr<TrackBuffer>> mShutdownTrackBuffers;
nsTArray<nsRefPtr<TrackBuffer>> mEssentialTrackBuffers;
nsRefPtr<TrackBuffer> mAudioTrack;
nsRefPtr<TrackBuffer> mVideoTrack;
MediaPromiseRequestHolder<AudioDataPromise> mAudioRequest;
MediaPromiseRequestHolder<VideoDataPromise> mVideoRequest;
MediaPromiseHolder<AudioDataPromise> mAudioPromise;
MediaPromiseHolder<VideoDataPromise> mVideoPromise;
MediaPromiseHolder<WaitForDataPromise> mAudioWaitPromise;
MediaPromiseHolder<WaitForDataPromise> mVideoWaitPromise;
MediaPromiseHolder<WaitForDataPromise>& WaitPromise(MediaData::Type aType)
{
return aType == MediaData::AUDIO_DATA ? mAudioWaitPromise : mVideoWaitPromise;
}
// These are read and written on the decode task queue threads.
int64_t mLastAudioTime;
int64_t mLastVideoTime;
MediaPromiseRequestHolder<SeekPromise> mAudioSeekRequest;
MediaPromiseRequestHolder<SeekPromise> mVideoSeekRequest;
MediaPromiseHolder<SeekPromise> mSeekPromise;
// Temporary seek information while we wait for the data
// to be added to the track buffer.
int64_t mOriginalSeekTime;
int64_t mPendingSeekTime;
bool mWaitingForSeekData;
bool mSeekToEnd;
int64_t mTimeThreshold;
bool mDropAudioBeforeThreshold;
bool mDropVideoBeforeThreshold;
bool mAudioDiscontinuity;
bool mVideoDiscontinuity;
bool mEnded;
double mMediaSourceDuration;
bool mHasEssentialTrackBuffers;
void ContinueShutdown();
MediaPromiseHolder<ShutdownPromise> mMediaSourceShutdownPromise;
#ifdef MOZ_FMP4
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
#endif
};
} // namespace mozilla
#endif /* MOZILLA_MEDIASOURCEREADER_H_ */