Skip to content

Commit

Permalink
Add freeBuffers() function to InputFile classes
Browse files Browse the repository at this point in the history
The idea here is to provide a way to get InputFile objects back to their
initial state after pixels have been read, which involves the allocating
of various memory buffers that usually aren't freed until the objects
are destroyed.  This can be useful if an application wants to keep an
object around for additional reading, but doesn't want unnecessary
memory overhead in the meantime.

Also provided is a bufferSize() function that the application might
use to determine if freeing the buffers is enough of a memory savings
to be worth the trouble.

Signed-off-by: Brendan Bolles <brendan@fnord.com>
  • Loading branch information
fnordware committed Sep 20, 2024
1 parent 04cc126 commit 2ca0bb2
Show file tree
Hide file tree
Showing 20 changed files with 424 additions and 55 deletions.
50 changes: 48 additions & 2 deletions src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ struct ScanLineProcess
const DeepFrameBuffer *outfb,
int fbY);

size_t get_buffer_size ()
{
return exr_decoding_get_buffer_size (&decoder);
}

void free_buffers ()
{
exr_decoding_free_buffers (&decoder);
}

exr_result_t last_decode_err = EXR_ERR_UNKNOWN;
bool first = true;
bool counts_only = false;
Expand Down Expand Up @@ -458,6 +468,44 @@ DeepScanLineInputFile::lastScanLineInChunk (int y) const
return _data->getChunkRange (y).second;
}

////////////////////////////////////////

size_t
DeepScanLineInputFile::bufferSize () const
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
size_t retval = 0;

std::shared_ptr<ScanLineProcess> sp = _data->processStack;

while (sp)
{
retval += sp->get_buffer_size();

sp = sp->next;
}

return retval;
}

void
DeepScanLineInputFile::freeBuffers ()
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
std::shared_ptr<ScanLineProcess> sp = _data->processStack;

while (sp)
{
sp->free_buffers();

sp = sp->next;
}
}

std::pair<int, int> DeepScanLineInputFile::Data::getChunkRange (int y) const
{
exr_attr_box2i_t dw = _ctxt->dataWindow (partNumber);
Expand Down Expand Up @@ -612,8 +660,6 @@ DeepScanLineInputFile::Data::readData (
#endif
}

////////////////////////////////////////

void
DeepScanLineInputFile::Data::readMemData (
const DeepFrameBuffer &fb,
Expand Down
6 changes: 6 additions & 0 deletions src/lib/OpenEXR/ImfDeepScanLineInputFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ class IMF_EXPORT_TYPE DeepScanLineInputFile
int scanLine1,
int scanLine2) const;

IMF_EXPORT
size_t bufferSize () const;

IMF_EXPORT
void freeBuffers ();

private:
Context _ctxt;
struct IMF_HIDDEN Data;
Expand Down
12 changes: 12 additions & 0 deletions src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,16 @@ DeepScanLineInputPart::readPixelSampleCounts (
rawdata, frameBuffer, scanLine1, scanLine2);
}

unsigned long long
DeepScanLineInputPart::bufferSize () const
{
return file->bufferSize ();
}

void
DeepScanLineInputPart::freeBuffers ()
{
file->freeBuffers ();
}

OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
5 changes: 5 additions & 0 deletions src/lib/OpenEXR/ImfDeepScanLineInputPart.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ class IMF_EXPORT_TYPE DeepScanLineInputPart
int firstScanLineInChunk (int y) const;
IMF_EXPORT
int lastScanLineInChunk (int y) const;

IMF_EXPORT
unsigned long long bufferSize () const;
IMF_EXPORT
void freeBuffers ();

private:
DeepScanLineInputFile* file;
Expand Down
46 changes: 46 additions & 0 deletions src/lib/OpenEXR/ImfDeepTiledInputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ struct TileProcess
int fb_absX, int fb_absY,
int t_absX, int t_absY);

size_t get_buffer_size ()
{
return exr_decoding_get_buffer_size (&decoder);
}

void free_buffers ()
{
exr_decoding_free_buffers (&decoder);
}

exr_result_t last_decode_err = EXR_ERR_UNKNOWN;
bool first = true;
bool counts_only = false;
Expand Down Expand Up @@ -914,6 +924,42 @@ DeepTiledInputFile::getTileOrder (int dx[], int dy[], int lx[], int ly[]) const
}
}

size_t
DeepTiledInputFile::bufferSize () const
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
size_t retval = 0;

std::shared_ptr<TileProcess> sp = _data->processStack;

while (sp)
{
retval += sp->get_buffer_size();

sp = sp->next;
}

return retval;
}

void
DeepTiledInputFile::freeBuffers ()
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
std::shared_ptr<TileProcess> sp = _data->processStack;

while (sp)
{
sp->free_buffers();

sp = sp->next;
}
}

void DeepTiledInputFile::Data::readTiles (
int dx1, int dx2, int dy1, int dy2, int lx, int ly, bool countsOnly)
{
Expand Down
6 changes: 6 additions & 0 deletions src/lib/OpenEXR/ImfDeepTiledInputFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,12 @@ class IMF_EXPORT_TYPE DeepTiledInputFile
IMF_EXPORT
void readPixelSampleCounts (int dx1, int dx2, int dy1, int dy2, int l = 0);

IMF_EXPORT
size_t bufferSize () const;

IMF_EXPORT
void freeBuffers ();

private:
Context _ctxt;
struct IMF_HIDDEN Data;
Expand Down
12 changes: 12 additions & 0 deletions src/lib/OpenEXR/ImfDeepTiledInputPart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,16 @@ DeepTiledInputPart::readPixelSampleCounts (
file->readPixelSampleCounts (dx1, dx2, dy1, dy2, l);
}

unsigned long long
DeepTiledInputPart::bufferSize () const
{
return file->bufferSize ();
}

void
DeepTiledInputPart::freeBuffers ()
{
file->freeBuffers ();
}

OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
5 changes: 5 additions & 0 deletions src/lib/OpenEXR/ImfDeepTiledInputPart.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@ class IMF_EXPORT_TYPE DeepTiledInputPart
IMF_EXPORT
void readPixelSampleCounts (int dx1, int dx2, int dy1, int dy2, int l = 0);

IMF_EXPORT
unsigned long long bufferSize () const;
IMF_EXPORT
void freeBuffers ();

private:
DeepTiledInputFile* file;

Expand Down
56 changes: 55 additions & 1 deletion src/lib/OpenEXR/ImfInputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

//-----------------------------------------------------------------------------
//
// class InputFile
// class InputFile
//
//-----------------------------------------------------------------------------

Expand Down Expand Up @@ -271,6 +271,60 @@ InputFile::rawTileData (
}
}

size_t
InputFile::bufferSize () const
{
if (_data->_storage == EXR_STORAGE_DEEP_SCANLINE)
{
return _data->_dsFile->bufferSize ();
}
else if (
_data->_storage == EXR_STORAGE_DEEP_TILED ||
_data->_storage == EXR_STORAGE_TILED)
{
return _data->_tFile->bufferSize ();
}
else if (_data->_storage == EXR_STORAGE_SCANLINE)
{
return _data->_sFile->bufferSize ();
}
else
{
THROW (
IEX_NAMESPACE::ArgExc,
"Unable to handle data storage type in file '" << fileName ()
<< "'");
}
}

void
InputFile::freeBuffers ()
{
_data->deleteCachedBuffer ();

if (_data->_storage == EXR_STORAGE_DEEP_SCANLINE)
{
_data->_dsFile->freeBuffers ();
}
else if (
_data->_storage == EXR_STORAGE_DEEP_TILED ||
_data->_storage == EXR_STORAGE_TILED)
{
_data->_tFile->freeBuffers ();
}
else if (_data->_storage == EXR_STORAGE_SCANLINE)
{
_data->_sFile->freeBuffers ();
}
else
{
THROW (
IEX_NAMESPACE::ArgExc,
"Unable to handle data storage type in file '" << fileName ()
<< "'");
}
}

TiledInputFile&
InputFile::asTiledInput (void) const
{
Expand Down
6 changes: 6 additions & 0 deletions src/lib/OpenEXR/ImfInputFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ class IMF_EXPORT_TYPE InputFile
const char*& pixelData,
int& pixelDataSize);

IMF_EXPORT
size_t bufferSize () const;

IMF_EXPORT
void freeBuffers ();

private:
IMF_HIDDEN void initialize (void);

Expand Down
12 changes: 12 additions & 0 deletions src/lib/OpenEXR/ImfInputPart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,16 @@ InputPart::rawTileData (
file->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
}

unsigned long long
InputPart::bufferSize () const
{
return file->bufferSize ();
}

void
InputPart::freeBuffers ()
{
file->freeBuffers ();
}

OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
6 changes: 6 additions & 0 deletions src/lib/OpenEXR/ImfInputPart.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class IMF_EXPORT_TYPE InputPart
const char*& pixelData,
int& pixelDataSize);

IMF_EXPORT
unsigned long long bufferSize () const;

IMF_EXPORT
void freeBuffers ();

private:
InputFile* file;
// for internal use - give OutputFile and TiledOutputFile access to file for copyPixels
Expand Down
50 changes: 49 additions & 1 deletion src/lib/OpenEXR/ImfScanLineInputFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

//-----------------------------------------------------------------------------
//
// class ScanLineInputFile
// class ScanLineInputFile
//
//-----------------------------------------------------------------------------

Expand Down Expand Up @@ -61,6 +61,16 @@ struct ScanLineProcess
const FrameBuffer *outfb,
int fbY,
const std::vector<Slice> &filllist);

size_t get_buffer_size ()
{
return exr_decoding_get_buffer_size (&decoder);
}

void free_buffers ()
{
exr_decoding_free_buffers (&decoder);
}

exr_result_t last_decode_err = EXR_ERR_UNKNOWN;
bool first = true;
Expand Down Expand Up @@ -408,6 +418,44 @@ ScanLineInputFile::rawPixelDataToBuffer (

////////////////////////////////////////

size_t
ScanLineInputFile::bufferSize () const
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
size_t retval = 0;

std::shared_ptr<ScanLineProcess> sp = _data->processStack;

while (sp)
{
retval += sp->get_buffer_size();

sp = sp->next;
}

return retval;
}

void
ScanLineInputFile::freeBuffers ()
{
#if ILMTHREAD_THREADING_ENABLED
std::lock_guard<std::mutex> lock (_data->_mx);
#endif
std::shared_ptr<ScanLineProcess> sp = _data->processStack;

while (sp)
{
sp->free_buffers();

sp = sp->next;
}
}

////////////////////////////////////////

void ScanLineInputFile::Data::readPixels (
const FrameBuffer &fb, int scanLine1, int scanLine2)
{
Expand Down
Loading

0 comments on commit 2ca0bb2

Please sign in to comment.