[FFmpeg-devel,3/7] avcodec/ffv1enc: prevent encoder to create buggy streams with small frame sizes

Submitted by Jerome Martinez on March 7, 2018, 3:49 p.m.

Details

Message ID 8d5bea24-1b19-f33c-7fcb-0f685b2710c3@mediaarea.net
State New
Headers show

Commit Message

Jerome Martinez March 7, 2018, 3:49 p.m.
When there is 1 pixel per slice for the first half of slices, the 
encoder creates buggy slices.

Example:
ffmpeg -f lavfi -i mandelbrot=s=8x8 -vf format=yuv444p -t 1 -c ffv1 
-coder 1 -context 0 -g 1 -level 3 -slices 64 -slicecrc 1 a.mkv
ffmpeg -f lavfi -i mandelbrot=s=9x9 -vf format=yuv444p -t 1 -c ffv1 
-coder 1 -context 0 -g 1 -level 3 -slices 64 -slicecrc 1 a.mkv
ffmpeg -f lavfi -i mandelbrot=s=10x10 -vf format=yuv444p -t 1 -c ffv1 
-coder 1 -context 0 -g 1 -level 3 -slices 64 -slicecrc 1 a.mkv
ffmpeg -f lavfi -i mandelbrot=s=11x11 -vf format=yuv444p -t 1 -c ffv1 
-coder 1 -context 0 -g 1 -level 3 -slices 64 -slicecrc 1 a.mkv
ffmpeg -f lavfi -i mandelbrot=s=12x12 -vf format=yuv444p -t 1 -c ffv1 
-coder 1 -context 0 -g 1 -level 3 -slices 64 -slicecrc 1 a.mkv
then for each file:
ffmpeg -i a.mkv
[ffv1 @ 000001977d8ee240] bytestream end mismatching by -1
etc

This patch is an hotfix for preventing the encoder to create such stream.
From 1c78e038a9fb826c70d7b609430a92d5e98ce1de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Martinez?= <jerome@mediaarea.net>
Date: Wed, 7 Mar 2018 10:40:05 +0100
Subject: [PATCH 3/7] avcodec/ffv1enc: prevent encoder to create buggy streams
 with small frame sizes

The first half of slices must have more than 1 pixel else encoder does not correctly handle slice_x and/or slice_y
---
 libavcodec/ffv1enc.c | 4 ++++
 1 file changed, 4 insertions(+)

Patch hide | download patch | download mbox

diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index ac8b715b74..51aa8c2898 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -864,6 +864,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
         int plane_count = 1 + 2*s->chroma_planes + s->transparency;
         int max_h_slices = AV_CEIL_RSHIFT(avctx->width , s->chroma_h_shift);
         int max_v_slices = AV_CEIL_RSHIFT(avctx->height, s->chroma_v_shift);
+        while (max_h_slices && ((float)(avctx->width >> (s->chroma_h_shift))) / max_h_slices <= 1.5) // Hotfix: the first half of slices must have more than 1 pixel else encoder does not correctly handle slice_x
+            max_h_slices--;
+        while (max_v_slices && ((float)(avctx->height >> (s->chroma_v_shift))) / max_v_slices <= 1.5) // Hotfix: the first half of slices must have more than 1 pixel else encoder does not correctly handle slice_y
+            max_v_slices--;
         s->num_v_slices = (avctx->width > 352 || avctx->height > 288 || !avctx->slices) ? 2 : 1;
 
         s->num_v_slices = FFMIN(s->num_v_slices, max_v_slices);