{
  "schemaVersion": 1,
  "generated": "2026-07-22",
  "generatedFrom": "baseline/ffmpeg-invocations.json plus the approved 2026-07-24 LGPL hardware-only product policy",
  "ffmpegTargetVersion": "8.1.2",
  "purpose": "Authoritative list of FFmpeg capabilities the NextNote build must expose (asserted present) and things that must never be present (asserted absent). tests/capability-tests.ps1 consumes this file. Required runtime components are traceable to baseline/ffmpeg-invocations.json; the GPL and software-encoder exclusions are explicit product policy.",
  "encoderPreferenceOrder": ["h264_nvenc", "h264_amf", "h264_qsv"],
  "requiredLicenseMarker": "GNU Lesser General Public License",
  "required": {
    "programs": ["ffmpeg"],
    "inputDevices": ["gdigrab", "lavfi"],
    "demuxers": ["h264"],
    "muxers": ["h264", "rawvideo", "null"],
    "decoders": ["h264", "bmp", "wrapped_avframe"],
    "hardwareAccelerators": ["d3d11va"],
    "encoders": ["h264_nvenc", "h264_amf", "h264_qsv", "rawvideo"],
    "parsers": ["h264"],
    "bitstreamFilters": ["dump_extra", "filter_units", "h264_metadata"],
    "protocols": ["pipe", "file"],
    "filters": ["buffer", "buffersink", "color", "drawbox", "format", "scale"],
    "pixelFormats": ["yuv420p", "bgra", "bgr24"],
    "configureFlags": [
      "--enable-amf",
      "--enable-nvenc",
      "--enable-ffnvcodec",
      "--enable-libvpl",
      "--enable-d3d11va",
      "--enable-hwaccel=h264_d3d11va",
      "--enable-hwaccel=h264_d3d11va2"
    ]
  },
  "requiredRationale": {
    "decoders.bmp": "gdigrab produces BMP-coded frames; without the bmp decoder every capture command fails.",
    "decoders.wrapped_avframe": "lavfi input device wraps frames as wrapped_avframe packets (black-frame path).",
    "decoders.h264": "NextNote Display decodes the LiveView H.264 bitstream through the required D3D11VA hardware path.",
    "hardwareAccelerators.d3d11va": "Required vendor-neutral Windows H.264 hardware decoding for Intel, NVIDIA, and AMD GPUs. NextNote Display requests D3D11VA explicitly and does not silently fall back to software decoding.",
    "encoders.rawvideo": "Distinct from the rawvideo MUXER (also required): -f rawvideo -pix_fmt bgra output on Display's decode command still goes through avcodec's encode API via this passthrough codec even though no real encoding happens. Without it: \"Error selecting an encoder ... Encoder not found.\" Found via the decode smoke test during Milestone 2 authoring (2026-07-22).",
    "parsers.h264": "Raw h264 demuxer needs the h264 parser to split Annex-B input on pipe:0.",
    "filters.buffer": "fftools/ffmpeg_filter.c calls avfilter_get_by_name(\"buffer\") unconditionally to build the CLI's own filtergraph; the ffmpeg binary cannot run any video path without it. Verified against FFmpeg 8.1.2 source (2026-07-22); the M0 assumption that a 'null' filter is auto-inserted was incorrect and has been removed.",
    "filters.buffersink": "Companion to filters.buffer -- fftools/ffmpeg_filter.c calls avfilter_get_by_name(\"buffersink\") unconditionally.",
    "filters.format": "Auto-inserted for -pix_fmt yuv420p (encode) and -pix_fmt bgra (decode output); fftools/ffmpeg_filter.c calls avfilter_get_by_name(\"format\") directly.",
    "filters.scale": "Explicit -vf scale=960:-2 downscale, plus auto-inserted colourspace conversion; requires libswscale.",
    "filters.color": "lavfi color=black source for the pre-encoded end-of-show black frame.",
    "filters.drawbox": "QSV black-frame path fills a gdigrab surface with black.",
    "pixelFormats.bgr24": "gdigrab's native output for 24-bit desktops; conversion input for the encode path.",
    "muxers.null": "Encoder capability probes end in -f null -.",
    "protocols.pipe": "All stream I/O is pipe:0/pipe:1.",
    "protocols.file": "Local file I/O and resolution of '-' targets.",
    "bitstreamFilters.h264_metadata": "NextNote never invokes this bsf. It exists purely to compile in cbs_h264 (FFmpeg's H.264 Coded Bitstream unit) as a build-time transitive dependency, without which filter_units fails at runtime with \"Codec 'h264' (27) is not supported by the bitstream filter 'filter_units'\" even though filter_units itself is enabled -- cbs_h264 is FFmpeg's own CONFIG_EXTRA and cannot be enabled directly. Full detail in config/ffmpeg.configure.args. Kept in this required set so a future minimisation pass (Milestone 4) does not drop it and silently reintroduce the failure."
  },
  "configureNameMapping": {
    "comment": "Some capabilities have a different --enable-X name in FFmpeg's configure than their runtime command-line name, because configure derives component names from C source symbols (see configure's find_things_extern), not from the runtime .p.name/.name string. Verified directly against FFmpeg 8.1.2 source (2026-07-22) -- do not guess these.",
    "dump_extra": {
      "runtimeName": "dump_extra",
      "configureFlag": "--enable-bsf=dump_extradata",
      "reason": "Symbol is ff_dump_extradata_bsf in libavcodec/bitstream_filters.c; find_things_extern strips 'ff_' and '_bsf' to get 'dump_extradata'. The filter's own .p.name field (libavcodec/bsf/dump_extradata.c) is 'dump_extra', which is what -bsf:v uses on the command line."
    }
  },
  "requiredOptionSmoke": {
    "comment": "CLI options that capability tests must exercise (option name existence is not enough; each must be accepted by the relevant component).",
    "global": ["-loglevel", "-hide_banner"],
    "input": ["-hwaccel d3d11va", "-f", "-framerate", "-video_size", "-offset_x", "-offset_y", "-draw_mouse", "-probesize", "-analyzeduration", "-fflags nobuffer+flush_packets", "-flags low_delay", "-i"],
    "output": ["-vframes", "-c:v", "-vf", "-g", "-bf", "-an", "-bsf:v", "-flush_packets", "-f", "-pix_fmt", "-fps_mode passthrough", "-profile:v", "-level", "-b:v", "-maxrate", "-bufsize", "-preset", "-tune", "-rc", "-rc-lookahead", "-forced-idr", "-usage", "-quality"],
    "bitstreamFilterArgs": ["dump_extra=freq=keyframe", "filter_units=remove_types=6|12"]
  },
  "forbidden": {
    "configureFlags": ["--enable-gpl", "--enable-version3", "--enable-libx264", "--enable-nonfree"],
    "programs": ["ffprobe", "ffplay"],
    "encoders": ["libx264"],
    "components": ["libfdk_aac", "openssl-nonfree", "libnpp", "cuda-nvcc", "cuda-sdk", "decklink"],
    "comment": "Applies to every build, including the Milestone 2 compatibility build. Non-free components make the binary non-redistributable; only ffmpeg.exe is shipped."
  },
  "absentAfterMinimisation": {
    "comment": "Deliberate absences asserted only from Milestone 4 onward. The compatibility build may still contain these; the minimised build must not.",
    "encoders": ["libx265", "hevc_nvenc", "hevc_amf", "hevc_qsv", "av1_nvenc", "libaom-av1", "libvpx", "libvpx-vp9", "aac", "libmp3lame", "libopus"],
    "muxers": ["mp4", "matroska", "mov", "webm", "mpegts", "avi"],
    "demuxers": ["mov,mp4,m4a,3gp,3g2,mj2", "matroska,webm", "mpegts", "avi"],
    "protocols": ["http", "https", "tls", "tcp", "udp", "rtp", "srt", "ftp"],
    "inputDevices": ["dshow", "vfwcap", "openal"],
    "audio": "No audio decoders, encoders, filters, or resampling paths are required; NextNote streams are video-only (-an on every encode)."
  }
}
