PR #25831 opened by romainhedouin URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25831 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25831.patch
The encoder wrote h / 2 lines for both the top and the bottom half of a bitmap. For an odd height the last line belongs to the top half, so it was never written and came back empty after decoding. A 1-line bitmap was lost entirely. The top half now gets (h + 1) / 2 lines. Even heights give the same bytes as before. Encoding then decoding the PGS and VobSub samples now gives back every pixel, and the dvbsub FATE tests are unchanged. For a height of 1, our decoder now logs an "Invalid object location" error once for that object. The spec says such an object isn't valid, and before this change the bitmap was lost. Testing: I tested this change against a corpus of thousands of random subtitle sets, even heights (all byte-identical before/after), I tested the output with the VLC decoder, I tested extreme sizes Found during a code review sweep of ffmpeg using an LLM. <!-- If this PR requires new FATE test samples, attach them to the PR and list their target paths below (relative to the fate-suite root). Attached filenames must match the sample's filename: ```fate-samples # e.g. vorbis/new-sample.ogg ``` --> >From b49916f1fcdaa68cd8ffecb7805ea0d800ae2c04 Mon Sep 17 00:00:00 2001 From: romainhedouin <[email protected]> Date: Sat, 7 Nov 2026 13:16:41 +0100 Subject: [PATCH] avcodec/dvbsubenc: encode the last line of odd-height bitmaps An object is coded as two interlaced fields: the top field holds lines 0, 2, 4, ... and the bottom field lines 1, 3, 5, ... (ETSI EN 300 743, 7.2.5), which is also how the decoder places them. Both fields were coded with h >> 1 lines, so for an odd height the last line, which belongs to the top field, was never written; our decoder left it at the region background, pixel code 0. A height of 1 lost the whole bitmap. Bitmaps of odd height are common, for example when converting PGS subtitles; the PGS sample of the FATE suite has two rects of heights 67 and 63, and an encode/decode round trip with our own decoder now gives back every pixel of them. Even heights produce the same bytes as before. Code (h + 1) >> 1 lines in the top field. Each line is still checked against the worst case line size in the RLE coders, so the output buffer checks hold for the extra line. For a height of 1 the bottom field is now empty, which the specification defines as repeating the top field; our decoder then logs that the repeated line lies outside the region and keeps the line it decoded. Found during a code review sweep of ffmpeg using an LLM. Signed-off-by: romainhedouin <[email protected]> --- libavcodec/dvbsubenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/dvbsubenc.c b/libavcodec/dvbsubenc.c index a7507723568..4ba9d954b7e 100644 --- a/libavcodec/dvbsubenc.c +++ b/libavcodec/dvbsubenc.c @@ -526,7 +526,7 @@ static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, h->rects[object_id]->data[0], h->rects[object_id]->w * 2, h->rects[object_id]->w, - h->rects[object_id]->h >> 1); + (h->rects[object_id]->h + 1) >> 1); if (ret < 0) return ret; buf_size -= ret; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
