From 5f858bebdcab3355f9ba75b51b4b911d18d8bae0 Mon Sep 17 00:00:00 2001 From: pinjie Date: Thu, 20 Aug 2026 11:02:42 +0000 Subject: [PATCH] fix get gop stride bug, when numpy>2.0 Signed-off-by: pinjie --- .../ext_impl/external/pybind11 | 2 +- .../src/PyNvGopDecoder_constructors.cpp | 10 ++++--- .../tests/test_gop_cache.py | 27 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/on_demand_video_decoder/ext_impl/external/pybind11 b/packages/on_demand_video_decoder/ext_impl/external/pybind11 index aa304c9c..2e081527 160000 --- a/packages/on_demand_video_decoder/ext_impl/external/pybind11 +++ b/packages/on_demand_video_decoder/ext_impl/external/pybind11 @@ -1 +1 @@ -Subproject commit aa304c9c7d725ffb9d10af08a3b34cb372307020 +Subproject commit 2e0815278cb899b20870a67ca8205996ef47e70f diff --git a/packages/on_demand_video_decoder/ext_impl/src/PyNvOnDemandDecoder/src/PyNvGopDecoder_constructors.cpp b/packages/on_demand_video_decoder/ext_impl/src/PyNvOnDemandDecoder/src/PyNvGopDecoder_constructors.cpp index d9575039..71c41b7f 100644 --- a/packages/on_demand_video_decoder/ext_impl/src/PyNvOnDemandDecoder/src/PyNvGopDecoder_constructors.cpp +++ b/packages/on_demand_video_decoder/ext_impl/src/PyNvOnDemandDecoder/src/PyNvGopDecoder_constructors.cpp @@ -541,8 +541,10 @@ void Init_PyNvGopDecoder(py::module& m) { // Create numpy array from serialized data for this video auto capsule = py::capsule(bundle.data.release(), [](void* ptr) { delete[] static_cast(ptr); }); - py::array_t numpy_data( - bundle.size, static_cast(capsule.get_pointer()), capsule); + py::array_t numpy_data({static_cast(bundle.size)}, + {static_cast(sizeof(uint8_t))}, + static_cast(capsule.get_pointer()), + capsule); // Create tuple (numpy_data, first_frame_ids, gop_lens) for this video py::tuple video_tuple = @@ -1218,7 +1220,9 @@ void Init_PyNvGopDecoder(py::module& m) { py::capsule(raw_ptr, [](void* ptr) { delete[] static_cast(ptr); }); // Create numpy array - py::array_t numpy_data(size, raw_ptr, capsule); + py::array_t numpy_data({static_cast(size)}, + {static_cast(sizeof(uint8_t))}, raw_ptr, + capsule); result_list.append(std::move(numpy_data)); } diff --git a/packages/on_demand_video_decoder/tests/test_gop_cache.py b/packages/on_demand_video_decoder/tests/test_gop_cache.py index ce5439ef..99c1a2b7 100644 --- a/packages/on_demand_video_decoder/tests/test_gop_cache.py +++ b/packages/on_demand_video_decoder/tests/test_gop_cache.py @@ -19,6 +19,9 @@ including cache hit/miss scenarios, cache management, and data correctness. """ +from pathlib import Path + +import numpy as np import pytest import sys import torch @@ -47,6 +50,17 @@ def _gop_ranges(gop_list): return first_ids, gop_lens +def _assert_contiguous_byte_bundle(bundle: np.ndarray, expected: bytes) -> None: + assert isinstance(bundle, np.ndarray) + assert bundle.dtype == np.dtype(np.uint8) + assert bundle.ndim == 1 + assert bundle.itemsize == 1 + assert bundle.strides == (1,) + assert bundle.flags.c_contiguous + assert bundle.nbytes == len(expected) + assert bundle.tobytes() == expected + + class TestGetGOPListCache: """Tests for GetGOPList with useGOPCache parameter.""" @@ -95,6 +109,19 @@ def test_getgoplist_basic(self, decoder, test_files_and_frames, use_cache): print(f"✓ Test passed: Got {len(gop_list)} GOP bundles") + def test_gop_bundle_numpy_layout(self, decoder, tmp_path): + """Serialized GOP bundles stay contiguous on NumPy 1.x and 2.x.""" + sample_video = Path(utils.get_data_dir()) / "sample_clip" / "moving_shape_circle_h265.mp4" + bundle = decoder.GetGOPList([str(sample_video)], [10], useGOPCache=False)[0][0] + + gop_path = tmp_path / "serialized.gop" + nvc.SaveGopToFile(bundle, str(gop_path)) + expected = gop_path.read_bytes() + _assert_contiguous_byte_bundle(bundle, expected) + + loaded = decoder.LoadGopsToList([str(gop_path)])[0] + _assert_contiguous_byte_bundle(loaded, expected) + def test_getgoplist_cache_hit(self, decoder, test_files_and_frames): """ Test GetGOPList cache hit scenario.