ImageTrackList.cpp (8145B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 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 "mozilla/dom/ImageTrackList.h" 8 9 #include "MediaResult.h" 10 #include "mozilla/dom/ImageDecoder.h" 11 #include "mozilla/dom/ImageTrack.h" 12 #include "mozilla/dom/Promise.h" 13 #include "mozilla/image/ImageUtils.h" 14 15 namespace mozilla::dom { 16 17 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ImageTrackList, mParent, mDecoder, 18 mReadyPromise, mTracks) 19 NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageTrackList) 20 NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageTrackList) 21 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageTrackList) 22 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 23 NS_INTERFACE_MAP_ENTRY(nsISupports) 24 NS_INTERFACE_MAP_END 25 26 ImageTrackList::ImageTrackList(nsIGlobalObject* aParent, ImageDecoder* aDecoder) 27 : mParent(aParent), mDecoder(aDecoder) {} 28 29 ImageTrackList::~ImageTrackList() = default; 30 31 JSObject* ImageTrackList::WrapObject(JSContext* aCx, 32 JS::Handle<JSObject*> aGivenProto) { 33 AssertIsOnOwningThread(); 34 return ImageTrackList_Binding::Wrap(aCx, this, aGivenProto); 35 } 36 37 void ImageTrackList::Initialize(ErrorResult& aRv) { 38 mReadyPromise = Promise::Create(mParent, aRv); 39 if (NS_WARN_IF(aRv.Failed())) { 40 return; 41 } 42 } 43 44 void ImageTrackList::Destroy() { 45 if (!mIsReady && mReadyPromise && mReadyPromise->PromiseObj()) { 46 mReadyPromise->MaybeRejectWithAbortError("ImageTrackList destroyed"); 47 mIsReady = true; 48 } 49 50 for (auto& track : mTracks) { 51 track->Destroy(); 52 } 53 mTracks.Clear(); 54 55 mDecoder = nullptr; 56 mSelectedIndex = -1; 57 } 58 59 void ImageTrackList::MaybeRejectReady(const MediaResult& aResult) { 60 if (mIsReady || !mReadyPromise || !mReadyPromise->PromiseObj()) { 61 return; 62 } 63 aResult.RejectTo(mReadyPromise); 64 mIsReady = true; 65 } 66 67 void ImageTrackList::OnMetadataSuccess( 68 const image::DecodeMetadataResult& aMetadata) { 69 // 10.2.5. Establish Tracks 70 // 71 // Note that our implementation only supports one track, so many of these 72 // steps are simplified. 73 74 // 4. Let newTrackList be a new list. 75 MOZ_ASSERT(mTracks.IsEmpty()); 76 77 // Mozilla-internal-only addition 78 nsTArray<ImageSize> imageSizes; 79 for (const OrientedIntSize& nativeSize : aMetadata.mNativeSizes) { 80 ImageSize* imageSize = imageSizes.AppendElement(); 81 imageSize->mWidth = nativeSize.width; 82 imageSize->mHeight = nativeSize.height; 83 } 84 85 // 5. For each image track found in [[encoded data]]: 86 // 5.1. Let newTrack be a new ImageTrack, initialized as follows: 87 // 5.1.1. Assign this to [[ImageDecoder]]. 88 // 5.1.2. Assign tracks to [[ImageTrackList]]. 89 // 5.1.3. If image track is found to be animated, assign true to newTrack's 90 // [[animated]] internal slot. Otherwise, assign false. 91 // 5.1.4. If image track is found to describe a frame count, assign that 92 // count to newTrack's [[frame count]] internal slot. Otherwise, assign 93 // 0. 94 // 5.1.5. If image track is found to describe a repetition count, assign that 95 // count to [[repetition count]] internal slot. Otherwise, assign 0. 96 // 5.1.6. Assign false to newTrack’s [[selected]] internal slot. 97 // 5.2. Append newTrack to newTrackList. 98 // 6. Let selectedTrackIndex be the result of running the Get Default Selected 99 // Track Index algorithm with newTrackList. 100 // 7. Let selectedTrack be the track at position selectedTrackIndex within 101 // newTrackList. 102 // 8. Assign true to selectedTrack’s [[selected]] internal slot. 103 // 9. Assign selectedTrackIndex to [[internal selected track index]]. 104 const float repetitions = aMetadata.mRepetitions < 0 105 ? std::numeric_limits<float>::infinity() 106 : static_cast<float>(aMetadata.mRepetitions); 107 auto track = MakeRefPtr<ImageTrack>( 108 this, /* aIndex */ 0, std::move(imageSizes), /* aSelected */ true, 109 aMetadata.mAnimated, aMetadata.mFrameCount, aMetadata.mFrameCountComplete, 110 repetitions); 111 112 // 11. Queue a task to perform the following steps: 113 // 114 // Note that we were already dispatched by the image decoder. 115 116 // 11.1. Assign newTrackList to the tracks [[track list]] internal slot. 117 mTracks.AppendElement(std::move(track)); 118 119 // 11.2. Assign selectedTrackIndex to tracks [[selected index]]. 120 mSelectedIndex = 0; 121 122 // 11.3. Resolve [[ready promise]]. 123 MOZ_ASSERT(!mIsReady); 124 mReadyPromise->MaybeResolveWithUndefined(); 125 mIsReady = true; 126 } 127 128 void ImageTrackList::OnFrameCountSuccess( 129 const image::DecodeFrameCountResult& aResult) { 130 if (mTracks.IsEmpty()) { 131 return; 132 } 133 134 // 10.2.5. Update Tracks 135 // 136 // Note that we were already dispatched from the decoding threads. 137 138 // 3. Let trackList be a copy of tracks' [[track list]]. 139 // 4. For each track in trackList: 140 // 4.1. Let trackIndex be the position of track in trackList. 141 // 4.2. Let latestFrameCount be the frame count as indicated by 142 // [[encoded data]] for the track corresponding to track. 143 // 4.3. Assert that latestFrameCount is greater than or equal to 144 // track.frameCount. 145 // 4.4. If latestFrameCount is greater than track.frameCount: 146 // 4.4.1. Let change be a track update struct whose track index is trackIndex 147 // and frame count is latestFrameCount. 148 // 4.4.2. Append change to tracksChanges. 149 // 5. If tracksChanges is empty, abort these steps. 150 // 6. Queue a task to perform the following steps: 151 // 6.1. For each update in trackChanges: 152 // 6.1.1. Let updateTrack be the ImageTrack at position update.trackIndex 153 // within tracks' [[track list]]. 154 // 6.1.2. Assign update.frameCount to updateTrack’s [[frame count]]. 155 mTracks.LastElement()->OnFrameCountSuccess(aResult); 156 } 157 158 void ImageTrackList::SetSelectedIndex(int32_t aIndex, bool aSelected) { 159 MOZ_ASSERT(aIndex >= 0); 160 MOZ_ASSERT(uint32_t(aIndex) < mTracks.Length()); 161 162 // 10.7.2. Attributes - selected, of type boolean 163 164 // 1. If [[ImageDecoder]]'s [[closed]] slot is true, abort these steps. 165 if (!mDecoder) { 166 return; 167 } 168 169 // 2. Let newValue be the given value. 170 // 3. If newValue equals [[selected]], abort these steps. 171 // 4. Assign newValue to [[selected]]. 172 // 5. Let parentTrackList be [[ImageTrackList]] 173 // 6. Let oldSelectedIndex be the value of parentTrackList [[selected index]]. 174 // 7. If oldSelectedIndex is not -1: 175 // 7.1. Let oldSelectedTrack be the ImageTrack in parentTrackList 176 // [[track list]] at the position of oldSelectedIndex. 177 // 7.2. Assign false to oldSelectedTrack [[selected]] 178 // 8. If newValue is true, let selectedIndex be the index of this ImageTrack 179 // within parentTrackList's [[track list]]. Otherwise, let selectedIndex be 180 // -1. 181 // 9. Assign selectedIndex to parentTrackList [[selected index]]. 182 if (aSelected) { 183 if (mSelectedIndex == -1) { 184 MOZ_ASSERT(!mTracks[aIndex]->Selected()); 185 mTracks[aIndex]->MarkSelected(); 186 mSelectedIndex = aIndex; 187 } else if (mSelectedIndex != aIndex) { 188 MOZ_ASSERT(mTracks[mSelectedIndex]->Selected()); 189 MOZ_ASSERT(!mTracks[aIndex]->Selected()); 190 mTracks[mSelectedIndex]->ClearSelected(); 191 mTracks[aIndex]->MarkSelected(); 192 mSelectedIndex = aIndex; 193 } else { 194 MOZ_ASSERT(mTracks[mSelectedIndex]->Selected()); 195 return; 196 } 197 } else if (mSelectedIndex == aIndex) { 198 mTracks[mSelectedIndex]->ClearSelected(); 199 mSelectedIndex = -1; 200 } else { 201 MOZ_ASSERT(!mTracks[aIndex]->Selected()); 202 return; 203 } 204 205 // 10. Run the Reset ImageDecoder algorithm on [[ImageDecoder]]. 206 mDecoder->Reset(); 207 208 // 11. Queue a control message to [[ImageDecoder]]'s control message queue to 209 // update the internal selected track index with selectedIndex. 210 mDecoder->QueueSelectTrackMessage(mSelectedIndex); 211 212 // 12. Process the control message queue belonging to [[ImageDecoder]]. 213 mDecoder->ProcessControlMessageQueue(); 214 } 215 216 } // namespace mozilla::dom