tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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