changeset 1676:5e76d5e8167a

limit the amount of frames to be prefetched
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 23 Nov 2020 18:49:42 +0100
parents 6fa05252b085
children 51bab5188a13
files Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp
diffstat 1 files changed, 28 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Mon Nov 23 18:09:14 2020 +0100
+++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp	Mon Nov 23 18:49:42 2020 +0100
@@ -1227,7 +1227,7 @@
 
       assert(converted.get() != NULL);
       GetViewport().RenderCurrentSceneFromCommand(*converted, sopInstanceUid_, frameNumber_, DisplayedFrameQuality_Low);
-      GetViewport().cache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG);
+      GetViewport().framesCache_->Acquire(sopInstanceUid_, frameNumber_, converted.release(), QUALITY_JPEG);
 
       if (isPrefetch_)
       {
@@ -1320,7 +1320,7 @@
 
       assert(converted.get() != NULL);
       viewport.RenderCurrentSceneFromCommand(*converted, sopInstanceUid, frameNumber, DisplayedFrameQuality_High);
-      viewport.cache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL);
+      viewport.framesCache_->Acquire(sopInstanceUid, frameNumber, converted.release(), QUALITY_FULL);
     }
   };
 
@@ -1356,7 +1356,7 @@
   boost::shared_ptr<OrthancStone::WebAssemblyViewport>   viewport_;
   boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_;
   OrthancStone::DicomSource                    source_;
-  boost::shared_ptr<FramesCache>               cache_;  
+  boost::shared_ptr<FramesCache>               framesCache_;  
   std::unique_ptr<OrthancStone::SortedFrames>  frames_;
   std::unique_ptr<SeriesCursor>                cursor_;
   float                                        windowingCenter_;
@@ -1390,7 +1390,7 @@
       unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex);
 
       {
-        FramesCache::Accessor accessor(*cache_, sopInstanceUid, frameNumber);
+        FramesCache::Accessor accessor(*framesCache_, sopInstanceUid, frameNumber);
         if (!accessor.IsValid() ||
             (isFullQuality && accessor.GetQuality() == 0))
         {
@@ -1453,21 +1453,31 @@
   }
 
 
-  void SetupPrefetchAfterRendering(DisplayedFrameQuality quality)
+  /**
+   * NB: "frame" is only used to estimate the memory size to store 1
+   * frame, in order to avoid prefetching too much data.
+   **/
+  void SetupPrefetchAfterRendering(const Orthanc::ImageAccessor& frame,
+                                   DisplayedFrameQuality quality)
   {
+    const size_t frameSize = frame.GetPitch() * frame.GetHeight();
     const size_t cursorIndex = cursor_->GetCurrentIndex();
 
     // Prepare prefetching
     prefetchQueue_.clear();
 
-    if (1)  // TODO - DISABLE PREFETCHING
+    size_t prefetchedSize = 0;
+    
+    if (1)  // DISABLE PREFETCHING
     {
-      for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16; i++)
+      for (size_t i = 0; i < cursor_->GetPrefetchSize() && i < 16 &&
+             prefetchedSize <= framesCache_->GetMaximumSize() / 2; i++)
       {
         size_t a = cursor_->GetPrefetchIndex(i);
         if (a != cursorIndex)
         {
           prefetchQueue_.push_back(PrefetchItem(a, i < 2));
+          prefetchedSize += frameSize;
         }
       }
     }
@@ -1593,19 +1603,19 @@
         
         if (quality == DisplayedFrameQuality_Low)
         {
-          FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber);
+          FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber);
           if (accessor.IsValid() &&
               accessor.GetQuality() == QUALITY_FULL)
           {
             // A high-res image was downloaded in between: Use this cached image instead of the low-res
             RenderCurrentScene(accessor.GetImage(), instance, plane);
-            SetupPrefetchAfterRendering(DisplayedFrameQuality_High);
+            SetupPrefetchAfterRendering(frame, DisplayedFrameQuality_High);
           }
           else
           {
             // This frame is only available in low-res: Download the full DICOM
             RenderCurrentScene(frame, instance, plane);
-            SetupPrefetchAfterRendering(quality);
+            SetupPrefetchAfterRendering(frame, quality);
 
             /**
              * The command "SetupPrefetchAfterRendering()" must be
@@ -1621,7 +1631,7 @@
         else
         {
           assert(quality == DisplayedFrameQuality_High);
-          SetupPrefetchAfterRendering(quality);
+          SetupPrefetchAfterRendering(frame, quality);
           RenderCurrentScene(frame, instance, plane);
         }
       }
@@ -1744,7 +1754,7 @@
                  bool softwareRendering) :
     context_(context),
     source_(source),
-    cache_(cache),
+    framesCache_(cache),
     fitNextContent_(true),
     isCtrlDown_(false),
     flipX_(false),
@@ -1752,7 +1762,7 @@
     hasFocusOnInstance_(false),
     focusFrameNumber_(0)
   {
-    if (!cache_)
+    if (!framesCache_)
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
     }
@@ -1968,7 +1978,7 @@
       const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex);
       const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex);
 
-      FramesCache::Accessor accessor(*cache_, instance.GetSopInstanceUid(), frameNumber);
+      FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber);
       if (accessor.IsValid())
       {
         RenderCurrentScene(accessor.GetImage(), instance, frames_->GetFrameGeometry(cursorIndex));
@@ -1986,7 +1996,7 @@
           quality = DisplayedFrameQuality_High;
         }
 
-        SetupPrefetchAfterRendering(quality);
+        SetupPrefetchAfterRendering(accessor.GetImage(), quality);
       }
       else
       {
@@ -2467,7 +2477,7 @@
 
 
 static OrthancStone::DicomSource source_;
-static boost::shared_ptr<FramesCache> cache_;
+static boost::shared_ptr<FramesCache> framesCache_;
 static boost::shared_ptr<OrthancStone::WebAssemblyLoadersContext> context_;
 static std::string stringBuffer_;
 static bool softwareRendering_ = false;
@@ -2517,7 +2527,7 @@
   if (found == allViewports_.end())
   {
     boost::shared_ptr<ViewerViewport> viewport(
-      ViewerViewport::Create(*context_, source_, canvas, cache_, softwareRendering_));
+      ViewerViewport::Create(*context_, source_, canvas, framesCache_, softwareRendering_));
     viewport->SetMouseButtonActions(leftButtonAction_, middleButtonAction_, rightButtonAction_);
     viewport->AcquireObserver(new WebAssemblyObserver);
     viewport->SetAnnotations(annotations_);
@@ -2543,7 +2553,7 @@
     context_.reset(new OrthancStone::WebAssemblyLoadersContext(1, 4, 1));
     context_->SetDicomCacheSize(128 * 1024 * 1024);  // 128MB
     
-    cache_.reset(new FramesCache);
+    framesCache_.reset(new FramesCache);
     annotations_.reset(new OrthancStone::OsiriX::CollectionOfAnnotations);
     
     DISPATCH_JAVASCRIPT_EVENT("StoneInitialized");