From a3ee003efd32807cb313fa14a531fd4c2435396e Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@orfeo-toolbox.org> Date: Tue, 15 Nov 2011 10:15:56 +0100 Subject: [PATCH] ENH: One step toward parallel decoding (pre-sorting between tiles to decode and tiles from cache) --- Code/IO/otbJPEG2000ImageIO.cxx | 60 +++++++++++++++++++++++++--------- Code/IO/otbJPEG2000ImageIO.h | 11 +++++++ 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/Code/IO/otbJPEG2000ImageIO.cxx b/Code/IO/otbJPEG2000ImageIO.cxx index 6ec0cb7721..5d4c4ea1e4 100644 --- a/Code/IO/otbJPEG2000ImageIO.cxx +++ b/Code/IO/otbJPEG2000ImageIO.cxx @@ -629,7 +629,6 @@ void JPEG2000ImageIO::Read(void* buffer) } itkExceptionMacro(<< " IORegion is not correct in terme of tile!"); } - // Get nb. of lines and columns of the region to read int lNbLines = this->GetIORegion().GetSize()[1]; int lNbColumns = this->GetIORegion().GetSize()[0]; @@ -645,24 +644,50 @@ void JPEG2000ImageIO::Read(void* buffer) otbMsgDevMacro(<< "Component type: " << this->GetComponentTypeAsString(this->GetComponentType())); - // Decode tile need - for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); itTile++) + // Here we sort between tiles from cache and tiles to read + std::vector<JPEG2000TileCache::CachedTileType> cachedTiles; + std::vector<JPEG2000TileCache::CachedTileType> toReadTiles; + std::vector<JPEG2000TileCache::CachedTileType> allNeededTiles; + + for (std::vector<unsigned int>::iterator itTile = tileList.begin(); itTile < tileList.end(); ++itTile) + { + opj_image_t * currentImage = m_TileCache->GetTile(*itTile); + + JPEG2000TileCache::CachedTileType currentTile = std::make_pair((*itTile),currentImage); + + if(!currentImage) + { + toReadTiles.push_back(currentTile); + } + else + { + cachedTiles.push_back(currentTile); + } + } + + // Decode all tiles not in cache + for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile) { - opj_image_t * currentTile = m_TileCache->GetTile(*itTile); + // Call the reader + itTile->second = m_InternalReaders.front()->DecodeTile(itTile->first); - if(!currentTile) + // Check if tile is valid + if(!itTile->second) { - currentTile = m_InternalReaders.front()->DecodeTile(*itTile); - - if(!currentTile) - { - this->m_InternalReaders.front()->Clean(); - itkExceptionMacro(<< " otbopenjpeg failed to decode the desired tile "<< *itTile << "!"); - } - m_TileCache->AddTile((*itTile),currentTile); + this->m_InternalReaders.front()->Clean(); + itkExceptionMacro(<< " otbopenjpeg failed to decode the desired tile "<< itTile->first << "!"); } + otbMsgDevMacro(<< " Tile " << itTile->first << " is decoded."); + } - otbMsgDevMacro(<< " Tile " << *itTile << " is decoded."); + // Build the list of all tiles + allNeededTiles = cachedTiles; + allNeededTiles.insert(allNeededTiles.end(),toReadTiles.begin(),toReadTiles.end()); + + + for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = allNeededTiles.begin(); itTile < allNeededTiles.end(); ++itTile) + { + opj_image_t * currentTile = itTile->second; unsigned int lWidthSrc; // Width of the input pixel in nb of pixel unsigned int lHeightDest; // Height of the area where write in nb of pixel @@ -753,9 +778,14 @@ void JPEG2000ImageIO::Read(void* buffer) itkGenericExceptionMacro(<< "This data type is not handled"); break; } - } + + // Now, do cache book-keeping + for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile) + { + m_TileCache->AddTile(itTile->first,itTile->second); + } chrono.Stop(); otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec"); diff --git a/Code/IO/otbJPEG2000ImageIO.h b/Code/IO/otbJPEG2000ImageIO.h index ad2030d5d5..a81d999dcc 100644 --- a/Code/IO/otbJPEG2000ImageIO.h +++ b/Code/IO/otbJPEG2000ImageIO.h @@ -126,6 +126,17 @@ private: * (e.g., ImageSource). */ itk::MultiThreader::Pointer m_Threader; int m_NumberOfThreads; + + /** Static function used as a "callback" by the MultiThreader. The threading + * library will call this routine for each thread, which will delegate the + * control to ThreadedGenerateData(). */ + static ITK_THREAD_RETURN_TYPE ThreaderCallback( void *arg ); + + /** Internal structure used for passing image data into the threading library */ + struct ThreadStruct + { + Pointer Filter; + }; }; } // end namespace otb -- GitLab