diff --git a/src/av1.c b/src/av1.c index e47fb5d..727ffd8 100644 --- a/src/av1.c +++ b/src/av1.c @@ -293,7 +293,21 @@ static void av1_fill_frame(VADecPictureParameterBufferAV1 *picture, ctrl->cdef.uv_sec_strength[i] = uv & 0x03; } - /* ---- loop_restoration ---- (F3) */ + /* ---- loop_restoration ---- (F3) + * Phase 5 review Amendment 1 was REVERTED. The reviewer proposed + * remap = {NONE, SWITCHABLE, WIENER, SGRPROJ} (Kwiboo's table) + * based on AV1 spec FrameRestoreType wire encoding + * {NONE=0, SWITCHABLE=1, WIENER=2, SGRPROJ=3} differing from V4L2's + * {NONE=0, WIENER=1, SGRPROJ=2, SWITCHABLE=3}. Empirically applying + * that permutation regressed ALL tests (allintra 10/10 → 0/10) — + * so either VAAPI's yframe_restoration_type is NOT the raw spec + * value (already-remapped to V4L2 enum semantics?), or vpu981 + * interprets the V4L2 enum values via a different mapping than + * the V4L2 uAPI header documents. Per + * [[feedback_review_empirical_over_theoretical]] keep the + * identity mapping that empirically works; revisit if a + * restoration-using fixture surfaces a real decode bug. + */ { uint8_t remap[4] = { V4L2_AV1_FRAME_RESTORE_NONE, diff --git a/src/picture.c b/src/picture.c index 785b4a4..ef09064 100644 --- a/src/picture.c +++ b/src/picture.c @@ -390,6 +390,18 @@ VAStatus RequestBeginPicture(VADriverContextP context, VAContextID context_id, */ if (surface_object->current_slot != NULL) surface_unbind_slot(driver_data, surface_object); + + /* + * AV1 Phase 5 review Amendment 4: clear any stale + * linked_decode_surface_id from a prior film_grain display→decode + * link. If ffmpeg-vaapi recycles a former display surface as a + * decode target, BeginPicture binds a fresh slot — but without + * this reset, copy_surface_to_image's link-follow would still + * borrow from the now-stale linked surface and serve wrong data. + * Cleared unconditionally (cheap) so the next AV1 grain frame + * re-establishes the link if needed. + */ + surface_object->linked_decode_surface_id = VA_INVALID_SURFACE; { struct cap_pool_slot *cap_slot = cap_pool_acquire(&driver_data->capture_pool, surface_id);