diff --git a/src/av1.c b/src/av1.c index 5b2970c..964c035 100644 --- a/src/av1.c +++ b/src/av1.c @@ -53,11 +53,14 @@ #include "av1.h" #include "context.h" +#include "object_heap.h" #include "request.h" #include "surface.h" #include "utils.h" #include "v4l2.h" +#include + #include #include @@ -359,11 +362,13 @@ static void av1_fill_frame(VADecPictureParameterBufferAV1 *picture, } /* ---- reference frames + order hints ---- */ - for (i = 0; i < BACKEND_AV1_TOTAL_REFS_PER_FRAME; i++) { - /* VAAPI doesn't expose order_hints[]; leave zero. */ + /* reference_frame_ts[] is filled by the orchestrator (av1_set_controls) + * which has driver_data for the SURFACE() lookup. order_hints[] not + * exposed per-ref by VAAPI — leave zero. ref_frame_idx[7] is the + * index map from spec-defined ref slots (LAST..ALTREF) into + * ref_frame_map[8] (the surface IDs). */ + for (i = 0; i < BACKEND_AV1_TOTAL_REFS_PER_FRAME; i++) ctrl->order_hints[i] = 0; - ctrl->reference_frame_ts[i] = 0; - } for (i = 0; i < BACKEND_AV1_REFS_PER_FRAME; i++) ctrl->ref_frame_idx[i] = picture->ref_frame_idx[i]; @@ -534,6 +539,29 @@ int av1_set_controls(struct request_data *driver_data, av1_fill_sequence(picture, &sequence); av1_fill_frame(picture, &frame); + + /* + * Phase 2.1 + frame-2 divergence fix: wire reference_frame_ts[]. + * VAAPI exposes ref_frame_map[8] as VASurfaceIDs; the kernel needs + * v4l2-style timestamps to cross-reference the corresponding + * CAPTURE buffers (set on the OUTPUT buffer at QBUF time per + * picture.c::EndPicture, via surface_object->timestamp). Mirrors + * the vp9.c:614-628 pattern, scaled to AV1's 8 ref slots. + * + * VA_INVALID_SURFACE entries stay at the calloc'd zero timestamp + * (kernel reads zero, doesn't try to dereference). + */ + for (i = 0; i < BACKEND_AV1_TOTAL_REFS_PER_FRAME; i++) { + VASurfaceID ref_id = picture->ref_frame_map[i]; + struct object_surface *ref_surface; + if (ref_id == VA_INVALID_SURFACE) + continue; + ref_surface = SURFACE(driver_data, ref_id); + if (ref_surface) + frame.reference_frame_ts[i] = + v4l2_timeval_to_ns(&ref_surface->timestamp); + } + if (driver_data->has_av1_film_grain) av1_fill_film_grain(picture, &film_grain);