From: Michael Niedermayer <michael@niedermayer.cc> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH 3/3] [RFC] avcodec/ffv1: Better rounding for slice positions Date: Sat, 7 Oct 2023 02:14:44 +0200 Message-ID: <20231007001444.31861-3-michael@niedermayer.cc> (raw) In-Reply-To: <20231007001444.31861-1-michael@niedermayer.cc> This fixes green lines in some odd dimensions with some slice configurations like Ticket 5548 This also changes the encoder and whats encoded, and would require an update to the specification. This change attempts to limit the change to configurations that have missing lines currently. Testing is welcome and needed Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/ffv1.c | 38 ++++++++++++++++++++++++++++++++++---- libavcodec/ffv1.h | 2 ++ libavcodec/ffv1dec.c | 8 ++++---- libavcodec/ffv1enc.c | 7 ++++--- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index f44fead350b..e780c910aee 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -103,6 +103,36 @@ av_cold int ff_ffv1_init_slices_state(FFV1Context *f) return 0; } +int ff_need_new_slices(int width, int num_h_slices, int chroma_shift) { + int mpw = 1<<chroma_shift; + int i = width * (int64_t)(num_h_slices - 1) / num_h_slices; + + return width % mpw && (width - i) % mpw == 0; +} + +int ff_slice_coord(const FFV1Context *f, int width, int sx, int num_h_slices, int chroma_shift) { + int mpw = 1<<chroma_shift; + int awidth = FFALIGN(width, mpw); + int old = 1; + + if (f->version > 4) { + old = 0; + } else if (f->version == 3 && f->micro_version > 4 || + f->version == 4 && f->micro_version > 2 + ) { + // If the old system will not encode all pixels we will choose the new + old = !ff_need_new_slices(width, num_h_slices, chroma_shift); + } + + if (old) + return width * sx / num_h_slices; + + sx = (awidth * (int64_t)sx + (num_h_slices * mpw / 2)) / (num_h_slices * mpw) * mpw; + if (sx == awidth) + sx = width; + return sx; +} + av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f) { int i, max_slice_count = f->num_h_slices * f->num_v_slices; @@ -112,10 +142,10 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f) for (i = 0; i < max_slice_count;) { int sx = i % f->num_h_slices; int sy = i / f->num_h_slices; - int sxs = f->avctx->width * sx / f->num_h_slices; - int sxe = f->avctx->width * (sx + 1) / f->num_h_slices; - int sys = f->avctx->height * sy / f->num_v_slices; - int sye = f->avctx->height * (sy + 1) / f->num_v_slices; + int sxs = ff_slice_coord(f, f->avctx->width , sx , f->num_h_slices, f->chroma_h_shift); + int sxe = ff_slice_coord(f, f->avctx->width , sx + 1, f->num_h_slices, f->chroma_h_shift); + int sys = ff_slice_coord(f, f->avctx->height, sy , f->num_v_slices, f->chroma_v_shift); + int sye = ff_slice_coord(f, f->avctx->height, sy + 1, f->num_v_slices, f->chroma_v_shift); FFV1Context *fs = av_mallocz(sizeof(*fs)); if (!fs) diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 14e40936065..3f658a26522 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -143,6 +143,8 @@ int ff_ffv1_init_slice_contexts(FFV1Context *f); int ff_ffv1_allocate_initial_states(FFV1Context *f); void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs); int ff_ffv1_close(AVCodecContext *avctx); +int ff_need_new_slices(int width, int num_h_slices, int chroma_shift); +int ff_slice_coord(const FFV1Context *f, int width, int sx, int num_h_slices, int chroma_shift); static av_always_inline int fold(int diff, int bits) { diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index a376a4c8170..0486938eb2b 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -184,10 +184,10 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs) if (sx > f->num_h_slices - sw || sy > f->num_v_slices - sh) return AVERROR_INVALIDDATA; - fs->slice_x = sx * (int64_t)f->width / f->num_h_slices; - fs->slice_y = sy * (int64_t)f->height / f->num_v_slices; - fs->slice_width = (sx + sw) * (int64_t)f->width / f->num_h_slices - fs->slice_x; - fs->slice_height = (sy + sh) * (int64_t)f->height / f->num_v_slices - fs->slice_y; + fs->slice_x = ff_slice_coord(f, f->width , sx , f->num_h_slices, f->chroma_h_shift); + fs->slice_y = ff_slice_coord(f, f->height, sy , f->num_v_slices, f->chroma_v_shift); + fs->slice_width = ff_slice_coord(f, f->width , sx + sw, f->num_h_slices, f->chroma_h_shift) - fs->slice_x; + fs->slice_height = ff_slice_coord(f, f->height, sy + sh, f->num_v_slices, f->chroma_v_shift) - fs->slice_y; av_assert0((unsigned)fs->slice_width <= f->width && (unsigned)fs->slice_height <= f->height); diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 11be7fe32ea..e04695efa93 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -397,7 +397,8 @@ static int write_extradata(FFV1Context *f) int i, j, k; uint8_t state2[32][CONTEXT_SIZE]; unsigned v; - + int need_new_slices = ff_need_new_slices(f->avctx->width , f->num_h_slices, f->chroma_h_shift) + ||ff_need_new_slices(f->avctx->height, f->num_v_slices, f->chroma_v_shift); memset(state2, 128, sizeof(state2)); memset(state, 128, sizeof(state)); @@ -412,9 +413,9 @@ static int write_extradata(FFV1Context *f) put_symbol(c, state, f->version, 0); if (f->version > 2) { if (f->version == 3) { - f->micro_version = 4; + f->micro_version = 4 + need_new_slices; } else if (f->version == 4) - f->micro_version = 2; + f->micro_version = 2 + need_new_slices; put_symbol(c, state, f->micro_version, 0); } -- 2.17.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-10-07 0:15 UTC|newest] Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-10-07 0:14 [FFmpeg-devel] [PATCH 1/3] avcodec/ffv1enc: Slice combination is unsupported Michael Niedermayer 2023-10-07 0:14 ` [FFmpeg-devel] [PATCH 2/3] avcodec/ffv1: Store and reuse sx/sy Michael Niedermayer 2023-10-07 0:14 ` Michael Niedermayer [this message] 2023-10-07 4:52 ` [FFmpeg-devel] [PATCH 3/3] [RFC] avcodec/ffv1: Better rounding for slice positions Jerome Martinez 2023-10-07 17:11 ` Michael Niedermayer
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20231007001444.31861-3-michael@niedermayer.cc \ --to=michael@niedermayer.cc \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git