aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.dev>2024-07-04 16:28:50 +0200
committerNiklas Haas <git@haasn.dev>2024-08-16 11:43:37 +0200
commitc8bc6fabd79ee19df93f2486b8a6ebeedb7cd27e (patch)
tree5adab4346d67313664a48670801bb5ef3177d543
parent15a67c0947d6fa8ff50607ef26185986813a6fd6 (diff)
downloadffmpeg-c8bc6fabd79ee19df93f2486b8a6ebeedb7cd27e.tar.gz
avfilter/vf_scale: fix 4:1:0 interlaced chroma pos
The current logic hard-coded a check for v_sub == 1. We can extend this logic slightly to cover the case of interlaced 4:1:0 (which has v_sub == 2). Here is a diagram explaining this scenario (with center-siting): a a a a a a a a b b b b b b b b X X a a a a a a a a b b b b b b b b a a a a a a a a b b b b b b b b Y Y a a a a a a a a b b b b b b b b a = even luma rows b = odd luma rows X = even chroma sample Y = odd chroma sample In progressive mode, the chroma samples sit at (384, 384) respectively. Relative to the 8x4 grid of even luma samples (a), the X sample sits at: h_chr_pos = 384 v_chr_pos = 192 Relative to the 8x4 grid of odd luma samples (b), the Y sample sits at: h_chr_pos = 384 v_chr_pos = 576 The new code calculates the correct values in all circumstances.
-rw-r--r--libavfilter/vf_scale.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index ea77bac1c3..afa159914b 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -643,9 +643,19 @@ static void calc_chroma_pos(int *h_pos_out, int *v_pos_out, int chroma_loc,
v_pos = v_pos_override;
/* Fix vertical chroma position for interlaced frames */
- if (v_sub == 1 && index > 0) {
- v_pos += 256 * (index == 2); /* offset by one luma row for odd rows */
- v_pos >>= 1; /* double luma row distance */
+ if (v_sub && index > 0) {
+ /* When vertically subsampling, chroma samples are effectively only
+ * placed next to even rows. To access them from the odd field, we need
+ * to account for this shift by offsetting the distance of one luma row.
+ *
+ * For 4x vertical subsampling (v_sub == 2), they are only placed
+ * next to every *other* even row, so we need to shift by three luma
+ * rows to get to the chroma sample. */
+ if (index == 2)
+ v_pos += (256 << v_sub) - 256;
+
+ /* Luma row distance is doubled for fields, so halve offsets */
+ v_pos >>= 1;
}
/* Explicitly strip chroma offsets when not subsampling, because it