Skip to content

Make the output dtype config the only dtype on VideoStreamOptions - #1696

Open
NicolasHug wants to merge 1 commit into
mainfrom
nvdec-surface-depth
Open

Make the output dtype config the only dtype on VideoStreamOptions#1696
NicolasHug wants to merge 1 commit into
mainfrom
nvdec-surface-depth

Conversation

@NicolasHug

@NicolasHug NicolasHug commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

VideoStreamOptions held both the user's OutputDtypeConfig and the OutputDtype resolved from it. Two changes, one theme: the config becomes the only dtype on the struct.

The NVDEC surface. The decode building block asked for a 16-bit surface by setting output_dtype to FLOAT32 — but it does no color conversion, so it has no output dtype. The expression it used to get there, bit_depth > 8 ? FLOAT32 : UINT8, is exactly what resolve_output_dtype() does with AUTO: it was resolving AUTO by hand so BetaCuda could map the answer back into a surface width. Pass the config and the mapping is direct:

config surface
UINT8 8-bit
FLOAT32 16-bit
AUTO match the source

The resolved field. OutputDtype is derived from the config plus the source pixel format, so storing it beside the config left the struct half-valid until someone resolved. SingleStreamDecoder wrote the answer back into its own options; ColorConverter, which must resolve per frame, fabricated a whole VideoStreamOptions just to carry it into initialize_color_conversion(). It is now an argument of that call, and SSD's per-stream answer lives on StreamInfo.

No behaviour change. initialize_color_conversion() and initialize_video() gain a parameter, so out-of-tree device interfaces will need updating.


Replaces #1692, which GitHub auto-closed as merged during a stack reorder — nothing was actually merged. Absorbs #1698.

@pytorch-bot

pytorch-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/meta-pytorch/torchcodec/1696

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 6cbab16 with merge base 2312413 (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Sep 4, 2026
@NicolasHug NicolasHug changed the title Pick the NVDEC surface from an explicit option, not from output_dtype Pick the NVDEC surface from the output dtype config, not a resolved dtype Sep 4, 2026
@NicolasHug NicolasHug changed the title Pick the NVDEC surface from the output dtype config, not a resolved dtype Make the output dtype config the only dtype on VideoStreamOptions Sep 4, 2026
@NicolasHug
NicolasHug force-pushed the nvdec-surface-depth branch 2 times, most recently from 53f6d35 to 0d854f0 Compare September 4, 2026 10:02
Two halves of one thing. VideoStreamOptions held both the user's
OutputDtypeConfig and the OutputDtype resolved from it, and both the decode
building block and BetaCuda were reaching for the resolved one when what
they wanted was the config.

First, the NVDEC surface. The decode building block asked for a 16-bit
surface by setting output_dtype to FLOAT32, which nothing downstream of it
reads: it does no color conversion, so it has no output dtype. What it
computed to get there, `stream_bit_depth > 8 ? FLOAT32 : UINT8`, is
character for character the rule resolve_output_dtype() applies to AUTO, so
the block was resolving AUTO by hand and leaving BetaCuda to map the answer
back into a surface width. Pass the config and the mapping is total:

    UINT8   -> 8-bit surface, all a uint8 output needs
    FLOAT32 -> 16-bit surface, so precision survives
    AUTO    -> whatever the source has

A caller that color-converts elsewhere wants that last one, so it asks for
AUTO and says nothing about NVDEC. BetaCuda's output_dtype_ member goes
with it: the decode path was its only reader, and the store in
initialize_color_conversion() was already dead.

Second, the field itself. OutputDtype is resolve_output_dtype(config,
source pixel format) - derived, not configured - and holding it next to the
config it derives from left the struct half-valid until someone resolved.
The two users then resolved it in ways one shared field couldn't express:
SingleStreamDecoder wrote the answer back into its own options once per
stream, while ColorConverter, which resolves per frame because AUTO "can
differ from one frame to the next", fabricated a whole VideoStreamOptions
purely to carry the answer across initialize_color_conversion(). So make
the resolved dtype an argument of that call - the only stage that needs it
- and leave the struct with the config alone. SingleStreamDecoder's
once-per-stream answer moves to StreamInfo, where decoder state belongs.

Worth knowing while reading: the two resolutions take their pixel format
from different places, the stream header in SingleStreamDecoder and the
frame itself in ColorConverter, so they can disagree. Passing the value
explicitly doesn't fix that, but it stops one struct field from implying
they are the same thing.

No behaviour change. initialize_color_conversion() and initialize_video()
both gain a parameter, which out-of-tree device interfaces will need to
follow.
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.

1 participant