# HG changeset patch # User Alain Mazy # Date 1669118050 -3600 # Node ID a386dfb5b386041d341ae912042d2b65f1ea14b8 # Parent 43461cc998387a18b0182040b84066159e3fc521 Optimization: now using multiple threads to transcode files for asynchronous download of studies archive diff -r 43461cc99838 -r a386dfb5b386 NEWS --- a/NEWS Mon Nov 21 09:07:12 2022 +0100 +++ b/NEWS Tue Nov 22 12:54:10 2022 +0100 @@ -8,6 +8,7 @@ instead of Orthanc own AcceptedTransferSyntaxes. * Made the default SQLite DB more robust wrt future updates like adding new columns in DB. * Made the HTTP Client errors more verbose by including the url in the logs. +* Optimization: now using multiple threads to transcode files for asynchronous download of studies archive. REST API -------- diff -r 43461cc99838 -r a386dfb5b386 OrthancServer/Sources/ServerJobs/ArchiveJob.cpp --- a/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp Mon Nov 21 09:07:12 2022 +0100 +++ b/OrthancServer/Sources/ServerJobs/ArchiveJob.cpp Tue Nov 22 12:54:10 2022 +0100 @@ -82,9 +82,13 @@ { protected: ServerContext& context_; + bool transcode_; + DicomTransferSyntax transferSyntax_; public: - explicit InstanceLoader(ServerContext& context) - : context_(context) + explicit InstanceLoader(ServerContext& context, bool transcode, DicomTransferSyntax transferSyntax) + : context_(context), + transcode_(transcode), + transferSyntax_(transferSyntax) { } @@ -94,7 +98,31 @@ virtual void PrepareDicom(const std::string& instanceId) { + } + bool TranscodeDicom(std::string& transcodedBuffer, const std::string& sourceBuffer, const std::string& instanceId) + { + if (transcode_) + { + std::set syntaxes; + syntaxes.insert(transferSyntax_); + + IDicomTranscoder::DicomImage source, transcoded; + source.SetExternalBuffer(sourceBuffer); + + if (context_.Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */)) + { + transcodedBuffer.assign(reinterpret_cast(transcoded.GetBufferData()), transcoded.GetBufferSize()); + return true; + } + else + { + LOG(INFO) << "Cannot transcode instance " << instanceId + << " to transfer syntax: " << GetTransferSyntaxUid(transferSyntax_); + } + } + + return false; } virtual void GetDicom(std::string& dicom, const std::string& instanceId) = 0; @@ -107,14 +135,24 @@ class ArchiveJob::SynchronousInstanceLoader : public ArchiveJob::InstanceLoader { public: - explicit SynchronousInstanceLoader(ServerContext& context) - : InstanceLoader(context) + explicit SynchronousInstanceLoader(ServerContext& context, bool transcode, DicomTransferSyntax transferSyntax) + : InstanceLoader(context, transcode, transferSyntax) { } virtual void GetDicom(std::string& dicom, const std::string& instanceId) ORTHANC_OVERRIDE { context_.ReadDicom(dicom, instanceId); + + if (transcode_) + { + std::string transcoded; + if (TranscodeDicom(transcoded, dicom, instanceId)) + { + dicom.swap(transcoded); + } + } + } }; @@ -145,8 +183,8 @@ public: - ThreadedInstanceLoader(ServerContext& context, size_t threadCount) - : InstanceLoader(context), + ThreadedInstanceLoader(ServerContext& context, size_t threadCount, bool transcode, DicomTransferSyntax transferSyntax) + : InstanceLoader(context, transcode, transferSyntax), availableInstancesSemaphore_(0) { for (size_t i = 0; i < threadCount; i++) @@ -194,6 +232,16 @@ { boost::shared_ptr dicomContent(new std::string()); that->context_.ReadDicom(*dicomContent, instanceId->GetId()); + + if (that->transcode_) + { + boost::shared_ptr transcodedDicom(new std::string()); + if (that->TranscodeDicom(*transcodedDicom, *dicomContent, instanceId->GetId())) + { + dicomContent = transcodedDicom; + } + } + { boost::mutex::scoped_lock lock(that->availableInstancesMutex_); that->availableInstances_[instanceId->GetId()] = dicomContent; @@ -597,42 +645,12 @@ return; } - //boost::this_thread::sleep(boost::posix_time::milliseconds(300)); - writer.OpenFile(filename_.c_str()); bool transcodeSuccess = false; std::unique_ptr parsed; - if (transcode) - { - // New in Orthanc 1.7.0 - std::set syntaxes; - syntaxes.insert(transferSyntax); - - IDicomTranscoder::DicomImage source, transcoded; - source.SetExternalBuffer(content); - - if (context.Transcode(transcoded, source, syntaxes, true /* allow new SOP instance UID */)) - { - writer.Write(transcoded.GetBufferData(), transcoded.GetBufferSize()); - - if (dicomDir != NULL) - { - std::unique_ptr tmp(transcoded.ReleaseAsParsedDicomFile()); - dicomDir->Add(dicomDirFolder, filename_, *tmp); - } - - transcodeSuccess = true; - } - else - { - LOG(INFO) << "Cannot transcode instance " << instanceId_ - << " to transfer syntax: " << GetTransferSyntaxUid(transferSyntax); - } - } - if (!transcodeSuccess) { writer.Write(content); @@ -1195,11 +1213,11 @@ if (loaderThreads_ == 0) { // default behaviour before loaderThreads was introducted in 1.10.0 - instanceLoader_.reset(new SynchronousInstanceLoader(context_)); + instanceLoader_.reset(new SynchronousInstanceLoader(context_, transcode_, transferSyntax_)); } else { - instanceLoader_.reset(new ThreadedInstanceLoader(context_, loaderThreads_)); + instanceLoader_.reset(new ThreadedInstanceLoader(context_, loaderThreads_, transcode_, transferSyntax_)); } if (writer_.get() != NULL)