Skip to content

Commit 1a718c2

Browse files
committed
fix(hevc): remove duplicate function, fix DEVNULL file handle leak
P2: remove duplicate _split_yuv420_planes definition - function was defined twice identically (lines 68-94 and 98-124) - removed the second duplicate definition P2: fix DEVNULL file handle leak in HevcFeatureReader.close() - DEVNULL was opened but never closed - added cleanup in close() method
1 parent 06d81aa commit 1a718c2

1 file changed

Lines changed: 8 additions & 31 deletions

File tree

tools/tools_for_hevc/hevc_feature_decoder_mv.py

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -64,36 +64,6 @@ def ffprobe(filename):
6464

6565

6666

67-
# ---------------- YUV plane parsers ----------------
68-
def _split_yuv420_planes(buf: bytes, H: int, W: int, layout: str):
69-
"""Return Y (H,W), U (H/2,W/2), V (H/2,W/2) for layout in {i420,yv12,nv12,nv21}."""
70-
nY = H*W
71-
nUV = (H//2)*(W//2)
72-
arr = np.frombuffer(buf, dtype=np.uint8)
73-
if layout in ("i420","yv12"):
74-
Y = arr[:nY].reshape(H, W)
75-
UV = arr[nY:]
76-
# planar U and V (each nUV)
77-
U_planar, V_planar = (UV[:nUV], UV[nUV:]) if layout=="i420" else (UV[nUV:], UV[:nUV])
78-
U = U_planar.reshape(H//2, W//2)
79-
V = V_planar.reshape(H//2, W//2)
80-
return Y, U, V
81-
elif layout in ("nv12","nv21"):
82-
Y = arr[:nY].reshape(H, W)
83-
UVint = arr[nY:].reshape(H//2, W) # interleaved per row: UVUV or VUVU
84-
U = np.empty((H//2, W//2), dtype=np.uint8)
85-
V = np.empty((H//2, W//2), dtype=np.uint8)
86-
if layout == "nv12": # UVUV...
87-
U[:] = UVint[:, 0::2]
88-
V[:] = UVint[:, 1::2]
89-
else: # nv21: VUVU...
90-
V[:] = UVint[:, 0::2]
91-
U[:] = UVint[:, 1::2]
92-
return Y, U, V
93-
else:
94-
raise ValueError(layout)
95-
96-
9767
# ---------------- YUV plane parsers ----------------
9868
def _split_yuv420_planes(buf: bytes, H: int, W: int, layout: str):
9969
"""Return Y (H,W), U (H/2,W/2), V (H/2,W/2) for layout in {i420,yv12,nv12,nv21}."""
@@ -564,9 +534,16 @@ def close(self):
564534
if self._proc is not None and self._proc.poll() is None:
565535
self._proc.stdin.close()
566536
self._proc.stdout.close()
567-
# self._proc.stderr.close()
537+
# stderr is redirected to DEVNULL, not a pipe
568538
self._terminate(0.2)
569539
self._proc = None
540+
# fix: close DEVNULL file handle to prevent resource leak
541+
if hasattr(self, 'DEVNULL') and self.DEVNULL is not None:
542+
try:
543+
self.DEVNULL.close()
544+
except Exception:
545+
pass
546+
self.DEVNULL = None
570547

571548
def _terminate(self, timeout=1.0):
572549
"""Terminate the sub process."""

0 commit comments

Comments
 (0)