Bug Summary

File:root/firefox-clang/dom/media/MediaFormatReader.h
Warning:line 396, column 10
Excessive padding in 'struct mozilla::MediaFormatReader::DecoderData' (34 padding bytes, where 2 is optimal). Optimal fields order: mOwner, mTrackDemuxer, mTaskQueue, mDecoder, mDecodePerfRecorder, mSeekRequest, mQueuedSamples, mDemuxRequest, mWaitingPromise, mDecodeRequest, mShutdownPromise, mDrainRequest, mOutput, mNumSamplesInput, mNumSamplesOutput, mNumSamplesOutputTotal, mNumSamplesSkippedTotal, mSizeOfQueue, mOriginalInfo, mWorkingInfo, mInfo, mDescription, mProcessName, mCodecName, mWaitingForDataStartTime, mFrameRateEstimator, mFirstFrameTime, mLastTimeRangesEnd, mFirstDemuxedSampleTime, mError, mMutex, mLastDecodedSampleTime, mTimeThreshold, mTimeRanges, mDrainState, mNumOfConsecutiveDecodingError, mMaxConsecutiveDecodingError, mNumOfConsecutiveRDDOrGPUCrashes, mMaxConsecutiveRDDOrGPUCrashes, mNumOfConsecutiveUtilityCrashes, mMaxConsecutiveUtilityCrashes, mIsHardwareAccelerated, mLastStreamSourceID, mNextStreamSourceID, mVideoDecodeProperties, mType, mUpdateScheduled, mDemuxEOS, mWaitingForKey, mReceivedNewData, mFlushing, mFlushed, mIsNullDecode, mHardwareDecodingDisabled, mHasReportedVideoHardwareSupportTelemtry, consider reordering the fields or adding explicit padding members

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_media_mediasink0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/mediasink -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/mediasink -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/media/mediasink -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/mediasink -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libsoundtouch/src -I /root/firefox-clang/dom/media -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_dom_media_mediasink0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#if !defined(MediaFormatReader_h_)
6# define MediaFormatReader_h_
7
8# include "FrameStatistics.h"
9# include "MediaDataDemuxer.h"
10# include "MediaEventSource.h"
11# include "MediaMetadataManager.h"
12# include "MediaPromiseDefs.h"
13# include "PlatformDecoderModule.h"
14# include "SeekTarget.h"
15# include "mozilla/Atomics.h"
16# include "mozilla/CumulativeAverage.h"
17# include "mozilla/Maybe.h"
18# include "mozilla/MozPromise.h"
19# include "mozilla/Mutex.h"
20# include "mozilla/StateMirroring.h"
21# include "mozilla/StaticPrefs_media.h"
22# include "mozilla/TaskQueue.h"
23# include "mozilla/ThreadSafeWeakPtr.h"
24# include "mozilla/TimeStamp.h"
25# include "mozilla/dom/MediaDebugInfoBinding.h"
26
27namespace mozilla {
28
29class CDMProxy;
30class GMPCrashHelper;
31class MediaResource;
32class VideoFrameContainer;
33
34struct WaitForDataRejectValue {
35 enum Reason { SHUTDOWN, CANCELED };
36
37 WaitForDataRejectValue(MediaData::Type aType, Reason aReason)
38 : mType(aType), mReason(aReason) {}
39 MediaData::Type mType;
40 Reason mReason;
41};
42
43struct SeekRejectValue {
44 MOZ_IMPLICIT SeekRejectValue(const MediaResult& aError)
45 : mType(MediaData::Type::NULL_DATA), mError(aError) {}
46 MOZ_IMPLICIT SeekRejectValue(nsresult aResult)
47 : mType(MediaData::Type::NULL_DATA), mError(aResult) {}
48 SeekRejectValue(MediaData::Type aType, const MediaResult& aError)
49 : mType(aType), mError(aError) {}
50 MediaData::Type mType;
51 MediaResult mError;
52};
53
54struct MetadataHolder {
55 UniquePtr<MediaInfo> mInfo;
56 UniquePtr<MetadataTags> mTags;
57};
58
59using MediaDecoderOwnerID = void*;
60
61struct MOZ_STACK_CLASS MediaFormatReaderInit {
62 MediaResource* mResource = nullptr;
63 VideoFrameContainer* mVideoFrameContainer = nullptr;
64 FrameStatistics* mFrameStats = nullptr;
65 already_AddRefed<layers::KnowsCompositor> mKnowsCompositor;
66 already_AddRefed<GMPCrashHelper> mCrashHelper;
67 // Used in bug 1393399 for temporary telemetry.
68 MediaDecoderOwnerID mMediaDecoderOwnerID = nullptr;
69 Maybe<TrackingId> mTrackingId;
70};
71
72DDLoggedTypeDeclName(MediaFormatReader)class MediaFormatReader; template <> struct DDLoggedTypeTraits
<MediaFormatReader> { using Type = MediaFormatReader; static
constexpr const char* Name() { return "MediaFormatReader"; }
using HasBase = std::false_type; using BaseType = MediaFormatReader
; static constexpr const char* BaseTypeName() { return ""; } }
;
;
73
74class MediaFormatReader final
75 : public SupportsThreadSafeWeakPtr<MediaFormatReader>,
76 public DecoderDoctorLifeLogger<MediaFormatReader> {
77 static const bool IsExclusive = true;
78 using TrackType = TrackInfo::TrackType;
79 using NotifyDataArrivedPromise = MozPromise<bool, MediaResult, IsExclusive>;
80
81 public:
82 MOZ_DECLARE_REFCOUNTED_TYPENAME(MediaFormatReader)const char* typeName() const { return "MediaFormatReader"; } size_t
typeSize() const { return sizeof(*this); }
83
84 using TrackSet = EnumSet<TrackInfo::TrackType>;
85 using MetadataPromise = MozPromise<MetadataHolder, MediaResult, IsExclusive>;
86
87 template <typename Type>
88 using DataPromise = MozPromise<RefPtr<Type>, MediaResult, IsExclusive>;
89 using AudioDataPromise = DataPromise<AudioData>;
90 using VideoDataPromise = DataPromise<VideoData>;
91
92 using SeekPromise = MozPromise<media::TimeUnit, SeekRejectValue, IsExclusive>;
93
94 // Note that, conceptually, WaitForData makes sense in a non-exclusive sense.
95 // But in the current architecture it's only ever used exclusively (by MDSM),
96 // so we mark it that way to verify our assumptions. If you have a use-case
97 // for multiple WaitForData consumers, feel free to flip the exclusivity here.
98 using WaitForDataPromise =
99 MozPromise<MediaData::Type, WaitForDataRejectValue, IsExclusive>;
100
101 MediaFormatReader(MediaFormatReaderInit& aInit, MediaDataDemuxer* aDemuxer);
102 virtual ~MediaFormatReader();
103
104 // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
105 // on failure.
106 nsresult Init();
107
108 size_t SizeOfVideoQueueInFrames();
109 size_t SizeOfAudioQueueInFrames();
110
111 // Requests one video sample from the reader.
112 RefPtr<VideoDataPromise> RequestVideoData(
113 const media::TimeUnit& aTimeThreshold,
114 bool aRequestNextVideoKeyFrame = false);
115
116 // Requests one audio sample from the reader.
117 //
118 // The decode should be performed asynchronously, and the promise should
119 // be resolved when it is complete.
120 RefPtr<AudioDataPromise> RequestAudioData();
121
122 // The default implementation of AsyncReadMetadata is implemented in terms of
123 // synchronous ReadMetadata() calls. Implementations may also
124 // override AsyncReadMetadata to create a more proper async implementation.
125 RefPtr<MetadataPromise> AsyncReadMetadata();
126
127 // Fills aInfo with the latest cached data required to present the media,
128 // ReadUpdatedMetadata will always be called once ReadMetadata has succeeded.
129 void ReadUpdatedMetadata(MediaInfo* aInfo);
130
131 RefPtr<SeekPromise> Seek(const SeekTarget& aTarget);
132
133 // Called once new data has been cached by the MediaResource.
134 // mBuffered should be recalculated and updated accordingly.
135 void NotifyDataArrived();
136
137 // Update ID for the external playback engine. Currently it's only used on
138 // Windows when the media engine playback is enabled.
139 void UpdateMediaEngineId(uint64_t aMediaEngineId);
140
141 // This function will be called if the media key is set before playback
142 // starts, indicating the playback should be encrypted.
143 void SetEncryptedCustomIdent();
144
145 bool IsEncryptedCustomIdent() const { return mEncryptedCustomIdent; }
146
147 protected:
148 // Recomputes mBuffered.
149 void UpdateBuffered();
150
151 public:
152 // Called by MDSM in dormant state to release resources allocated by this
153 // reader. The reader can resume decoding by calling Seek() to a specific
154 // position.
155 void ReleaseResources();
156
157 bool OnTaskQueue() const { return OwnerThread()->IsCurrentThreadIn(); }
158
159 // Resets all state related to decoding, emptying all buffers etc.
160 // Cancels all pending Request*Data() request callbacks, rejects any
161 // outstanding seek promises, and flushes the decode pipeline. The
162 // decoder must not call any of the callbacks for outstanding
163 // Request*Data() calls after this is called. Calls to Request*Data()
164 // made after this should be processed as usual.
165 //
166 // Normally this call preceedes a Seek() call, or shutdown.
167 //
168 // aParam is a set of TrackInfo::TrackType enums specifying which
169 // queues need to be reset, defaulting to both audio and video tracks.
170 nsresult ResetDecode(const TrackSet& aTracks);
171
172 // Destroys the decoding state. The reader cannot be made usable again.
173 // This is different from ReleaseMediaResources() as it is irreversable,
174 // whereas ReleaseMediaResources() is. Must be called on the decode
175 // thread.
176 RefPtr<ShutdownPromise> Shutdown();
177
178 // Returns true if this decoder reader uses hardware accelerated video
179 // decoding.
180 bool VideoIsHardwareAccelerated() const;
181
182 // By default, the state machine polls the reader once per second when it's
183 // in buffering mode. Some readers support a promise-based mechanism by which
184 // they notify the state machine when the data arrives.
185 bool IsWaitForDataSupported() const { return true; }
186
187 RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType);
188
189 // The MediaDecoderStateMachine uses various heuristics that assume that
190 // raw media data is arriving sequentially from a network channel. This
191 // makes sense in the <video src="foo"> case, but not for more advanced use
192 // cases like MSE.
193 bool UseBufferingHeuristics() const { return mTrackDemuxersMayBlock; }
194
195 RefPtr<SetCDMPromise> SetCDMProxy(CDMProxy* aProxy);
196
197 // Requests that the MediaFormatReader populates aInfo with debug information.
198 // This may be done asynchronously, and aInfo should *not* be accessed by the
199 // caller until the returned promise is resolved or rejected.
200 RefPtr<GenericPromise> RequestDebugInfo(
201 dom::MediaFormatReaderDebugInfo& aInfo);
202
203 // Switch the video decoder to NullDecoderModule. It might takes effective
204 // since a few samples later depends on how much demuxed samples are already
205 // queued in the original video decoder.
206 void SetVideoNullDecode(bool aIsNullDecode);
207
208 void UpdateCompositor(already_AddRefed<layers::KnowsCompositor>);
209
210 void UpdateDuration(const media::TimeUnit& aDuration) {
211 MOZ_ASSERT(OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(OnTaskQueue()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("OnTaskQueue()",
"/root/firefox-clang/dom/media/MediaFormatReader.h", 211); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 211); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
212 UpdateBuffered();
213 }
214
215 AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
216 return &mBuffered;
217 }
218
219 TaskQueue* OwnerThread() const { return mTaskQueue; }
220
221 TimedMetadataEventSource& TimedMetadataEvent() { return mTimedMetadataEvent; }
222
223 // Notified by the OggDemuxer during playback when chained ogg is detected.
224 MediaEventSource<void>& OnMediaNotSeekable() { return mOnMediaNotSeekable; }
225
226 TimedMetadataEventProducer& TimedMetadataProducer() {
227 return mTimedMetadataEvent;
228 }
229
230 MediaEventProducer<void>& MediaNotSeekableProducer() {
231 return mOnMediaNotSeekable;
232 }
233
234 // Notified if the reader can't decode a sample due to a missing decryption
235 // key.
236 MediaEventSource<TrackInfo::TrackType>& OnTrackWaitingForKey() {
237 return mOnTrackWaitingForKey;
238 }
239
240 MediaEventProducer<TrackInfo::TrackType>& OnTrackWaitingForKeyProducer() {
241 return mOnTrackWaitingForKey;
242 }
243
244 MediaEventSource<nsTArray<uint8_t>, nsString>& OnEncrypted() {
245 return mOnEncrypted;
246 }
247
248 MediaEventSource<void>& OnWaitingForKey() { return mOnWaitingForKey; }
249
250 MediaEventSource<MediaResult>& OnDecodeWarning() { return mOnDecodeWarning; }
251
252 MediaEventProducer<VideoInfo, AudioInfo>& OnTrackInfoUpdatedEvent() {
253 return mTrackInfoUpdatedEvent;
254 }
255
256# ifdef MOZ_WMF_CDM
257 // Called when the MFCDM encrypted playback path signals that a decryption key
258 // is needed before decoding can proceed.
259 void NotifyWaitingForKeyForMFCDM() {
260 NotifyWaitingForKey(TrackInfo::TrackType::kVideoTrack);
261 }
262# endif
263
264 template <typename T>
265 friend struct DDLoggedTypeTraits; // For DecoderData
266
267 class VideoDecodeProperties final {
268 public:
269 void Load(RefPtr<MediaDataDecoder>& aDecoder);
270 void Clear() {
271 mMaxQueueSize.reset();
272 mMinQueueSize.reset();
273 mSendToCompositorSize.reset();
274 }
275
276 Maybe<uint32_t> MaxQueueSize() { return mMaxQueueSize; }
277 Maybe<uint32_t> MinQueueSize() { return mMinQueueSize; }
278 Maybe<uint32_t> SendToCompositorSize() { return mSendToCompositorSize; }
279
280 private:
281 Maybe<uint32_t> mMaxQueueSize;
282 Maybe<uint32_t> mMinQueueSize;
283 Maybe<uint32_t> mSendToCompositorSize;
284 };
285
286 VideoDecodeProperties& GetVideoDecodeProperties() {
287 MutexAutoLock lock(mVideo.mMutex);
288 return mVideo.mVideoDecodeProperties;
289 }
290
291 private:
292 bool HasVideo() const { return mVideo.mTrackDemuxer; }
293 bool HasAudio() const { return mAudio.mTrackDemuxer; }
294
295 bool IsWaitingOnCDMResource();
296
297 bool InitDemuxer();
298 // Notify the track demuxers that new data has been received.
299 void NotifyTrackDemuxers();
300 void ReturnOutput(MediaData* aData, TrackType aTrack);
301
302 // Enqueues a task to call Update(aTrack) on the decoder task queue.
303 // Lock for corresponding track must be held.
304 void ScheduleUpdate(TrackType aTrack);
305 void Update(TrackType aTrack);
306 // Handle actions should more data be received.
307 // Returns true if no more action is required.
308 bool UpdateReceivedNewData(TrackType aTrack);
309 // Called when new samples need to be demuxed.
310 void RequestDemuxSamples(TrackType aTrack);
311 // Handle demuxed samples by the input behavior.
312 void HandleDemuxedSamples(TrackType aTrack,
313 FrameStatistics::AutoNotifyDecoded& aA);
314 // Decode any pending already demuxed samples.
315 void DecodeDemuxedSamples(TrackType aTrack, MediaRawData* aSample);
316
317 struct InternalSeekTarget {
318 InternalSeekTarget(const media::TimeInterval& aTime, bool aDropTarget)
319 : mTime(aTime),
320 mDropTarget(aDropTarget),
321 mWaiting(false),
322 mHasSeeked(false) {}
323
324 media::TimeUnit Time() const { return mTime.mStart; }
325 media::TimeUnit EndTime() const { return mTime.mEnd; }
326 bool Contains(const media::TimeUnit& aTime) const {
327 return mTime.Contains(aTime);
328 }
329
330 media::TimeInterval mTime;
331 bool mDropTarget;
332 // Whether known waiting for more raw packets, either for the random
333 // access point or dependent frames.
334 bool mWaiting;
335 // Whether `MediaTrackDemuxer::Seek()` has found the preceding random
336 // access point.
337 bool mHasSeeked;
338 };
339
340 // Perform an internal seek to aTime. If aDropTarget is true then
341 // the first sample past the target will be dropped.
342 void InternalSeek(TrackType aTrack, const InternalSeekTarget& aTarget);
343 // Return the end time of the internal seek target if it exists. Otherwise,
344 // return infinity.
345 media::TimeUnit GetInternalSeekTargetEndTime() const;
346
347 // Drain the current decoder.
348 void DrainDecoder(TrackType aTrack);
349 void NotifyNewOutput(TrackType aTrack,
350 MediaDataDecoder::DecodedData&& aResults);
351 void NotifyError(TrackType aTrack, const MediaResult& aError);
352 void NotifyWaitingForData(TrackType aTrack);
353 void NotifyWaitingForKey(TrackType aTrack);
354 void NotifyEndOfStream(TrackType aTrack);
355
356 void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
357
358 // Initializes mLayersBackendType if possible.
359 void InitLayersBackendType();
360
361 void Reset(TrackType aTrack);
362 void DropDecodedSamples(TrackType aTrack);
363
364 // Return a target timeunit which the reader should skip to, this would be
365 // either the timethreshold we pass, or the time of the next keyframe. Return
366 // nothing if we don't need to skip.
367 // @param aTimeThreshold
368 // The time that we expect the time of next video frame should be or go beyond
369 // @param aRequestNextVideoKeyFrame
370 // If true and the next keyframe's time is larger than aTimeThreshold, skip to
371 // the next keyframe time instead of aTimeThreshold.
372 Maybe<media::TimeUnit> ShouldSkip(media::TimeUnit aTimeThreshold,
373 bool aRequestNextVideoKeyFrame);
374
375 void SetVideoDecodeThreshold();
376
377 size_t SizeOfQueue(TrackType aTrack);
378
379 void NotifyTrackInfoUpdated();
380
381 enum class DrainState {
382 None,
383 DrainRequested,
384 Draining,
385 PartialDrainPending,
386 DrainCompleted,
387 DrainAborted,
388 };
389
390 class SharedShutdownPromiseHolder : public MozPromiseHolder<ShutdownPromise> {
391 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedShutdownPromiseHolder)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<SharedShutdownPromiseHolder>, "Reference-counted class "
"SharedShutdownPromiseHolder" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/media/MediaFormatReader.h"
, 391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 391
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("SharedShutdownPromiseHolder"), (uint32_t)(sizeof(*this))
); return (nsrefcnt)count; } MozExternalRefCountType Release(
void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/media/MediaFormatReader.h"
, 391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 391
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("SharedShutdownPromiseHolder")); if (count == 0) { delete
(this); return 0; } return count; } using HasThreadSafeRefCnt
= std::true_type; protected: ::mozilla::ThreadSafeAutoRefCnt
mRefCnt; public:
392 private:
393 ~SharedShutdownPromiseHolder() = default;
394 };
395
396 struct DecoderData {
Excessive padding in 'struct mozilla::MediaFormatReader::DecoderData' (34 padding bytes, where 2 is optimal). Optimal fields order: mOwner, mTrackDemuxer, mTaskQueue, mDecoder, mDecodePerfRecorder, mSeekRequest, mQueuedSamples, mDemuxRequest, mWaitingPromise, mDecodeRequest, mShutdownPromise, mDrainRequest, mOutput, mNumSamplesInput, mNumSamplesOutput, mNumSamplesOutputTotal, mNumSamplesSkippedTotal, mSizeOfQueue, mOriginalInfo, mWorkingInfo, mInfo, mDescription, mProcessName, mCodecName, mWaitingForDataStartTime, mFrameRateEstimator, mFirstFrameTime, mLastTimeRangesEnd, mFirstDemuxedSampleTime, mError, mMutex, mLastDecodedSampleTime, mTimeThreshold, mTimeRanges, mDrainState, mNumOfConsecutiveDecodingError, mMaxConsecutiveDecodingError, mNumOfConsecutiveRDDOrGPUCrashes, mMaxConsecutiveRDDOrGPUCrashes, mNumOfConsecutiveUtilityCrashes, mMaxConsecutiveUtilityCrashes, mIsHardwareAccelerated, mLastStreamSourceID, mNextStreamSourceID, mVideoDecodeProperties, mType, mUpdateScheduled, mDemuxEOS, mWaitingForKey, mReceivedNewData, mFlushing, mFlushed, mIsNullDecode, mHardwareDecodingDisabled, mHasReportedVideoHardwareSupportTelemtry, consider reordering the fields or adding explicit padding members
397 DecoderData(MediaFormatReader* aOwner, MediaData::Type aType,
398 uint32_t aNumOfMaxError)
399 : mOwner(aOwner),
400 mType(aType),
401 mMutex("DecoderData"),
402 mDescription("uninitialized"),
403 mProcessName(""),
404 mCodecName(""),
405 mUpdateScheduled(false),
406 mDemuxEOS(false),
407 mWaitingForDataStartTime(Nothing()),
408 mWaitingForKey(false),
409 mReceivedNewData(false),
410 mFlushing(false),
411 mFlushed(true),
412 mDrainState(DrainState::None),
413 mNumOfConsecutiveDecodingError(0),
414 mMaxConsecutiveDecodingError(aNumOfMaxError),
415 mNumOfConsecutiveRDDOrGPUCrashes(0),
416 mMaxConsecutiveRDDOrGPUCrashes(
417 StaticPrefs::media_rdd_process_max_crashes()),
418 mNumOfConsecutiveUtilityCrashes(0),
419 mMaxConsecutiveUtilityCrashes(
420 StaticPrefs::media_utility_process_max_crashes()),
421 mFirstFrameTime(Some(media::TimeUnit::Zero())),
422 mNumSamplesInput(0),
423 mNumSamplesOutput(0),
424 mNumSamplesOutputTotal(0),
425 mNumSamplesSkippedTotal(0),
426 mSizeOfQueue(0),
427 mIsHardwareAccelerated(false),
428 mLastStreamSourceID(UINT32_MAX(4294967295U)),
429 mIsNullDecode(false),
430 mHardwareDecodingDisabled(false) {
431 DecoderDoctorLogger::LogConstruction("MediaFormatReader::DecoderData",
432 this);
433 }
434
435 ~DecoderData() {
436 DecoderDoctorLogger::LogDestruction("MediaFormatReader::DecoderData",
437 this);
438 }
439
440 MediaFormatReader* mOwner;
441 // Disambiguate Audio vs Video.
442 MediaData::Type mType;
443 RefPtr<MediaTrackDemuxer> mTrackDemuxer;
444 // TaskQueue on which decoder can choose to decode.
445 // Only non-null up until the decoder is created.
446 RefPtr<TaskQueue> mTaskQueue;
447
448 // Mutex protecting mDescription, mDecoder, mTrackDemuxer, mWorkingInfo,
449 // mProcessName, mCodecName and mDecodeProperties as those can be read
450 // outside the TaskQueue. They are only written on the TaskQueue however, as
451 // such mMutex doesn't need to be held when those members are read on the
452 // TaskQueue.
453 Mutex mMutex MOZ_UNANNOTATED;
454 // The platform decoder.
455 RefPtr<MediaDataDecoder> mDecoder;
456 nsCString mDescription;
457 nsCString mProcessName;
458 nsCString mCodecName;
459 VideoDecodeProperties mVideoDecodeProperties;
460
461 void LoadDecodeProperties() {
462 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 462); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
463 if (mType == MediaData::Type::VIDEO_DATA) {
464 mVideoDecodeProperties.Load(mDecoder);
465 }
466 }
467
468 void ShutdownDecoder();
469
470 // Only accessed from reader's task queue.
471 bool mUpdateScheduled;
472 bool mDemuxEOS;
473 Maybe<TimeStamp> mWaitingForDataStartTime;
474 bool mWaitingForKey;
475 bool mReceivedNewData;
476 UniquePtr<PerformanceRecorderMulti<PlaybackStage>> mDecodePerfRecorder;
477
478 // Pending seek.
479 MozPromiseRequestHolder<MediaTrackDemuxer::SeekPromise> mSeekRequest;
480
481 // Queued demuxed samples waiting to be decoded.
482 nsTArray<RefPtr<MediaRawData>> mQueuedSamples;
483 MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
484 // A WaitingPromise is pending if the demuxer is waiting for data or
485 // if the decoder is waiting for a key.
486 MozPromiseHolder<WaitForDataPromise> mWaitingPromise;
487 bool HasWaitingPromise() const {
488 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 488); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 488); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
489 return !mWaitingPromise.IsEmpty();
490 }
491
492 bool IsWaitingForData() const {
493 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 493); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 493); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
494 return !!mWaitingForDataStartTime;
495 }
496
497 bool IsWaitingForKey() const {
498 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 498); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 498); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
499 return mWaitingForKey && mDecodeRequest.Exists();
500 }
501
502 // MediaDataDecoder handler's variables.
503 MozPromiseRequestHolder<MediaDataDecoder::DecodePromise> mDecodeRequest;
504 bool mFlushing; // True if flush is in action.
505 // Set to true if the last operation run on the decoder was a flush.
506 bool mFlushed;
507 RefPtr<SharedShutdownPromiseHolder> mShutdownPromise;
508
509 MozPromiseRequestHolder<MediaDataDecoder::DecodePromise> mDrainRequest;
510 DrainState mDrainState;
511 bool HasPendingDrain() const { return mDrainState != DrainState::None; }
512 bool HasCompletedDrain() const {
513 return mDrainState == DrainState::DrainCompleted ||
514 mDrainState == DrainState::DrainAborted;
515 }
516 void RequestDrain();
517
518 void StartRecordDecodingPerf(const TrackType aTrack,
519 const MediaRawData* aSample);
520
521 // Track decoding error and fail when we hit the limit.
522 uint32_t mNumOfConsecutiveDecodingError;
523 uint32_t mMaxConsecutiveDecodingError;
524
525 // Track RDD or GPU process crashes and fail when we hit the limit.
526 uint32_t mNumOfConsecutiveRDDOrGPUCrashes;
527 uint32_t mMaxConsecutiveRDDOrGPUCrashes;
528
529 // Track Utility process crashes and fail when we hit the limit.
530 uint32_t mNumOfConsecutiveUtilityCrashes;
531 uint32_t mMaxConsecutiveUtilityCrashes;
532
533 // Set when we haven't yet decoded the first frame.
534 // Cleared once the first frame has been decoded.
535 // This is used to determine, upon error, if we should try again to decode
536 // the frame, or skip to the next keyframe.
537 Maybe<media::TimeUnit> mFirstFrameTime;
538
539 Maybe<MediaResult> mError;
540 bool HasFatalError() const {
541 if (!mError.isSome()) {
542 return false;
543 }
544 if (mError.ref() == NS_ERROR_DOM_MEDIA_DECODE_ERR) {
545 // Allow decode errors to be non-fatal, but give up
546 // if we have too many, or if warnings should be treated as errors.
547 return mNumOfConsecutiveDecodingError > mMaxConsecutiveDecodingError ||
548 StaticPrefs::media_playback_warnings_as_errors();
549 }
550 if (mError.ref() == NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER) {
551 // If the caller asked for a new decoder we shouldn't treat
552 // it as fatal.
553 return false;
554 }
555 if (mError.ref() == NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_RDD_OR_GPU_ERR) {
556 // Allow RDD crashes to be non-fatal, but give up
557 // if we have too many, or if warnings should be treated as errors.
558 return mNumOfConsecutiveRDDOrGPUCrashes >
559 mMaxConsecutiveRDDOrGPUCrashes ||
560 StaticPrefs::media_playback_warnings_as_errors();
561 }
562 if (mError.ref() == NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_UTILITY_ERR) {
563 bool tooManyConsecutiveCrashes =
564 mNumOfConsecutiveUtilityCrashes > mMaxConsecutiveUtilityCrashes;
565 // TODO: Telemetry?
566 return tooManyConsecutiveCrashes ||
567 StaticPrefs::media_playback_warnings_as_errors();
568 }
569 if (mError.ref() == NS_ERROR_DOM_MEDIA_REMOTE_CRASHED_MF_CDM_ERR) {
570 return false;
571 }
572 // All other error types are fatal
573 return true;
574 }
575
576 // If set, all decoded samples prior mTimeThreshold will be dropped.
577 // Used for internal seeking when a change of stream is detected or when
578 // encountering data discontinuity.
579 Maybe<InternalSeekTarget> mTimeThreshold;
580 // Time of last decoded sample returned.
581 Maybe<media::TimeInterval> mLastDecodedSampleTime;
582
583 // Decoded samples returned my mDecoder awaiting being returned to
584 // state machine upon request.
585 nsTArray<RefPtr<MediaData>> mOutput;
586 uint64_t mNumSamplesInput;
587 uint64_t mNumSamplesOutput;
588 uint64_t mNumSamplesOutputTotal;
589 uint64_t mNumSamplesSkippedTotal;
590
591 // These get overridden in the templated concrete class.
592 // Indicate if we have a pending promise for decoded frame.
593 // Rejecting the promise will stop the reader from decoding ahead.
594 virtual bool HasPromise() const = 0;
595 virtual void RejectPromise(const MediaResult& aError,
596 StaticString aMethodName) = 0;
597
598 // Clear track demuxer related data.
599 void ResetDemuxer() {
600 mDemuxRequest.DisconnectIfExists();
601 mSeekRequest.DisconnectIfExists();
602 mTrackDemuxer->Reset();
603 mQueuedSamples.Clear();
604 }
605
606 // Flush the decoder if present and reset decoding related data.
607 // Following a flush, the decoder is ready to accept any new data.
608 void Flush();
609
610 bool CancelWaitingForKey() {
611 if (!mWaitingForKey) {
612 return false;
613 }
614 mWaitingForKey = false;
615 if (IsWaitingForData() || !HasWaitingPromise()) {
616 return false;
617 }
618 mWaitingPromise.Resolve(mType, __func__);
619 return true;
620 }
621
622 // Reset the state of the DecoderData, clearing all queued frames
623 // (pending demuxed and decoded).
624 // The track demuxer is *not* reset.
625 void ResetState() {
626 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 626); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 626); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
627 mDemuxEOS = false;
628 mWaitingForDataStartTime.reset();
629 mQueuedSamples.Clear();
630 mDecodeRequest.DisconnectIfExists();
631 mDrainRequest.DisconnectIfExists();
632 mDrainState = DrainState::None;
633 CancelWaitingForKey();
634 mTimeThreshold.reset();
635 mLastDecodedSampleTime.reset();
636 mOutput.Clear();
637 mNumSamplesInput = 0;
638 mNumSamplesOutput = 0;
639 mSizeOfQueue = 0;
640 mNextStreamSourceID.reset();
641 if (!HasFatalError()) {
642 mError.reset();
643 }
644 if (mType == MediaData::Type::VIDEO_DATA) {
645 mVideoDecodeProperties.Clear();
646 }
647 }
648
649 // Return whether an InternalSeek() has been requested but has not yet
650 // seeked to the random access point preceding that target.
651 bool HasInternalSeekPending() const {
652 return mTimeThreshold && !mTimeThreshold.ref().mHasSeeked;
653 }
654
655 // Return the current TrackInfo in the stream. If the stream content never
656 // changed since AsyncReadMetadata was called then the TrackInfo used is
657 // mOriginalInfo, other it will be mInfo. The later case is only ever true
658 // with MSE or the WebMDemuxer.
659 const TrackInfo* GetCurrentInfo() const {
660 if (mInfo) {
661 return *mInfo;
662 }
663 return mOriginalInfo.get();
664 }
665 // Return the current TrackInfo updated as per the decoder output.
666 // Typically for audio, the number of channels and/or sampling rate can vary
667 // between what was found in the metadata and what the decoder returned.
668 const TrackInfo* GetWorkingInfo() const { return mWorkingInfo.get(); }
669 bool IsEncrypted() const { return GetCurrentInfo()->mCrypto.IsEncrypted(); }
670
671 // Used by the MDSM for logging purposes.
672 Atomic<size_t> mSizeOfQueue;
673 // Used by the MDSM to determine if video decoding is hardware accelerated.
674 // This value is updated after a frame is successfully decoded.
675 Atomic<bool> mIsHardwareAccelerated;
676 // Sample format monitoring.
677 uint32_t mLastStreamSourceID;
678 Maybe<uint32_t> mNextStreamSourceID;
679 media::TimeIntervals mTimeRanges;
680 Maybe<media::TimeUnit> mLastTimeRangesEnd;
681 // TrackInfo as first discovered during ReadMetadata.
682 UniquePtr<TrackInfo> mOriginalInfo;
683 // Written exclusively on the TaskQueue, can be read on MDSM's TaskQueue.
684 // Must be read with parent's mutex held.
685 UniquePtr<TrackInfo> mWorkingInfo;
686 RefPtr<TrackInfoSharedPtr> mInfo;
687 Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
688 // Use NullDecoderModule or not.
689 bool mIsNullDecode;
690 bool mHardwareDecodingDisabled;
691 // Whether we have reported hardware decoding support for video. Used only
692 // on reader's task queue,
693 bool mHasReportedVideoHardwareSupportTelemtry = false;
694
695 // Running frame-rate estimate over valid demuxed samples for the current
696 // stream source.
697 class FrameRateEstimator {
698 public:
699 double Rate() const {
700 MOZ_ASSERT_IF(!mMeanDuration.empty(), mMeanDuration.mean() > 0.0)do { if (!mMeanDuration.empty()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(mMeanDuration.mean
() > 0.0)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mMeanDuration.mean() > 0.0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mMeanDuration.mean() > 0.0"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 700); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mMeanDuration.mean() > 0.0" ")"); do { MOZ_CrashSequence
(__null, 700); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); } } while (false)
;
701 return mMeanDuration.empty() ? 0.0 : 1.0 / mMeanDuration.mean();
702 }
703
704 void Observe(const MediaRawData& aSample) {
705 // mTrackInfo is a sparse stream-change marker.
706 if (aSample.mTrackInfo &&
707 (mSourceID.isNothing() ||
708 mSourceID.ref() != aSample.mTrackInfo->GetID())) {
709 Reset();
710 mSourceID = Some(aSample.mTrackInfo->GetID());
711 }
712
713 const media::TimeUnit& duration = aSample.mDuration;
714 if (!duration.IsValid() || !duration.IsPositive() ||
715 duration.IsInfinite()) {
716 return;
717 }
718 mMeanDuration.insert(duration.ToSeconds());
719 }
720
721 void Reset() { mMeanDuration.reset(); }
722
723 private:
724 CumulativeAverage<double> mMeanDuration;
725 Maybe<uint32_t> mSourceID;
726 } mFrameRateEstimator;
727 };
728
729 template <typename Type>
730 class DecoderDataWithPromise : public DecoderData {
731 public:
732 DecoderDataWithPromise(MediaFormatReader* aOwner, MediaData::Type aType,
733 uint32_t aNumOfMaxError)
734 : DecoderData(aOwner, aType, aNumOfMaxError), mHasPromise(false) {
735 DecoderDoctorLogger::LogConstructionAndBase(
736 "MediaFormatReader::DecoderDataWithPromise", this,
737 "MediaFormatReader::DecoderData",
738 static_cast<const MediaFormatReader::DecoderData*>(this));
739 }
740
741 ~DecoderDataWithPromise() {
742 DecoderDoctorLogger::LogDestruction(
743 "MediaFormatReader::DecoderDataWithPromise", this);
744 }
745
746 bool HasPromise() const override { return mHasPromise; }
747
748 RefPtr<DataPromise<Type>> EnsurePromise(StaticString aMethodName) {
749 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 749); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 749); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
750 mHasPromise = true;
751 return mPromise.Ensure(aMethodName);
752 }
753
754 void ResolvePromise(Type* aData, StaticString aMethodName) {
755 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 755); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 755); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
756 mPromise.Resolve(aData, aMethodName);
757 mHasPromise = false;
758 }
759
760 void RejectPromise(const MediaResult& aError,
761 StaticString aMethodName) override {
762 MOZ_ASSERT(mOwner->OnTaskQueue())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOwner->OnTaskQueue())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOwner->OnTaskQueue()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mOwner->OnTaskQueue()"
, "/root/firefox-clang/dom/media/MediaFormatReader.h", 762); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mOwner->OnTaskQueue()" ")"); do { MOZ_CrashSequence
(__null, 762); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
763 mPromise.Reject(aError, aMethodName);
764 mHasPromise = false;
765 }
766
767 private:
768 MozPromiseHolder<DataPromise<Type>> mPromise;
769 Atomic<bool> mHasPromise;
770 };
771
772 // Decode task queue.
773 RefPtr<TaskQueue> mTaskQueue;
774
775 DecoderDataWithPromise<AudioData> mAudio;
776 DecoderDataWithPromise<VideoData> mVideo;
777
778 Watchable<bool> mWorkingInfoChanged;
779 WatchManager<MediaFormatReader> mWatchManager;
780 bool mIsWatchingWorkingInfo;
781
782 // Returns true when the decoder for this track needs input.
783 bool NeedInput(DecoderData& aDecoder);
784
785 DecoderData& GetDecoderData(TrackType aTrack);
786
787 // Demuxer objects.
788 class DemuxerProxy;
789 UniquePtr<DemuxerProxy> mDemuxer;
790 bool mDemuxerInitDone;
791 void OnDemuxerInitDone(const MediaResult& aResult);
792 void OnDemuxerInitFailed(const MediaResult& aError);
793 MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest;
794 MozPromiseRequestHolder<NotifyDataArrivedPromise> mNotifyDataArrivedPromise;
795 bool mPendingNotifyDataArrived;
796 void OnDemuxFailed(TrackType aTrack, const MediaResult& aError);
797
798 void DoDemuxVideo();
799 void OnVideoDemuxCompleted(
800 const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
801 void OnVideoDemuxFailed(const MediaResult& aError) {
802 OnDemuxFailed(TrackType::kVideoTrack, aError);
803 }
804
805 void DoDemuxAudio();
806 void OnAudioDemuxCompleted(
807 const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
808 void OnAudioDemuxFailed(const MediaResult& aError) {
809 OnDemuxFailed(TrackType::kAudioTrack, aError);
810 }
811
812 void SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold);
813 MozPromiseRequestHolder<MediaTrackDemuxer::SkipAccessPointPromise>
814 mSkipRequest;
815 void VideoSkipReset(uint32_t aSkipped);
816 void OnVideoSkipCompleted(uint32_t aSkipped);
817 void OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailure);
818
819 // The last number of decoded output frames that we've reported to
820 // MediaDecoder::NotifyDecoded(). We diff the number of output video
821 // frames every time that DecodeVideoData() is called, and report the
822 // delta there.
823 uint64_t mLastReportedNumDecodedFrames;
824
825 // Timestamp of the previous decoded video keyframe, in microseconds.
826 int64_t mPreviousDecodedKeyframeTime_us;
827 // Default mLastDecodedKeyframeTime_us value, must be bigger than anything.
828 static const int64_t sNoPreviousDecodedKeyframe = INT64_MAX(9223372036854775807L);
829
830 RefPtr<layers::KnowsCompositor> mKnowsCompositor;
831
832 // Metadata objects
833 // True if we've read the streams' metadata.
834 bool mInitDone;
835 MozPromiseHolder<MetadataPromise> mMetadataPromise;
836 bool IsEncrypted() const;
837
838 // Set to true if any of our track buffers may be blocking.
839 bool mTrackDemuxersMayBlock;
840
841 // Seeking objects.
842 void SetSeekTarget(const SeekTarget& aTarget);
843 bool IsSeeking() const { return mPendingSeekTime.isSome(); }
844 bool IsVideoOnlySeeking() const {
845 return IsSeeking() && mOriginalSeekTarget.IsVideoOnly();
846 }
847 bool IsAudioOnlySeeking() const {
848 return IsSeeking() && mOriginalSeekTarget.IsAudioOnly();
849 }
850 void ScheduleSeek();
851 void AttemptSeek();
852 void OnSeekFailed(TrackType aTrack, const MediaResult& aError);
853 void DoVideoSeek();
854 void OnVideoSeekCompleted(media::TimeUnit aTime);
855 void OnVideoSeekFailed(const MediaResult& aError);
856 bool mSeekScheduled;
857
858 void DoAudioSeek();
859 void OnAudioSeekCompleted(media::TimeUnit aTime);
860 void OnAudioSeekFailed(const MediaResult& aError);
861 // The SeekTarget that was last given to Seek()
862 SeekTarget mOriginalSeekTarget;
863 // Temporary seek information while we wait for the data
864 Maybe<media::TimeUnit> mFallbackSeekTime;
865 Maybe<media::TimeUnit> mPendingSeekTime;
866 // Decode threshold computed when a video seek completes, remembered so it can
867 // be delivered once the decoder is restarted: a cold start during the seek
868 // releases and recreates the decoder after IsSeeking() is already false,
869 // which would otherwise drop the threshold before it reaches the new decoder.
870 Maybe<media::TimeUnit> mPendingVideoSeekThreshold;
871 MozPromiseHolder<SeekPromise> mSeekPromise;
872
873 RefPtr<VideoFrameContainer> mVideoFrameContainer;
874 layers::ImageContainer* GetImageContainer();
875
876 RefPtr<CDMProxy> mCDMProxy;
877
878 RefPtr<GMPCrashHelper> mCrashHelper;
879
880 void SetNullDecode(TrackType aTrack, bool aIsNullDecode);
881
882 class DecoderFactory;
883 UniquePtr<DecoderFactory> mDecoderFactory;
884
885 class ShutdownPromisePool;
886 UniquePtr<ShutdownPromisePool> mShutdownPromisePool;
887
888 MediaEventListener mOnTrackWaitingForKeyListener;
889
890 void OnFirstDemuxCompleted(
891 TrackInfo::TrackType aType,
892 const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples);
893
894 void OnFirstDemuxFailed(TrackInfo::TrackType aType,
895 const MediaResult& aError);
896
897 void MaybeResolveMetadataPromise();
898
899 // Stores presentation info required for playback.
900 MediaInfo mInfo;
901
902 UniquePtr<MetadataTags> mTags;
903
904 // A flag indicating if the start time is known or not.
905 bool mHasStartTime = false;
906
907 void ShutdownDecoder(TrackType aTrack);
908 RefPtr<ShutdownPromise> TearDownDecoders();
909
910 bool mShutdown = false;
911
912 // Buffered range.
913 Canonical<media::TimeIntervals> mBuffered;
914
915 // Used to send TimedMetadata to the listener.
916 TimedMetadataEventProducer mTimedMetadataEvent;
917
918 // Notify if this media is not seekable.
919 MediaEventProducer<void> mOnMediaNotSeekable;
920
921 // Notify if we are waiting for a decryption key.
922 MediaEventProducer<TrackInfo::TrackType> mOnTrackWaitingForKey;
923
924 MediaEventProducer<nsTArray<uint8_t>, nsString> mOnEncrypted;
925
926 MediaEventProducer<void> mOnWaitingForKey;
927
928 MediaEventProducer<MediaResult> mOnDecodeWarning;
929
930 MediaEventProducer<VideoInfo, AudioInfo> mTrackInfoUpdatedEvent;
931
932 RefPtr<FrameStatistics> mFrameStats;
933
934 // Used in bug 1393399 for telemetry.
935 const MediaDecoderOwnerID mMediaDecoderOwnerID;
936
937 bool ResolveSetCDMPromiseIfDone(TrackType aTrack);
938 void PrepareToSetCDMForTrack(TrackType aTrack);
939 MozPromiseHolder<SetCDMPromise> mSetCDMPromise;
940 TrackSet mSetCDMForTracks{};
941 bool IsDecoderWaitingForCDM(TrackType aTrack);
942
943 void GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo);
944
945 // Only be used on Windows when the media engine playback is enabled.
946 Maybe<uint64_t> mMediaEngineId;
947
948 const Maybe<TrackingId> mTrackingId;
949
950 // The start time of reading the metdata and how long does it take. This
951 // measurement includes the time of downloading media resource over the
952 // internet.
953 Maybe<TimeStamp> mReadMetadataStartTime;
954 TimeDuration mReadMetaDataTime;
955
956 // The total amount of time we have been waiting for the video data due to
957 // lacking of data.
958 TimeDuration mTotalWaitingForVideoDataTime;
959
960 // https://github.com/w3c/encrypted-media/issues/251#issuecomment-819783073
961 // Treat playback as encrypted if the media key is set before playback starts,
962 // this allows websites to start with non-encrypted stream and switch to
963 // encrypted stream later.
964 Atomic<bool> mEncryptedCustomIdent;
965};
966
967DDLoggedTypeCustomName(MediaFormatReader::DecoderData, DecoderData)template <> struct DDLoggedTypeTraits<MediaFormatReader
::DecoderData> { using Type = MediaFormatReader::DecoderData
; static constexpr const char* Name() { return "DecoderData";
} using HasBase = std::false_type; using BaseType = MediaFormatReader
::DecoderData; static constexpr const char* BaseTypeName() { return
""; } }
;
968
969} // namespace mozilla
970
971#endif