Refactor video frame extraction to improve PyNvCodec availability check - #1511
Conversation
- Removed the try-except block for importing PyNvcFrameExtractor, simplifying the import logic. - Updated the condition for initializing the PyNvcFrameExtractor in the VideoFrameExtractionStage to rely solely on the _PYNVC_AVAILABLE flag. - Adjusted the handling of pixel format conversion in NvVideoDecoder to prepare for future updates to cvcuda. Signed-off-by: Abhinav Garg <abhinavg@stanford.edu>
…ting rule - Modified import statements in the test file to include the RUF100 linting rule, ensuring better adherence to coding standards. - This change enhances the clarity of the import handling tests. Signed-off-by: [Your Name] <your.email@example.com> Signed-off-by: Abhinav Garg <abhinavg@stanford.edu>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Signed-off-by: Abhinav Garg <abhinavg@stanford.edu>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Signed-off-by: Abhinav Garg <abhinavg@stanford.edu>
| # TODO: Remove the use of nvcv_image. It's deprecated | ||
| cvcuda_tensor = cvcuda.as_tensor(cvcuda.as_image(decoded_frame.nvcv_image(), cvcuda.Format.U8)) |
There was a problem hiding this comment.
Deprecated nvcv_image() method still in use
The TODO comment acknowledges nvcv_image() is deprecated, but the method is still called on the decoded frame object. If PyNvVideoCodec eventually removes nvcv_image() from its DecodedFrame API, this will fail at runtime with an AttributeError. The TODO should either track a GitHub issue or be resolved now by using the alternative non-deprecated frame access API exposed by PyNvVideoCodec.
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor | ||
| mock_cvcuda.as_image.return_value = Mock() | ||
| mock_cvcuda.Format.U8 = Mock() | ||
|
|
||
| # Mock torch tensor | ||
| mock_torch_nhwc = Mock() | ||
| mock_torch.empty.return_value = mock_torch_nhwc | ||
|
|
||
| # Mock cvcuda tensor | ||
| # Mock cvcuda tensor for NHWC conversion | ||
| mock_cvcuda_nhwc = Mock() | ||
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_nhwc | ||
|
|
||
| # Setup side effect for as_tensor to return different mocks | ||
| def as_tensor_side_effect(*args: Any, **_kwargs: Any) -> Any: | ||
| if len(args) == 2 and isinstance(args[1], str): | ||
| return mock_cvcuda_nhwc | ||
| return mock_cvcuda_tensor | ||
|
|
||
| mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect |
There was a problem hiding this comment.
as_tensor initial return_value is shadowed by side_effect
At line 676, mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor is set, but is immediately overridden by mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect at line 693. When a side_effect is set on a Mock, return_value is ignored entirely — Python's unittest.mock always invokes the side_effect callable instead. The line 676 assignment is dead code and should be removed to avoid confusing readers about which mock controls the return value.
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor | |
| mock_cvcuda.as_image.return_value = Mock() | |
| mock_cvcuda.Format.U8 = Mock() | |
| # Mock torch tensor | |
| mock_torch_nhwc = Mock() | |
| mock_torch.empty.return_value = mock_torch_nhwc | |
| # Mock cvcuda tensor | |
| # Mock cvcuda tensor for NHWC conversion | |
| mock_cvcuda_nhwc = Mock() | |
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_nhwc | |
| # Setup side effect for as_tensor to return different mocks | |
| def as_tensor_side_effect(*args: Any, **_kwargs: Any) -> Any: | |
| if len(args) == 2 and isinstance(args[1], str): | |
| return mock_cvcuda_nhwc | |
| return mock_cvcuda_tensor | |
| mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect | |
| mock_cvcuda.as_image.return_value = Mock() | |
| mock_cvcuda.Format.U8 = Mock() |
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor | ||
| mock_cvcuda.as_image.return_value = Mock() | ||
| mock_cvcuda.Format.U8 = Mock() | ||
|
|
||
| mock_torch_nhwc = Mock() | ||
| mock_torch.empty.return_value = mock_torch_nhwc | ||
| mock_cvcuda_nhwc = Mock() | ||
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_nhwc | ||
|
|
||
| # Setup side effect for as_tensor to return different mocks | ||
| def as_tensor_side_effect(*args: Any, **_kwargs: Any) -> Any: | ||
| if len(args) == 2 and isinstance(args[1], str): | ||
| return mock_cvcuda_nhwc | ||
| return mock_cvcuda_tensor | ||
|
|
||
| mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect |
There was a problem hiding this comment.
Same dead return_value assignment shadowed by side_effect
mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor at line 790 is set but immediately overridden when mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect is assigned at line 804. As with test_generate_decoded_frames_with_frames, the return_value is never consulted once a side_effect is active, making the assignment dead code.
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_tensor | |
| mock_cvcuda.as_image.return_value = Mock() | |
| mock_cvcuda.Format.U8 = Mock() | |
| mock_torch_nhwc = Mock() | |
| mock_torch.empty.return_value = mock_torch_nhwc | |
| mock_cvcuda_nhwc = Mock() | |
| mock_cvcuda.as_tensor.return_value = mock_cvcuda_nhwc | |
| # Setup side effect for as_tensor to return different mocks | |
| def as_tensor_side_effect(*args: Any, **_kwargs: Any) -> Any: | |
| if len(args) == 2 and isinstance(args[1], str): | |
| return mock_cvcuda_nhwc | |
| return mock_cvcuda_tensor | |
| mock_cvcuda.as_tensor.side_effect = as_tensor_side_effect | |
| mock_cvcuda.as_image.return_value = Mock() | |
| mock_cvcuda.Format.U8 = Mock() |
Description
Usage
# Add snippet demonstrating usageChecklist