Mercurial > hg > orthanc
changeset 5108:a386dfb5b386
Optimization: now using multiple threads to transcode files for asynchronous download of studies archive
author | Alain Mazy <am@osimis.io> |
---|---|
date | Tue, 22 Nov 2022 12:54:10 +0100 |
parents | 43461cc99838 |
children | 027366cae766 |
files | NEWS OrthancServer/Sources/ServerJobs/ArchiveJob.cpp |
diffstat | 2 files changed, 57 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- 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 --------
--- 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<DicomTransferSyntax> 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<const char*>(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<std::string> dicomContent(new std::string()); that->context_.ReadDicom(*dicomContent, instanceId->GetId()); + + if (that->transcode_) + { + boost::shared_ptr<std::string> 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<ParsedDicomFile> parsed; - if (transcode) - { - // New in Orthanc 1.7.0 - std::set<DicomTransferSyntax> 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<ParsedDicomFile> 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)