Skip to content

Report unparsed headers, and bind seven of them - #362

Open
Ruslan-B wants to merge 2 commits into
mainfrom
feature/header-coverage-report
Open

Ruslan-B wants to merge 2 commits into
mainfrom
feature/header-coverage-report

Conversation

@Ruslan-B

@Ruslan-B Ruslan-B commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Two commits: a report that finds headers the parser never saw, and the first batch of what it found.

The report

The list in Program.Parse names entry points, not files. Clang follows the includes and ASTProcessor takes every non-system translation unit, so a root brings its whole closure — 28 roots reached 62 headers. What a root cannot bring is a leaf that nothing includes, and most of libavutil is exactly that. Those only get noticed when somebody asks: libavcodec/exif.h had been unparsed since 8.1, libavutil/raw_color_params.h since 9.0.

It prints after processing, is silent when there is nothing to say, and splits the list by whether a header can be added at all:

82 header(s) under FFmpeg\include were never parsed.
  12 need headers this build does not have, so they cannot be added as they are:
    libavutil/hwcontext_cuda.h <- cuda.h
    libavutil/hwcontext_vaapi.h <- va/va.h
    libavutil/hwcontext_vulkan.h <- vulkan/vulkan.h
    ...
  70 include nothing beyond FFmpeg and the C standard library, so adding
  any of them to the list in Program.Parse would bind it:
    libavcodec/exif.h
    libavutil/parseutils.h
    ...

That split is the point: those twelve cannot be added without installing the SDK named beside them, which is why the list has always been curated. It is a decision, and the report keeps it visible rather than leaving it to memory.

The seven

Not a sweep. Twenty-two of the seventy are ciphers and digests that System.Security.Cryptography already covers; another handful are macros or internals. These earn their place:

header what it brings
libavutil/parseutils.h av_parse_video_size("1280x720"), av_parse_video_rate, av_parse_color, av_parse_time
libavutil/tx.h av_tx_init — FFmpeg's FFT and MDCT, which .NET has no equivalent for
libavutil/eval.h the expression evaluator, for dynamic filter values
libavutil/encryption_info.h AVEncryptionInfo, for CENC streams
libavutil/iamf.h see below
libavutil/hwcontext_drm.h DRM PRIME, the zero-copy path on Linux
libavcodec/exif.h EXIF metadata, new in 8.1

+52 functions, +25 structs, +11 enums.

iamf.h is not a nice-to-have. avformat.h forward-declares AVIAMFAudioElement and AVIAMFMixPresentation, so both were already generated — as empty structs, because the header that defines them was never parsed. Reaching them through AVStreamGroup.params compiled and handed you a pointer to a struct with no fields. They are complete now. The two that became incomplete in their place, AVExpr and AVTXContext, are forward-declared in FFmpeg on purpose, like AVDictionary and SwrContext.

Two that did not make it

Both for reasons the report cannot see, which is worth recording:

  • libavutil/fifo.h crashes the generator. AVFifoCB is a typedef to a function type rather than to a function pointer, so the parameter arrives as a bare FunctionType and TypeHelper.GetTypeName has no case for it. That wants a fix in the generator, not a workaround here.
  • libavutil/timestamp.h is two static inline helpers and one export, all of which format text into a caller-supplied char*. The inline bodies would need hand-porting and the result would be pointless from C#, where the whole thing is ts == long.MinValue ? "NOPTS" : ts.ToString().

iamf.h did bring one inline that needed porting — av_iamf_param_definition_get_subblock, whose body expands av_assert0 into av_log and abort(). Ported to a bounds check and pointer arithmetic, and I confirmed a regeneration keeps it, which is what the body hash is there for.

Verification

  • dotnet build -c Release — 0 errors, 0 warnings
  • dotnet test -c Release — 22/22
  • Regeneration is idempotent, including over the hand-ported inline
  • Example runs end to end: 1001 frames decoded, re-encoded and muxed

🤖 Generated with Claude Code

The list in Program.Parse names entry points rather than files: clang follows
the includes and ASTProcessor takes every non-system translation unit, so a
root brings its whole closure with it - 28 roots reach 62 headers. What a root
cannot bring is a leaf nothing includes, and most of libavutil is exactly that.
Those only get noticed when somebody asks, which is how libavcodec/exif.h has
been sitting unparsed since 8.1 and libavutil/raw_color_params.h since 9.0.

Missing one is not only "the type is absent". avformat.h forward-declares
AVIAMFAudioElement and AVIAMFMixPresentation, so both are generated - as empty
structs marked incomplete, because libavutil/iamf.h is never parsed even though
it defines them in full. Reaching them through AVStreamGroup.params compiles and
gives you a pointer to a struct with no fields.

The generator now lists what it never parsed, split by whether the header can be
added at all: twelve of them pull in an SDK this build does not have, and the
report names the missing include for each (vulkan/vulkan.h, cuda.h, va/va.h,
mfxvideo.h and so on). The remaining seventy include nothing beyond FFmpeg and
the C standard library, so any of them is one line in Program.Parse away.

It reports, it does not decide: twenty-two of those seventy are ciphers and
digests that System.Security.Cryptography already covers, and nobody needs
FFmpeg's AES from C#. The point is to see the list after an FFmpeg upgrade
rather than to bind all of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 21, 2026 21:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Not a sweep. Twenty-two of the seventy self-contained ones are ciphers and
digests that System.Security.Cryptography already covers, and another handful
are macros or FFmpeg internals. These seven are the ones worth having:

  libavutil/parseutils.h      av_parse_video_size("1280x720"), av_parse_video_rate,
                              av_parse_color, av_parse_time
  libavutil/tx.h              av_tx_init - FFmpeg's FFT and MDCT, which .NET has
                              no equivalent for
  libavutil/eval.h            the expression evaluator, for dynamic filter values
  libavutil/encryption_info.h AVEncryptionInfo, for CENC streams
  libavutil/iamf.h            see below
  libavutil/hwcontext_drm.h   DRM PRIME, the zero-copy path on Linux
  libavcodec/exif.h           EXIF metadata, new in 8.1 and unparsed since

+52 functions, +25 structs, +11 enums.

iamf.h is not a nice-to-have. avformat.h forward-declares AVIAMFAudioElement
and AVIAMFMixPresentation, so both were already generated - as empty structs,
because the header defining them was never parsed. Anyone reaching them through
AVStreamGroup.params got a pointer to a struct with no fields. They are complete
now. The two structs that became incomplete in their place, AVExpr and
AVTXContext, are forward-declared in FFmpeg on purpose, like AVDictionary and
SwrContext.

Two candidates did not make it, both for reasons the report cannot see:

libavutil/fifo.h crashes the generator. AVFifoCB is a typedef to a function
type rather than to a function pointer, so the parameter arrives as a bare
FunctionType and TypeHelper.GetTypeName has no case for it. That wants a fix in
the generator, not a workaround here.

libavutil/timestamp.h is two static inline helpers and one export, and all
three format text into a caller-supplied char*. The inline bodies would need
hand-porting, and the result would be pointless from C#, where the whole thing
is ts == long.MinValue ? "NOPTS" : ts.ToString().

iamf.h did bring one inline that needed porting -
av_iamf_param_definition_get_subblock, whose body expands av_assert0 into
av_log and abort(). Ported to a bounds check and pointer arithmetic; verified
that regenerating keeps it, which is what the body hash is for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Ruslan-B Ruslan-B changed the title Report headers the parser never saw Report unparsed headers, and bind seven of them Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants