Commit 5734b4cd40 for ffmpeg
commit 5734b4cd4060424274d9178dffbea7c2d23e60df
Author: Rainbaby <r@bgr.jp>
Date: Fri Aug 28 16:18:07 2026 +0900
avcodec/cavsdec: scale direct mode by co-located distance
Clause 9.9.1 b) step 2 divides by BlockDistanceRef, which the
co-located block carries, not by the current picture's distance to the
reference it names. For frame pictures the two agree, so output is
unchanged; a field picture's co-located block can name a distance no
entry of the old two element table held.
Signed-off-by: Rainbaby <r@bgr.jp>
diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c
index 9b83112a06..4d24f8846a 100644
--- a/libavcodec/cavs.c
+++ b/libavcodec/cavs.c
@@ -829,6 +829,8 @@ av_cold int ff_cavs_init(AVCodecContext *avctx)
h->intra_pred_c[INTRA_C_DC_128] = intra_pred_dc_128;
h->mv[7] = un_mv;
h->mv[19] = un_mv;
+ for (int i = 0; i < FF_ARRAY_ELEMS(h->direct_den); i++)
+ h->direct_den[i] = i ? 16384 / i : 0;
return 0;
}
diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h
index 2172ac9ac0..30c51ed6ac 100644
--- a/libavcodec/cavs.h
+++ b/libavcodec/cavs.h
@@ -241,9 +241,14 @@ typedef struct AVSContext {
/* scaling factors for MV prediction */
int sym_factor; ///< for scaling in symmetrical B block
- int direct_den[2]; ///< for scaling in direct B block
int scale_den[2]; ///< for scaling neighbouring MVs
+ /**
+ * 16384 / BlockDistanceRef of clause 9.9.1 b) 3), indexed by the
+ * co-located block's own distance, which is 9 bits (clause 9.4.6.1)
+ */
+ uint16_t direct_den[512];
+
uint8_t *edge_emu_buffer;
int got_keyframe;
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index f53576d787..0dc5cb3700 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -472,7 +472,7 @@ static inline void mv_pred_direct(AVSContext *h, cavs_vector *pmv_fw,
cavs_vector *col_mv)
{
cavs_vector *pmv_bw = pmv_fw + MV_BWD_OFFS;
- unsigned den = h->direct_den[col_mv->ref];
+ unsigned den = h->direct_den[col_mv->dist];
int m = FF_SIGNBIT(col_mv->x);
pmv_fw->dist = h->dist[1];
@@ -1087,9 +1087,6 @@ static int decode_pic(AVSContext *h)
av_log(h->avctx, AV_LOG_ERROR, "sym_factor %d too large\n", h->sym_factor);
return AVERROR_INVALIDDATA;
}
- } else {
- h->direct_den[0] = h->dist[0] ? 16384 / h->dist[0] : 0;
- h->direct_den[1] = h->dist[1] ? 16384 / h->dist[1] : 0;
}
if (h->low_delay)