SourceBufferList.cpp (5844B)
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 #include "SourceBufferList.h" 8 9 #include "AsyncEventRunner.h" 10 #include "mozilla/ErrorResult.h" 11 #include "mozilla/Logging.h" 12 #include "mozilla/dom/SourceBufferListBinding.h" 13 #include "mozilla/mozalloc.h" 14 #include "nsCOMPtr.h" 15 #include "nsIRunnable.h" 16 #include "nsString.h" 17 #include "nsThreadUtils.h" 18 19 extern mozilla::LogModule* GetMediaSourceLog(); 20 extern mozilla::LogModule* GetMediaSourceAPILog(); 21 22 #define MSE_API(arg, ...) \ 23 MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, \ 24 ("SourceBufferList(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 25 #define MSE_DEBUG(arg, ...) \ 26 MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, \ 27 ("SourceBufferList(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 28 29 struct JSContext; 30 class JSObject; 31 32 using TimeUnit = mozilla::media::TimeUnit; 33 34 namespace mozilla::dom { 35 36 SourceBufferList::~SourceBufferList() = default; 37 38 SourceBuffer* SourceBufferList::IndexedGetter(uint32_t aIndex, bool& aFound) { 39 MOZ_ASSERT(NS_IsMainThread()); 40 aFound = aIndex < mSourceBuffers.Length(); 41 42 if (!aFound) { 43 return nullptr; 44 } 45 return mSourceBuffers[aIndex]; 46 } 47 48 uint32_t SourceBufferList::Length() { 49 MOZ_ASSERT(NS_IsMainThread()); 50 return mSourceBuffers.Length(); 51 } 52 53 void SourceBufferList::Append(SourceBuffer* aSourceBuffer) { 54 MOZ_ASSERT(NS_IsMainThread()); 55 mSourceBuffers.AppendElement(aSourceBuffer); 56 QueueAsyncSimpleEvent("addsourcebuffer"); 57 } 58 59 void SourceBufferList::AppendSimple(SourceBuffer* aSourceBuffer) { 60 MOZ_ASSERT(NS_IsMainThread()); 61 mSourceBuffers.AppendElement(aSourceBuffer); 62 } 63 64 void SourceBufferList::Remove(SourceBuffer* aSourceBuffer) { 65 MOZ_ASSERT(NS_IsMainThread()); 66 MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer)); 67 aSourceBuffer->Detach(); 68 QueueAsyncSimpleEvent("removesourcebuffer"); 69 } 70 71 bool SourceBufferList::Contains(SourceBuffer* aSourceBuffer) { 72 MOZ_ASSERT(NS_IsMainThread()); 73 return mSourceBuffers.Contains(aSourceBuffer); 74 } 75 76 void SourceBufferList::Clear() { 77 MOZ_ASSERT(NS_IsMainThread()); 78 for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { 79 mSourceBuffers[i]->Detach(); 80 } 81 mSourceBuffers.Clear(); 82 QueueAsyncSimpleEvent("removesourcebuffer"); 83 } 84 85 void SourceBufferList::ClearSimple() { 86 MOZ_ASSERT(NS_IsMainThread()); 87 mSourceBuffers.Clear(); 88 } 89 90 bool SourceBufferList::IsEmpty() { 91 MOZ_ASSERT(NS_IsMainThread()); 92 return mSourceBuffers.IsEmpty(); 93 } 94 95 bool SourceBufferList::AnyUpdating() { 96 MOZ_ASSERT(NS_IsMainThread()); 97 for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { 98 if (mSourceBuffers[i]->Updating()) { 99 return true; 100 } 101 } 102 return false; 103 } 104 105 void SourceBufferList::RangeRemoval(double aStart, double aEnd) { 106 MOZ_ASSERT(NS_IsMainThread()); 107 MSE_DEBUG("RangeRemoval(aStart=%f, aEnd=%f)", aStart, aEnd); 108 for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { 109 mSourceBuffers[i]->RangeRemoval(aStart, aEnd); 110 } 111 } 112 113 void SourceBufferList::SetEnded( 114 const Optional<MediaSourceEndOfStreamError>& aError) { 115 MOZ_ASSERT(NS_IsMainThread()); 116 for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { 117 mSourceBuffers[i]->SetEnded(aError); 118 } 119 } 120 121 TimeUnit SourceBufferList::GetHighestBufferedEndTime() { 122 MOZ_ASSERT(NS_IsMainThread()); 123 TimeUnit highestEndTime = TimeUnit::Zero(); 124 for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { 125 highestEndTime = 126 std::max(highestEndTime, mSourceBuffers[i]->GetBufferedEnd()); 127 } 128 return highestEndTime; 129 } 130 131 void SourceBufferList::DispatchSimpleEvent(const char* aName) { 132 MOZ_ASSERT(NS_IsMainThread()); 133 MSE_API("Dispatch event '%s'", aName); 134 DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName)); 135 } 136 137 void SourceBufferList::QueueAsyncSimpleEvent(const char* aName) { 138 MSE_DEBUG("Queue event '%s'", aName); 139 nsCOMPtr<nsIRunnable> event = 140 new AsyncEventRunner<SourceBufferList>(this, aName); 141 mAbstractMainThread->Dispatch(event.forget()); 142 } 143 144 SourceBufferList::SourceBufferList(MediaSource* aMediaSource) 145 : DOMEventTargetHelper(aMediaSource->GetParentObject()), 146 mMediaSource(aMediaSource), 147 mAbstractMainThread(mMediaSource->AbstractMainThread()) { 148 MOZ_ASSERT(aMediaSource); 149 } 150 151 MediaSource* SourceBufferList::GetParentObject() const { return mMediaSource; } 152 153 TimeUnit SourceBufferList::HighestStartTime() { 154 MOZ_ASSERT(NS_IsMainThread()); 155 TimeUnit highestStartTime = TimeUnit::Zero(); 156 for (auto& sourceBuffer : mSourceBuffers) { 157 highestStartTime = 158 std::max(sourceBuffer->HighestStartTime(), highestStartTime); 159 } 160 return highestStartTime; 161 } 162 163 TimeUnit SourceBufferList::HighestEndTime() { 164 MOZ_ASSERT(NS_IsMainThread()); 165 TimeUnit highestEndTime = TimeUnit::Zero(); 166 for (auto& sourceBuffer : mSourceBuffers) { 167 highestEndTime = std::max(sourceBuffer->HighestEndTime(), highestEndTime); 168 } 169 return highestEndTime; 170 } 171 172 JSObject* SourceBufferList::WrapObject(JSContext* aCx, 173 JS::Handle<JSObject*> aGivenProto) { 174 return SourceBufferList_Binding::Wrap(aCx, this, aGivenProto); 175 } 176 177 NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBufferList, DOMEventTargetHelper, 178 mMediaSource, mSourceBuffers) 179 180 NS_IMPL_ADDREF_INHERITED(SourceBufferList, DOMEventTargetHelper) 181 NS_IMPL_RELEASE_INHERITED(SourceBufferList, DOMEventTargetHelper) 182 183 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SourceBufferList) 184 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) 185 186 #undef MSE_API 187 #undef MSE_DEBUG 188 } // namespace mozilla::dom