Skip to content

Windows: the default vcpkg FFmpeg has no PNG decoder, so --vision rejects every PNG #136

Description

@tmark00

On Windows, --vision fails on every PNG with

error: media codec is not supported

while JPEG, BMP, WebP, TIFF and GIF all decode fine. That asymmetry makes it read as a broken vision path rather than a missing build dependency, and PNG is the default screenshot format on Windows, so it is the first format a user is likely to try.

The message comes from src/media/decode/decode.cpp, where avcodec_find_decoder returns nullptr for the stream's codec id. Nothing is wrong in NInfer — the decoder was never built.

Root cause

FFmpeg gates its PNG decoder on zlib, one hop of indirection:

configure:3295   png_decoder_select="inflate_wrapper"
configure:3103   inflate_wrapper_deps="zlib"

(line numbers from the FFmpeg 9.0.1 tree that vcpkg builds)

The vcpkg ffmpeg port does not enable zlib unless it is asked for. A default vcpkg install ffmpeg:x64-windows — or one that names only the library features — produces an avcodec with no png decoder in it. cmake/NInferMediaDeps.cmake locates FFmpeg through the vcpkg prefix on Windows, and there is no way for a find_path / find_library probe to notice that a codec is missing from the library it found.

How to check an existing build

strings on the DLL is not conclusive here; enumerating the decoder table is. This loads the avcodec that sits next to ninfer-serve.exe and walks av_codec_iterate:

import ctypes, os
p = r"<build>/apps"            # or the vcpkg bin directory
os.add_dll_directory(p)
av = ctypes.CDLL(os.path.join(p, "avcodec-63.dll"))

class AVCodec(ctypes.Structure):
    _fields_ = [("name", ctypes.c_char_p), ("long_name", ctypes.c_char_p),
                ("type", ctypes.c_int), ("id", ctypes.c_int)]

av.av_codec_iterate.restype = ctypes.POINTER(AVCodec)
av.av_codec_iterate.argtypes = [ctypes.POINTER(ctypes.c_void_p)]
av.av_codec_is_decoder.restype = ctypes.c_int
av.av_codec_is_decoder.argtypes = [ctypes.POINTER(AVCodec)]

it, dec = ctypes.c_void_p(None), []
while True:
    c = av.av_codec_iterate(ctypes.byref(it))
    if not c:
        break
    if av.av_codec_is_decoder(c):
        dec.append(c.contents.name.decode())

print(len(dec), "decoders;", "png" in dec)

Measured on the same machine, before and after enabling the feature:

decoders png
ffmpeg[avcodec,avdevice,avfilter,avformat,swresample,swscale] 477 absent
the same plus zlib 499 present

The 22 that appear are exactly the zlib-dependent ones — png and apng through inflate_wrapper, plus flashsv, tdsc, zlib, zmbv and friends.

Fix

vcpkg install "ffmpeg[core,avcodec,avdevice,avfilter,avformat,swresample,swscale,zlib]:x64-windows" --recurse

That rebuild took about 13 minutes here. Afterwards a normal build picks the new DLLs up on its own, since the link step already copies the vcpkg runtime next to the executables. Verified end to end: the same PNG that previously produced media codec is not supported is now described correctly through both the CLI and /v1/chat/completions.

Suggestion

Two places where stating it would have saved the debugging:

Happy to send a docs patch if that is useful.

Environment

  • Windows 11, MSVC 14.51, CUDA 13.2, Ninja
  • vcpkg ffmpeg 9.0.1#1, triplet x64-windows
  • RTX 5090 Laptop (GB203), driver 616.56

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions