FFmpeg 9.0

enz1 pts0 comments

FFmpeg 9.0 — Jean-Baptiste Kempf

04 AUG 2026<br>VIDEOLAN<br>13 min read

FFmpeg 9.0

FFmpeg 9.0: swscale, Vulkan, WebP, asm and a big cleanup

FFmpeg 9.0 &ldquo;Lei&rdquo; is out.

FFmpeg needs no introduction: it is the engine room of everything multimedia, from every player to every transcoding workflow, and VLC uses libavcodec and libavformat heavily. The FFmpeg and VideoLAN communities have always been close and share quite a few developers, often meeting at FOSDEM and VDD.

FFmpeg 9.0 is a major release. It comes four and a half months after 8.1 &ldquo;Hoare&rdquo;, with more than 2200 commits from over 160 authors , touching 1781 files, adding almost 85000 lines and deleting more than 33000. It bumps the major version of all seven libraries (libavutil 61, libavcodec 63, libavformat 63, libavdevice 63, libavfilter 12, libswscale 10, libswresample 7), which means an ABI break across the board, and it means the big cleanup that FFmpeg only allows itself at major bumps.

Let me go through it, subsystem by subsystem.

swscale, rewritten

The most important long-term work in this release is invisible on a feature list: the multi-year rewrite of swscale , led by Niklas Haas, who landed more than 300 commits in libswscale alone this cycle, with Ramiro Polla close behind on the ARM side.

The old swscale is twenty years of bespoke, format-specific conversion code. The new architecture is completely different: every conversion is decomposed into a list of elementary operations (read, swizzle, linear transform, scale, pack…), an optimizer simplifies and splits that list, and a backend then compiles it into a chain of kernels.

In 9.0 this becomes user-visible: the public API gains an SwsBackend selector, and the backends now include the template-based C reference, a fast memcpy path, chained x86 SIMD kernels , chained AArch64 NEON kernels , and a Vulkan SPIR-V backend that compiles the same operation lists into compute shaders, so the exact same conversion graph can run on the CPU or on the GPU. There is also a new SwsScaler enum to pick the scaling algorithm explicitly, instead of the old flags soup.

The correctness engineering underneath is the part I like. The constant math driving every conversion moved to a new 64-bit rational type, computed exactly instead of in floating point, which let a whole series of overflow checks simply disappear. Ask for SWS_BITEXACT and even the Vulkan backend complies, down to decorating its linear arithmetic with SPIR-V NoContraction so the GPU is not allowed to fuse multiply-adds; leave it off and you get a faster matrix-multiply variant instead. And the optimizer learned to split operation lists per plane and into linked subpasses, so a planar conversion compiles into independent kernels per plane instead of one monolithic loop.

The new paths are still gated behind SWS_UNSTABLE, with the legacy code as the stable default. This cycle also brought palette (PAL8) support to the new architecture, with an AVX2 path for palette reads, and proper modelling of interlaced content in the format negotiation. The architecture is now in place.

You should look at Niklas&rsquo; talk at the last VDD about this topic.

libavcodec

More than 700 commits landed in libavcodec. The most important ones:

FFmpeg can finally decode animated WebP , natively, with a demuxer to go with it. This closes ticket #4907 , opened in 2015, a regular of &ldquo;why does FFmpeg only decode the first frame?&rdquo; threads for a decade. The patches were originally started by Josef Zlomek, and Ramiro Polla finally finished it: it was more complex than anticipated, notably with RGB and YUV cases.

The AAC decoder now handles 960-sample frames , the variant used by DAB+ digital radio.

NVENC gains AV1 hierarchical B-frame reference mode, compatibility with Video Codec SDK 13.1, and accepts 12-bit input formats (truncated to 10 bits).

We have a video encoder and muxer for the Playdate , the little yellow console with a crank. It produces 1-bit, 400×240 video using delta coding and zlib compression. It is not important, but it is cool.

A new decoding API, avcodec_receive_frame_flags(), with an AV_CODEC_RECEIVE_FRAME_FLAG_SYNCHRONOUS flag that bypasses frame-threading delay and returns the next frame as soon as possible. This is useful for low-latency consumers that still want threaded decoding the rest of the time.

Assembly and SIMD: x86, NEON and RISC-V

FFmpeg still writes assembly, and this cycle was busy: nearly 200 commits touched the x86 directories, and about a hundred the ARM ones.

On x86 , a large part of the work is Andreas Rheinhardt dragging the oldest DSP code in the tree into the present: the half-pel motion compensation code (hpeldsp and fpel, which date back to the MMX era) was ported to SSE2, the H.264 intra prediction gained AVX2 horizontal predictors, the pp7 postprocessing DCT left MMX behind, and the last MMX remnants were removed from mpegvideoenc. The motion-estimation compare functions gained...

ffmpeg conversion swscale libavcodec commits code

Related Articles