TrackBuffersManager.h (25094B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_TRACKBUFFERSMANAGER_H_ 8 #define MOZILLA_TRACKBUFFERSMANAGER_H_ 9 10 #include "MediaContainerType.h" 11 #include "MediaData.h" 12 #include "MediaDataDemuxer.h" 13 #include "MediaResult.h" 14 #include "MediaSourceDecoder.h" 15 #include "MediaSpan.h" 16 #include "SourceBufferTask.h" 17 #include "TimeUnits.h" 18 #include "mozilla/Atomics.h" 19 #include "mozilla/EventTargetCapability.h" 20 #include "mozilla/Maybe.h" 21 #include "mozilla/Mutex.h" 22 #include "mozilla/NotNull.h" 23 #include "mozilla/TaskQueue.h" 24 #include "mozilla/dom/MediaDebugInfoBinding.h" 25 #include "nsTArray.h" 26 27 namespace mozilla { 28 29 class AbstractThread; 30 class ContainerParser; 31 class MediaByteBuffer; 32 class MediaRawData; 33 class MediaSourceDemuxer; 34 class SourceBufferResource; 35 36 namespace dom { 37 enum class MediaSourceEndOfStreamError : uint8_t; 38 } // namespace dom 39 40 class SourceBufferTaskQueue { 41 public: 42 SourceBufferTaskQueue() = default; 43 44 ~SourceBufferTaskQueue() { 45 MOZ_ASSERT(mQueue.IsEmpty(), "All tasks must have been processed"); 46 } 47 48 void Push(SourceBufferTask* aTask) { mQueue.AppendElement(aTask); } 49 50 already_AddRefed<SourceBufferTask> Pop() { 51 if (!mQueue.Length()) { 52 return nullptr; 53 } 54 RefPtr<SourceBufferTask> task = std::move(mQueue[0]); 55 mQueue.RemoveElementAt(0); 56 return task.forget(); 57 } 58 59 nsTArray<RefPtr<SourceBufferTask>>::size_type Length() const { 60 return mQueue.Length(); 61 } 62 63 private: 64 nsTArray<RefPtr<SourceBufferTask>> mQueue; 65 }; 66 67 DDLoggedTypeDeclName(TrackBuffersManager); 68 69 class TrackBuffersManager final 70 : public DecoderDoctorLifeLogger<TrackBuffersManager> { 71 public: 72 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffersManager); 73 74 enum class EvictDataResult : int8_t { 75 NO_DATA_EVICTED, 76 CANT_EVICT, 77 BUFFER_FULL, 78 }; 79 80 using TrackType = TrackInfo::TrackType; 81 using MediaType = MediaData::Type; 82 using TrackBuffer = nsTArray<RefPtr<MediaRawData>>; 83 using AppendPromise = SourceBufferTask::AppendPromise; 84 using RangeRemovalPromise = SourceBufferTask::RangeRemovalPromise; 85 86 // Interface for SourceBuffer 87 TrackBuffersManager(MediaSourceDecoder* aParentDecoder, 88 const MediaContainerType& aType); 89 90 // Queue a task to add data to the end of the input buffer and run the MSE 91 // Buffer Append Algorithm 92 // 3.5.5 Buffer Append Algorithm. 93 // http://w3c.github.io/media-source/index.html#sourcebuffer-buffer-append 94 RefPtr<AppendPromise> AppendData(already_AddRefed<MediaByteBuffer> aData, 95 const SourceBufferAttributes& aAttributes); 96 97 // Queue a task to abort any pending AppendData. 98 // Does nothing at this stage. 99 void AbortAppendData(); 100 101 // Queue a task to run MSE Reset Parser State Algorithm. 102 // 3.5.2 Reset Parser State 103 void ResetParserState(SourceBufferAttributes& aAttributes); 104 105 // Queue a task to run the MSE range removal algorithm. 106 // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal 107 RefPtr<RangeRemovalPromise> RangeRemoval(media::TimeUnit aStart, 108 media::TimeUnit aEnd); 109 110 // Schedule data eviction if necessary as the next call to AppendData will 111 // add aSize bytes. 112 // Eviction is done in two steps, first remove data up to aPlaybackTime 113 // and if still more space is needed remove from the end. 114 EvictDataResult EvictData(const media::TimeUnit& aPlaybackTime, int64_t aSize, 115 TrackType aType); 116 117 // Schedule data eviction if necessary and the size of eviction would be 118 // determined automatically. This is currently used when the buffer's size is 119 // close to full and the normal procedure to evict data is not enough. 120 void EvictDataWithoutSize(TrackType aType, const media::TimeUnit& aTarget); 121 122 // Queue a task to run ChangeType 123 void ChangeType(const MediaContainerType& aType); 124 125 // Returns the buffered range currently managed. 126 // This may be called on any thread. 127 // Buffered must conform to 128 // http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered 129 media::TimeIntervals Buffered() const; 130 media::TimeUnit HighestStartTime() const; 131 media::TimeUnit HighestEndTime() const; 132 133 // Return the size of the data managed by this SourceBufferContentManager. 134 int64_t GetSize() const; 135 136 // Indicate that the MediaSource parent object got into "ended" state. 137 void SetEnded(const dom::Optional<dom::MediaSourceEndOfStreamError>& aError); 138 139 // The parent SourceBuffer is about to be destroyed. 140 void Detach(); 141 142 // Return the eviction threshold, in bytes, for a track type (audio or video). 143 // When the track type isn't passed in (kUndefinedTrack), this returns the 144 // value for video if a video track is present. Specifying the track type 145 // explicitely is useful when initialization hasn't finished, but the track 146 // type is known already. 147 int64_t EvictionThreshold( 148 TrackInfo::TrackType aType = TrackInfo::TrackType::kUndefinedTrack) const; 149 150 // Interface for MediaSourceDemuxer 151 MediaInfo GetMetadata() const; 152 const TrackBuffer& GetTrackBuffer(TrackInfo::TrackType aTrack) const; 153 const media::TimeIntervals& Buffered(TrackInfo::TrackType) const; 154 const media::TimeUnit& HighestStartTime(TrackInfo::TrackType) const; 155 media::TimeIntervals SafeBuffered(TrackInfo::TrackType) const; 156 bool HaveAllData() const { return mHaveAllData; } 157 uint32_t Evictable(TrackInfo::TrackType aTrack) const; 158 media::TimeUnit Seek(TrackInfo::TrackType aTrack, 159 const media::TimeUnit& aTime, 160 const media::TimeUnit& aFuzz); 161 uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack, 162 const media::TimeUnit& aTimeThreadshold, 163 const media::TimeUnit& aFuzz, 164 bool& aFound); 165 166 already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack, 167 const media::TimeUnit& aFuzz, 168 MediaResult& aResult); 169 int32_t FindCurrentPosition(TrackInfo::TrackType aTrack, 170 const media::TimeUnit& aFuzz) const 171 MOZ_REQUIRES(mTaskQueueCapability); 172 173 // Will set the next GetSample index if needed. This information is determined 174 // through the value of mNextSampleTimecode. Return false if the index 175 // couldn't be determined or if there's nothing more that could be demuxed. 176 // This occurs if either the track buffer doesn't contain the required 177 // timecode or is empty. 178 nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack, 179 const media::TimeUnit& aFuzz) 180 MOZ_REQUIRES(mTaskQueueCapability); 181 182 media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, 183 const media::TimeUnit& aFuzz); 184 185 // Requests that the TrackBuffersManager populates aInfo with debug 186 // information. This may be done asynchronously, and aInfo should *not* be 187 // accessed by the caller until the returned promise is resolved or rejected. 188 RefPtr<GenericPromise> RequestDebugInfo( 189 dom::TrackBuffersManagerDebugInfo& aInfo) const; 190 void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const; 191 192 private: 193 using CodedFrameProcessingPromise = MozPromise<bool, MediaResult, true>; 194 195 ~TrackBuffersManager(); 196 // main thread: 197 void Reopen(); 198 199 // All following functions run on the taskqueue. 200 RefPtr<AppendPromise> DoAppendData(already_AddRefed<MediaByteBuffer> aData, 201 const SourceBufferAttributes& aAttributes); 202 void ScheduleSegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability); 203 void SegmentParserLoop() MOZ_REQUIRES(mTaskQueueCapability); 204 void InitializationSegmentReceived() MOZ_REQUIRES(mTaskQueueCapability); 205 void ShutdownDemuxers() MOZ_REQUIRES(mTaskQueueCapability); 206 void CreateDemuxerforMIMEType() MOZ_REQUIRES(mTaskQueueCapability); 207 void ResetDemuxingState() MOZ_REQUIRES(mTaskQueueCapability); 208 void NeedMoreData() MOZ_REQUIRES(mTaskQueueCapability); 209 void RejectAppend(const MediaResult& aRejectValue, const char* aName) 210 MOZ_REQUIRES(mTaskQueueCapability); 211 // Will return a promise that will be resolved once all frames of the current 212 // media segment have been processed. 213 RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing() 214 MOZ_REQUIRES(mTaskQueueCapability); 215 void CompleteCodedFrameProcessing() MOZ_REQUIRES(mTaskQueueCapability); 216 // Called by ResetParserState. 217 void CompleteResetParserState() MOZ_REQUIRES(mTaskQueueCapability); 218 RefPtr<RangeRemovalPromise> CodedFrameRemovalWithPromise( 219 const media::TimeInterval& aInterval) MOZ_REQUIRES(mTaskQueueCapability); 220 bool CodedFrameRemoval(const media::TimeInterval& aInterval) 221 MOZ_REQUIRES(mTaskQueueCapability); 222 // Removes all coded frames -- this is not to spec and should be used as a 223 // last resort to clear buffers only if other methods cannot. 224 void RemoveAllCodedFrames() MOZ_REQUIRES(mTaskQueueCapability); 225 void SetAppendState(SourceBufferAttributes::AppendState aAppendState) 226 MOZ_REQUIRES(mTaskQueueCapability); 227 228 bool HasVideo() const { return mVideoTracks.mNumTracks > 0; } 229 bool HasAudio() const { return mAudioTracks.mNumTracks > 0; } 230 231 // The input buffer as per 232 // http://w3c.github.io/media-source/index.html#sourcebuffer-input-buffer 233 Maybe<MediaSpan> mInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability); 234 // Buffer full flag as per 235 // https://w3c.github.io/media-source/#sourcebuffer-buffer-full-flag. Accessed 236 // on both the main thread and the task queue. 237 Atomic<bool> mBufferFull; 238 bool mFirstInitializationSegmentReceived MOZ_GUARDED_BY(mTaskQueueCapability); 239 bool mChangeTypeReceived MOZ_GUARDED_BY(mTaskQueueCapability); 240 // Set to true once a new segment is started. 241 bool mNewMediaSegmentStarted MOZ_GUARDED_BY(mTaskQueueCapability); 242 bool mActiveTrack MOZ_GUARDED_BY(mTaskQueueCapability); 243 MediaContainerType mType MOZ_GUARDED_BY(mTaskQueueCapability); 244 245 // ContainerParser objects and methods. 246 // Those are used to parse the incoming input buffer. 247 248 // Recreate the ContainerParser and if aReuseInitData is true then 249 // feed it with the previous init segment found. 250 void RecreateParser(bool aReuseInitData) MOZ_REQUIRES(mTaskQueueCapability); 251 UniquePtr<ContainerParser> mParser; 252 253 // Demuxer objects and methods. 254 void AppendDataToCurrentInputBuffer(const MediaSpan& aData) 255 MOZ_REQUIRES(mTaskQueueCapability); 256 257 RefPtr<MediaByteBuffer> mInitData MOZ_GUARDED_BY(mTaskQueueCapability); 258 259 // Checks if a new set of init data is a repeat of the last set of init data 260 // received. Because streams may retransmit the same init data (or 261 // functionally equivalent init data) we do not want to perform costly 262 // operations each time we receive init data, only when it's actually 263 // different data. 264 bool IsRepeatInitData(const MediaInfo& aNewMediaInfo) const 265 MOZ_REQUIRES(mTaskQueueCapability); 266 267 // Temporary input buffer to handle partial media segment header. 268 // We store the current input buffer content into it should we need to 269 // reinitialize the demuxer once we have some samples and a discontinuity is 270 // detected. 271 Maybe<MediaSpan> mPendingInputBuffer MOZ_GUARDED_BY(mTaskQueueCapability); 272 RefPtr<SourceBufferResource> mCurrentInputBuffer 273 MOZ_GUARDED_BY(mTaskQueueCapability); 274 RefPtr<MediaDataDemuxer> mInputDemuxer MOZ_GUARDED_BY(mTaskQueueCapability); 275 // Length already processed in current media segment. 276 uint64_t mProcessedInput MOZ_GUARDED_BY(mTaskQueueCapability); 277 Maybe<media::TimeUnit> mLastParsedEndTime 278 MOZ_GUARDED_BY(mTaskQueueCapability); 279 280 void OnDemuxerInitDone(const MediaResult& aResult); 281 void OnDemuxerInitFailed(const MediaResult& aError); 282 void OnDemuxerResetDone(const MediaResult& aResult) 283 MOZ_REQUIRES(mTaskQueueCapability); 284 MozPromiseRequestHolder<MediaDataDemuxer::InitPromise> mDemuxerInitRequest; 285 286 void OnDemuxFailed(TrackType aTrack, const MediaResult& aError) 287 MOZ_REQUIRES(mTaskQueueCapability); 288 void DoDemuxVideo() MOZ_REQUIRES(mTaskQueueCapability); 289 void OnVideoDemuxCompleted( 290 const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples); 291 void OnVideoDemuxFailed(const MediaResult& aError) { 292 mVideoTracks.mDemuxRequest.Complete(); 293 mTaskQueueCapability->AssertOnCurrentThread(); 294 OnDemuxFailed(TrackType::kVideoTrack, aError); 295 } 296 void DoDemuxAudio() MOZ_REQUIRES(mTaskQueueCapability); 297 void OnAudioDemuxCompleted( 298 const RefPtr<MediaTrackDemuxer::SamplesHolder>& aSamples); 299 void OnAudioDemuxFailed(const MediaResult& aError) { 300 mAudioTracks.mDemuxRequest.Complete(); 301 mTaskQueueCapability->AssertOnCurrentThread(); 302 OnDemuxFailed(TrackType::kAudioTrack, aError); 303 } 304 305 // Dispatches an "encrypted" event is any sample in array has initData 306 // present. 307 void MaybeDispatchEncryptedEvent( 308 const nsTArray<RefPtr<MediaRawData>>& aSamples); 309 310 void DoEvictData(const media::TimeUnit& aPlaybackTime, 311 Maybe<int64_t> aSizeToEvict) 312 MOZ_REQUIRES(mTaskQueueCapability); 313 314 void GetDebugInfo(dom::TrackBuffersManagerDebugInfo& aInfo) const 315 MOZ_REQUIRES(mTaskQueueCapability); 316 317 struct TrackData { 318 TrackData() : mNumTracks(0), mNeedRandomAccessPoint(true), mSizeBuffer(0) {} 319 Atomic<uint32_t> mNumTracks; 320 // Definition of variables: 321 // https://w3c.github.io/media-source/#track-buffers 322 // Last decode timestamp variable that stores the decode timestamp of the 323 // last coded frame appended in the current coded frame group. 324 // The variable is initially unset to indicate that no coded frames have 325 // been appended yet. 326 Maybe<media::TimeUnit> mLastDecodeTimestamp; 327 // Last frame duration variable that stores the coded frame duration of the 328 // last coded frame appended in the current coded frame group. 329 // The variable is initially unset to indicate that no coded frames have 330 // been appended yet. 331 Maybe<media::TimeUnit> mLastFrameDuration; 332 // Highest end timestamp variable that stores the highest coded frame end 333 // timestamp across all coded frames in the current coded frame group that 334 // were appended to this track buffer. 335 // The variable is initially unset to indicate that no coded frames have 336 // been appended yet. 337 Maybe<media::TimeUnit> mHighestEndTimestamp; 338 // Highest presentation timestamp in track buffer. 339 // Protected by global monitor, except when reading on the task queue as it 340 // is only written there. 341 media::TimeUnit mHighestStartTimestamp; 342 // Longest frame duration seen since last random access point. 343 // Only ever accessed when mLastDecodeTimestamp and mLastFrameDuration are 344 // set. 345 media::TimeUnit mLongestFrameDuration; 346 // Need random access point flag variable that keeps track of whether the 347 // track buffer is waiting for a random access point coded frame. 348 // The variable is initially set to true to indicate that random access 349 // point coded frame is needed before anything can be added to the track 350 // buffer. 351 bool mNeedRandomAccessPoint; 352 RefPtr<MediaTrackDemuxer> mDemuxer; 353 MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest; 354 // Highest end timestamp of the last media segment demuxed. 355 media::TimeUnit mLastParsedEndTime; 356 357 // If set, position where the next contiguous frame will be inserted. 358 // If a discontinuity is detected, it will be unset and recalculated upon 359 // the next insertion. 360 Maybe<uint32_t> mNextInsertionIndex; 361 // Samples just demuxed, but not yet parsed. 362 TrackBuffer mQueuedSamples; 363 const TrackBuffer& GetTrackBuffer() const { 364 MOZ_RELEASE_ASSERT(mBuffers.Length(), 365 "TrackBuffer must have been created"); 366 return mBuffers.LastElement(); 367 } 368 TrackBuffer& GetTrackBuffer() { 369 MOZ_RELEASE_ASSERT(mBuffers.Length(), 370 "TrackBuffer must have been created"); 371 return mBuffers.LastElement(); 372 } 373 // We only manage a single track of each type at this time. 374 nsTArray<TrackBuffer> mBuffers; 375 // Track buffer ranges variable that represents the presentation time ranges 376 // occupied by the coded frames currently stored in the track buffer. 377 media::TimeIntervals mBufferedRanges; 378 // Sanitized mBufferedRanges with a fuzz of half a sample's duration applied 379 // This buffered ranges is the basis of what is exposed to the JS. 380 media::TimeIntervals mSanitizedBufferedRanges; 381 // Byte size of all samples contained in this track buffer. 382 uint32_t mSizeBuffer; 383 // TrackInfo of the first metadata received. 384 RefPtr<TrackInfoSharedPtr> mInfo; 385 // TrackInfo of the last metadata parsed (updated with each init segment. 386 RefPtr<TrackInfoSharedPtr> mLastInfo; 387 388 // If set, position of the next sample to be retrieved by GetSample(). 389 // If the position is equal to the TrackBuffer's length, it indicates that 390 // we've reached EOS. 391 Maybe<uint32_t> mNextGetSampleIndex; 392 // Approximation of the next sample's decode timestamp. 393 media::TimeUnit mNextSampleTimecode; 394 // Approximation of the next sample's presentation timestamp. 395 media::TimeUnit mNextSampleTime; 396 397 struct EvictionIndex { 398 EvictionIndex() { Reset(); } 399 void Reset() { 400 mEvictable = 0; 401 mLastIndex = 0; 402 } 403 uint32_t mEvictable = 0; 404 uint32_t mLastIndex = 0; 405 }; 406 // Size of data that can be safely evicted during the next eviction 407 // cycle. 408 // We consider as evictable all frames up to the last keyframe prior to 409 // mNextGetSampleIndex. If mNextGetSampleIndex isn't set, then we assume 410 // that we can't yet evict data. 411 // Protected by global monitor, except when reading on the task queue as it 412 // is only written there. 413 EvictionIndex mEvictionIndex; 414 415 void ResetAppendState() { 416 mLastDecodeTimestamp.reset(); 417 mLastFrameDuration.reset(); 418 mHighestEndTimestamp.reset(); 419 mNeedRandomAccessPoint = true; 420 mNextInsertionIndex.reset(); 421 } 422 423 void Reset() { 424 ResetAppendState(); 425 mEvictionIndex.Reset(); 426 for (auto& buffer : mBuffers) { 427 buffer.Clear(); 428 } 429 mSizeBuffer = 0; 430 mNextGetSampleIndex.reset(); 431 mBufferedRanges.Clear(); 432 mSanitizedBufferedRanges.Clear(); 433 } 434 435 void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const; 436 }; 437 438 void CheckSequenceDiscontinuity(const media::TimeUnit& aPresentationTime) 439 MOZ_REQUIRES(mTaskQueueCapability); 440 void ProcessFrames(TrackBuffer& aSamples, TrackData& aTrackData) 441 MOZ_REQUIRES(mTaskQueueCapability); 442 media::TimeInterval PresentationInterval(const TrackBuffer& aSamples) const 443 MOZ_REQUIRES(mTaskQueueCapability); 444 bool CheckNextInsertionIndex(TrackData& aTrackData, 445 const media::TimeUnit& aSampleTime) 446 MOZ_REQUIRES(mTaskQueueCapability); 447 void InsertFrames(TrackBuffer& aSamples, 448 const media::TimeIntervals& aIntervals, 449 TrackData& aTrackData) MOZ_REQUIRES(mTaskQueueCapability); 450 void UpdateHighestTimestamp(TrackData& aTrackData, 451 const media::TimeUnit& aHighestTime) 452 MOZ_REQUIRES(mTaskQueueCapability); 453 // Remove all frames and their dependencies contained in aIntervals. 454 // Return the index at which frames were first removed or 0 if no frames 455 // removed. 456 enum class RemovalMode { 457 kRemoveFrame, 458 kTruncateFrame, 459 }; 460 uint32_t RemoveFrames(const media::TimeIntervals& aIntervals, 461 TrackData& aTrackData, uint32_t aStartIndex, 462 RemovalMode aMode); 463 // Recalculate track's evictable amount. 464 void ResetEvictionIndex(TrackData& aTrackData); 465 void UpdateEvictionIndex(TrackData& aTrackData, uint32_t aCurrentIndex); 466 // Find index of sample. Return a negative value if not found. 467 uint32_t FindSampleIndex(const TrackBuffer& aTrackBuffer, 468 const media::TimeInterval& aInterval); 469 const MediaRawData* GetSample(TrackInfo::TrackType aTrack, uint32_t aIndex, 470 const media::TimeUnit& aExpectedDts, 471 const media::TimeUnit& aExpectedPts, 472 const media::TimeUnit& aFuzz); 473 void UpdateBufferedRanges(); 474 void RejectProcessing(const MediaResult& aRejectValue, const char* aName); 475 void ResolveProcessing(bool aResolveValue, const char* aName); 476 MozPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest; 477 MozPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise; 478 479 // Trackbuffers definition. 480 nsTArray<const TrackData*> GetTracksList() const; 481 nsTArray<TrackData*> GetTracksList(); 482 TrackData& GetTracksData(TrackType aTrack) { 483 switch (aTrack) { 484 case TrackType::kVideoTrack: 485 return mVideoTracks; 486 case TrackType::kAudioTrack: 487 default: 488 return mAudioTracks; 489 } 490 } 491 const TrackData& GetTracksData(TrackType aTrack) const { 492 switch (aTrack) { 493 case TrackType::kVideoTrack: 494 return mVideoTracks; 495 case TrackType::kAudioTrack: 496 default: 497 return mAudioTracks; 498 } 499 } 500 TrackData mVideoTracks; 501 TrackData mAudioTracks; 502 503 // TaskQueue methods and objects. 504 RefPtr<TaskQueue> GetTaskQueueSafe() const { 505 MutexAutoLock mut(mMutex); 506 return mTaskQueue; 507 } 508 NotNull<AbstractThread*> TaskQueueFromTaskQueue() const { 509 #ifdef DEBUG 510 RefPtr<TaskQueue> taskQueue = GetTaskQueueSafe(); 511 MOZ_ASSERT(taskQueue && taskQueue->IsCurrentThreadIn()); 512 #endif 513 return WrapNotNull(mTaskQueue.get()); 514 } 515 bool OnTaskQueue() const { 516 auto taskQueue = TaskQueueFromTaskQueue(); 517 return taskQueue->IsCurrentThreadIn(); 518 } 519 void ResetTaskQueue() { 520 MutexAutoLock mut(mMutex); 521 mTaskQueue = nullptr; 522 } 523 524 // SourceBuffer Queues and running context. 525 SourceBufferTaskQueue mQueue; 526 void QueueTask(SourceBufferTask* aTask); 527 void ProcessTasks(); 528 // Set if the TrackBuffersManager is currently processing a task. 529 // At this stage, this task is always a AppendBufferTask. 530 RefPtr<SourceBufferTask> mCurrentTask MOZ_GUARDED_BY(mTaskQueueCapability); 531 // Current SourceBuffer state for ongoing task. 532 // Its content is returned to the SourceBuffer once the AppendBufferTask has 533 // completed. 534 UniquePtr<SourceBufferAttributes> mSourceBufferAttributes 535 MOZ_GUARDED_BY(mTaskQueueCapability); 536 // The current sourcebuffer append window. It's content is equivalent to 537 // mSourceBufferAttributes.mAppendWindowStart/End 538 media::Interval<double> mAppendWindow MOZ_GUARDED_BY(mTaskQueueCapability); 539 540 // Strong references to external objects. 541 nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder; 542 543 const RefPtr<AbstractThread> mAbstractMainThread; 544 545 // Return public highest end time across all aTracks. 546 // Monitor must be held. 547 media::TimeUnit HighestEndTime( 548 nsTArray<const media::TimeIntervals*>& aTracks) const; 549 550 // true if endOfStream() has been called without error. 551 Atomic<bool> mHaveAllData{false}; 552 553 // Global size of this source buffer content. 554 Atomic<int64_t> mSizeSourceBuffer; 555 const int64_t mVideoEvictionThreshold; 556 const int64_t mAudioEvictionThreshold; 557 // A ratio of buffer fullness that we use for the auto eviction, 558 const double mEvictionBufferWatermarkRatio; 559 enum class EvictionState { 560 NO_EVICTION_NEEDED, 561 EVICTION_NEEDED, 562 EVICTION_COMPLETED, 563 }; 564 Atomic<EvictionState> mEvictionState; 565 566 // Monitor to protect following objects accessed across multiple threads. 567 mutable Mutex mMutex MOZ_UNANNOTATED; 568 // mTaskQueue is only ever written after construction on the task queue. 569 // As such, it can be accessed while on task queue without the need for the 570 // mutex. 571 RefPtr<TaskQueue> mTaskQueue; 572 // Stable audio and video track time ranges. 573 media::TimeIntervals mVideoBufferedRanges; 574 media::TimeIntervals mAudioBufferedRanges; 575 // MediaInfo of the first init segment read. 576 MediaInfo mInfo; 577 // Set to true if MediaSource readyState has changed to ended. 578 bool mEnded MOZ_GUARDED_BY(mMutex) = false; 579 // End mutex protected members. 580 581 // EventTargetCapability used to ensure we're running on the task queue 582 // as expected for various accesses. 583 // TODO: we could store only this and dispatch to it, rather than also having 584 // mTaskQueue. However, there's special locking around mTaskQueue, so we keep 585 // both for now. 586 Maybe<EventTargetCapability<TaskQueue>> mTaskQueueCapability; 587 588 Maybe<media::TimeUnit> mFrameEndTimeBeforeRecreateDemuxer; 589 }; 590 591 } // namespace mozilla 592 593 #endif /* MOZILLA_TRACKBUFFERSMANAGER_H_ */