Skip to content

Refactor video frame extraction to improve PyNvCodec availability check - #1511

Merged
abhinavg4 merged 7 commits into
mainfrom
video_nvdec_fix
Feb 17, 2026
Merged

Refactor video frame extraction to improve PyNvCodec availability check#1511
abhinavg4 merged 7 commits into
mainfrom
video_nvdec_fix

Conversation

@abhinavg4

Copy link
Copy Markdown
Contributor
  • 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.

Description

Usage

# Add snippet demonstrating usage

Checklist

  • I am familiar with the Contributing Guide.
  • New or Existing tests cover these changes.
  • The documentation is up to date with these changes.

- 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>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread tests/utils/test_nvcodec_utils.py
Comment thread tests/utils/test_nvcodec_utils.py
abhinavg4 and others added 2 commits February 17, 2026 11:05
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>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +271 to +272
# 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))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +676 to +693
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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()

Comment on lines +790 to +804
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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()

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread tests/utils/test_nvcodec_utils.py
Comment thread tests/utils/test_nvcodec_utils.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

r1.1.0 Pick this label for auto cherry-picking into r1.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants