Bug Summary

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