changeset 635:b892d390e6b4

use /file?transcode=... to benefit from Orthanc 1.12.2 StorageCache
author Alain Mazy <am@osimis.io>
date Thu, 16 Nov 2023 16:11:58 +0100
parents d78c4b632ed3
children c1e941efd4f4 bb3cf87fffb6
files NEWS Plugin/Plugin.cpp Plugin/WadoRs.h Plugin/WadoRsRetrieveFrames.cpp
diffstat 4 files changed, 68 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Nov 14 11:35:14 2023 +0100
+++ b/NEWS	Thu Nov 16 16:11:58 2023 +0100
@@ -4,7 +4,7 @@
 * Removed misleading log messages about transcoding.
   https://discourse.orthanc-server.org/t/dicomweb-plugin-1-13-possible-unnecessary-transcoding/3979
 * Fix parsing of Accept header "multipart/related; type=application/octet-stream; transfer-syntax=*" that is used by OHIF.
-
+* When retrieving frames, WADO-RS may now retrieve transcoded instances from Orthanc StorageCache (for Orthanc >= 1.12.2)
 
 Version 1.15 (2023-08-24)
 =========================
--- a/Plugin/Plugin.cpp	Tue Nov 14 11:35:14 2023 +0100
+++ b/Plugin/Plugin.cpp	Thu Nov 16 16:11:58 2023 +0100
@@ -536,6 +536,8 @@
       return -1;
     }
 
+    SetPluginCanDownloadTranscodedFile(OrthancPlugins::CheckMinimalOrthancVersion(1, 12, 2));
+
 #if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_CLIENT == 0
     LOG(WARNING) << "Performance warning in DICOMweb: The plugin was compiled against "
                  << "Orthanc SDK <= 1.5.6. STOW and WADO chunked transfers will be entirely stored in RAM.";
--- a/Plugin/WadoRs.h	Tue Nov 14 11:35:14 2023 +0100
+++ b/Plugin/WadoRs.h	Thu Nov 16 16:11:58 2023 +0100
@@ -100,3 +100,5 @@
 void RetrieveStudyRendered(OrthancPluginRestOutput* output,
                            const char* url,
                            const OrthancPluginHttpRequest* request);
+
+void SetPluginCanDownloadTranscodedFile(bool enable);
\ No newline at end of file
--- a/Plugin/WadoRsRetrieveFrames.cpp	Tue Nov 14 11:35:14 2023 +0100
+++ b/Plugin/WadoRsRetrieveFrames.cpp	Thu Nov 16 16:11:58 2023 +0100
@@ -31,6 +31,8 @@
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/lexical_cast.hpp>
 
+static bool pluginCanDownloadTranscodedFile = false;
+
 
 static void TokenizeAndNormalize(std::vector<std::string>& tokens,
                                  const std::string& source,
@@ -426,44 +428,74 @@
                            std::list<unsigned int>& frames)
 {
   std::string orthancId, studyInstanceUid, seriesInstanceUid, sopInstanceUid;
-  OrthancPlugins::MemoryBuffer content;
-  if (LocateInstance(output, orthancId, studyInstanceUid, seriesInstanceUid, sopInstanceUid, request) &&
-      content.RestApiGet("/instances/" + orthancId + "/file", false))
+  if (LocateInstance(output, orthancId, studyInstanceUid, seriesInstanceUid, sopInstanceUid, request))
   {
-    if (allFrames)
-    {
-      OrthancPlugins::LogInfo("DICOMweb RetrieveFrames on " + orthancId + ", all frames");
+    OrthancPlugins::MemoryBuffer content;
+    Orthanc::DicomTransferSyntax currentSyntax;
+    std::unique_ptr<OrthancPlugins::DicomInstance> instance;
+
+    { // logging only
+      if (allFrames)
+      {
+        OrthancPlugins::LogInfo("DICOMweb RetrieveFrames on " + orthancId + ", all frames");
+      }
+      else
+      {
+        std::string s = "DICOMweb RetrieveFrames on " + orthancId + ", frames: ";
+        for (std::list<unsigned int>::const_iterator 
+              frame = frames.begin(); frame != frames.end(); ++frame)
+        {
+          s += boost::lexical_cast<std::string>(*frame + 1) + " ";
+        }
+
+        OrthancPlugins::LogInfo(s);
+      }
     }
-    else
+
+    std::string currentSyntaxString;
+    if (!OrthancPlugins::RestApiGetString(currentSyntaxString, "/instances/" + orthancId + "/metadata/TransferSyntax", false))
     {
-      std::string s = "DICOMweb RetrieveFrames on " + orthancId + ", frames: ";
-      for (std::list<unsigned int>::const_iterator 
-             frame = frames.begin(); frame != frames.end(); ++frame)
-      {
-        s += boost::lexical_cast<std::string>(*frame + 1) + " ";
-      }
-
-      OrthancPlugins::LogInfo(s);
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "DICOMWeb: Unable to get TransferSyntax for instance " + orthancId);
     }
 
-    Orthanc::DicomTransferSyntax currentSyntax;
+    if (!Orthanc::LookupTransferSyntax(currentSyntax, currentSyntaxString))
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, "Unknown transfer syntax: " + currentSyntaxString);
+    }
 
-    std::unique_ptr<OrthancPlugins::DicomInstance> instance(new OrthancPlugins::DicomInstance(content.GetData(), content.GetSize()));
-    if (!Orthanc::LookupTransferSyntax(currentSyntax, instance->GetTransferSyntaxUid()))
+    Orthanc::DicomTransferSyntax targetSyntax = currentSyntax;  
+    bool transcodeThisInstance = false;
+    
+    if (ParseTransferSyntax(targetSyntax, request))
     {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented,
-                                      "Unknown transfer syntax: " + std::string(GetTransferSyntaxUid(currentSyntax)));
+      transcodeThisInstance = targetSyntax != currentSyntax;
     }
 
-    Orthanc::DicomTransferSyntax targetSyntax = currentSyntax;
-
-    if (ParseTransferSyntax(targetSyntax, request) && targetSyntax != currentSyntax)
+    // maximize the use the Orthanc storage cache.  Since 1.12.2, transcoded file may be stored in the storage cache
+    if (pluginCanDownloadTranscodedFile && transcodeThisInstance)
+    {
+      if (!content.RestApiGet("/instances/" + orthancId + "/file?transcode=" + Orthanc::GetTransferSyntaxUid(targetSyntax), false))
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "DICOMWeb: Unable to get transcoded file for for instance " + orthancId);
+      }
+      instance.reset(new OrthancPlugins::DicomInstance(content.GetData(), content.GetSize()));
+    }
+    else // pre 1.12.2 code (or no transcoding needed)
     {
-      OrthancPlugins::LogInfo("DICOMweb RetrieveFrames: Transcoding instance " + orthancId + 
-                              " to transfer syntax " + Orthanc::GetTransferSyntaxUid(targetSyntax));
+      if (!content.RestApiGet("/instances/" + orthancId + "/file", false))
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "DICOMWeb: Unable to get file for for instance " + orthancId);
+      }
+      instance.reset(new OrthancPlugins::DicomInstance(content.GetData(), content.GetSize()));
 
-      instance.reset(OrthancPlugins::DicomInstance::Transcode(
+      if (transcodeThisInstance)
+      {
+        OrthancPlugins::LogInfo("DICOMweb RetrieveFrames: Transcoding instance " + orthancId + 
+                                " to transfer syntax " + Orthanc::GetTransferSyntaxUid(targetSyntax));
+
+        instance.reset(OrthancPlugins::DicomInstance::Transcode(
                        content.GetData(), content.GetSize(), GetTransferSyntaxUid(targetSyntax)));
+      }
     }
 
     if (instance.get() == NULL)
@@ -503,3 +535,8 @@
   ParseFrameList(frames, request);
   RetrieveFrames(output, request, false, frames);
 }
+
+void SetPluginCanDownloadTranscodedFile(bool enable)
+{
+  pluginCanDownloadTranscodedFile = enable;
+}
\ No newline at end of file