Skip to content

Support negative index in SimpleVideoDecoder #743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 26, 2025

Conversation

Dan-Flores
Copy link
Contributor

This PR adds the missing functionality described in #150, specifically adding support for negative indexing in get_frame_at() and get_frames_at().

In both functions, a negative index n is converted to len(decoder) - n. The tests are updated to reflect this support as well.

The other item in that issue, allowing "upper bound in slices to be greated than len(decoder)", is already supported by getitem_slice. Specifically, this section of _video_decoder.py handles negative and out-of-range indices:

    def _getitem_slice(self, key: slice) -> Tensor:
        assert isinstance(key, slice)

        start, stop, step = key.indices(len(self))

I added a new test case to test_getitem_slice to make this more explicit.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Meta Open Source bot. label Jun 25, 2025
decoder.get_frames_at([-1])
expected_converted_index = -10000 + len(decoder)
with pytest.raises(
RuntimeError, match=f"Invalid frame index={expected_converted_index}"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This error is from SingleStreamDecoder.cpp. Should we also be checking valid indices at the Python level, in _video_decoder.py?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good observation - at the Python level, we currently don't check the input when we get a list of indices (get_frames_at()) or a list of timestamps (get_frames_played_at()). The weak rationale was that we'd have to walk the list to do the check, and that seemed wasteful. Now that we're walking the list in get_frames_at() to deal with negative indices, we might as well do error checking at the same time.

The question, then, is what to do in get_frames_played_at()? For completeness, I think it does make sense to do error checking at the Python level there, but let's do that in a separate PR. We can also do some refactoring there, and make _getitem_slice() call VideoDecoder.get_frames_in_range() in order to get that error checking at the Python level as well.

@@ -520,8 +549,11 @@ def test_get_frames_at(self, device, seek_mode):
def test_get_frames_at_fails(self, device, seek_mode):
decoder = VideoDecoder(NASA_VIDEO.path, device=device, seek_mode=seek_mode)

with pytest.raises(RuntimeError, match="Invalid frame index=-1"):
decoder.get_frames_at([-1])
expected_converted_index = -10000 + len(decoder)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not necessary to get the expected index here, but I added it to match the other tests. Alternatively, the test can simply match the text: "Invalid frame index".

Copy link
Contributor

Choose a reason for hiding this comment

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

It's fine to do, but I usually default to just matching the text that doesn't change.

@Dan-Flores Dan-Flores marked this pull request as ready for review June 25, 2025 19:23
Copy link
Contributor

@scotts scotts left a comment

Choose a reason for hiding this comment

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

Let's do the error checking in get_frames_at() now too, but approved to unblock.

Copy link
Member

@NicolasHug NicolasHug left a comment

Choose a reason for hiding this comment

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

Thanks @Dan-Flores , LGTM!

I forgot to write it down in #150, but eventually it'd be good to accept the same semantics for get_frames_in_range(). We we can merge this PR as-is though.

@Dan-Flores Dan-Flores merged commit e654189 into pytorch:main Jun 26, 2025
42 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Meta Open Source bot.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants