Skip to content
Go back
FFmpeg

The open source multimedia framework that decodes, encodes and converts video and audio inside a great deal of other software.

H.264 data partitioning in FFmpeg

avcodec/h264dec: implement slice data partitioning

FFmpeg's H.264 decoder now decodes streams that split each slice into three separately transmitted partitions. Support for them was removed in 2015 as never having worked.

Status
Merged
Merged
31 Aug 2026
Area
libavcodec · H.264 decoder
C
Diff
305 lines added and 22 removed across 18 files

The problem

H.264’s data partitioning splits each slice into up to three NAL units:

A decoder that receives A but loses C can still reconstruct something useful, which is the point: it’s an error-resilience feature for lossy transports. The Extended profile allows it, and some CCTV cameras use it.

FFmpeg had partial support once. It was removed in 2015 with the note “does not work correctly and apparently never did,” along with the claim that nothing but the reference software used the feature. The defect was that partitions B and C were read from the start of their payload, skipping their slice_id, colour_plane_id and redundant_pic_cnt headers. Every residual read therefore began at the wrong bit offset. Since then, FFmpeg has rejected these streams outright.

What I changed

Judgement calls

The spec and the reference software disagree. Clause 9.2.1 of the standard says that, under constrained intra prediction, an inter-coded neighbour is unavailable when deriving nC for an intra macroblock’s coefficient token. JM, the ITU reference encoder and decoder, instead treats that neighbour as available with a count of zero, so it still counts in the average. On a JM-encoded stream the literal reading puts the residual out of sync. Every partitioned stream in the wild comes from JM or something derived from it, so JM’s behaviour has to be the one that works by default.

I first implemented JM’s behaviour and flagged the divergence in the PR. The maintainer who reviewed and merged it asked for the decoder to support both, following the existing workaround_bugs convention. The result is a new flag, FF_BUG_H264_DP_NNZ. It is switched on automatically when the first partition A is seen, and -bug 0 gives the standard’s reading. Streams without data partitioning decode identically either way.

Arbitrary slice order is out of scope. The standard allows B and C to be separated from their A when slices arrive out of order. That case is reported as unsupported rather than decoded wrongly, and the maintainer agreed to leave it for later.

What review changed

FFmpeg’s automated reviewer went five rounds on the series. It found real problems: partitions from one picture could be matched to the next, a scan was quadratic on many-slice pictures, and hardware decoding could slip through on the first partition. It also found intermediate commits that introduced a problem a later commit fixed. FFmpeg expects every commit to stand on its own, so I rewrote the series into eight commits that each build and are correct by themselves.

On the mailing list, one developer repeated the 2015 argument: that data partitioning is theoretical and not worth the code. The answer was a real stream from a CCTV camera that uses it, published in FFmpeg’s sample archive.

Outcome

Merged on 31 August 2026, six days after it was opened. FFmpeg’s Changelog lists “H.264 data partitioning support” for the next release after 9.0.

Timeline

  1. 25 Aug 2026
    Pull request opened
  2. 31 Aug 2026
    Merged after 6 days in review

All open source work →