Skip to content

Commit 480ffc9

Browse files
committed
Add decoder instance caching as it gets used for every frame
Signed-off-by: M Q <mingmelvinq@nvidia.com>
1 parent 5a2b38f commit 480ffc9

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

monai/deploy/operators/decoder_nvimgcodec.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,14 @@ def _decode_frame(src: bytes, runner: DecodeRunner) -> bytearray | bytes
128128

129129
_logger = logging.getLogger(__name__)
130130

131+
# Lazy singletons for nvimgcodec resources; initialized on first use
132+
if nvimgcodec:
133+
_NVIMGCODEC_DECODER: Any = None
134+
_NVIMGCODEC_DECODE_PARAMS: Any = None
135+
else: # pragma: no cover - nvimgcodec not installed
136+
_NVIMGCODEC_DECODER = None
137+
_NVIMGCODEC_DECODE_PARAMS = None
138+
131139
# Required for decoder plugin
132140
DECODER_DEPENDENCIES = {
133141
x: ("numpy", "cupy", f"{NVIMGCODEC_MODULE_NAME}>={NVIMGCODEC_MIN_VERSION}") for x in SUPPORTED_TRANSFER_SYNTAXES
@@ -158,6 +166,25 @@ def is_available(uid: UID) -> bool:
158166
return True
159167

160168

169+
def _get_decoder_resources() -> tuple[Any, Any]:
170+
"""Return cached nvimgcodec decoder and decode parameters."""
171+
172+
if nvimgcodec is None:
173+
raise ImportError("nvimgcodec package is not available.")
174+
175+
global _NVIMGCODEC_DECODER, _NVIMGCODEC_DECODE_PARAMS
176+
177+
if _NVIMGCODEC_DECODER is None:
178+
_NVIMGCODEC_DECODER = nvimgcodec.Decoder()
179+
if _NVIMGCODEC_DECODE_PARAMS is None:
180+
_NVIMGCODEC_DECODE_PARAMS = nvimgcodec.DecodeParams(
181+
allow_any_depth=True,
182+
color_spec=nvimgcodec.ColorSpec.UNCHANGED,
183+
)
184+
185+
return _NVIMGCODEC_DECODER, _NVIMGCODEC_DECODE_PARAMS
186+
187+
161188
# Required function for decoder plugin (specific signature but flexible name to be registered to a decoder)
162189
# see also https://github.com/pydicom/pydicom/blob/v3.0.1/src/pydicom/pixels/decoders/base.py#L334
163190
def _decode_frame(src: bytes, runner: DecodeRunner) -> bytearray | bytes:
@@ -190,14 +217,10 @@ def _decode_frame(src: bytes, runner: DecodeRunner) -> bytearray | bytes:
190217
if not is_available(tsyntax):
191218
raise ValueError(f"Transfer syntax {tsyntax} not supported; see details in the debug log.")
192219

193-
nvimgcodec_decoder = nvimgcodec.Decoder()
194-
decode_params = nvimgcodec.DecodeParams(allow_any_depth=True, color_spec=nvimgcodec.ColorSpec.UNCHANGED)
195-
decoded_data = nvimgcodec_decoder.decode(
196-
src, params=decode_params
197-
) # HWC layout, interleaved format, and contiguous array in C-style
198-
superface = np.asarray(decoded_data.cpu())
199-
np.ascontiguousarray(superface)
200-
return superface.tobytes()
220+
decoder, params = _get_decoder_resources()
221+
decoded_surface = decoder.decode(src, params=params).cpu()
222+
np_surface = np.ascontiguousarray(np.asarray(decoded_surface))
223+
return np_surface.tobytes()
201224

202225

203226
def _is_nvimgcodec_available() -> bool:

0 commit comments

Comments
 (0)