iter4 fix: fresh request_fd per frame (fixes carryover EINVAL)

This is the load-bearing fix that resolves the iter1+iter2+iter3
"frame-11 EINVAL" carryover. Replace the per-surface request_fd cache
+ MEDIA_REQUEST_IOC_REINIT pattern with allocate-fresh-per-frame:
in RequestSyncSurface, after queue + wait_completion succeed, close
the request_fd and reset surface_object->request_fd = -1 so the next
BeginPicture allocates a new one via media_request_alloc.

Diagnostic root cause: per-control VIDIOC_TRY_EXT_CTRLS isolation
showed all four H.264 controls (SPS/PPS/DECODE_PARAMS/SCALING_MATRIX)
fail individually with EINVAL on the *same* request_fd that had been
through queue+wait+reinit. The fd state was bad even though every
ioctl in the previous decode cycle returned success. Allocating fresh
sidesteps any kernel-side request-state-machine subtlety we don't
fully understand.

Empirical verification (iter4 Phase 7, 90s autonomous run on ohm via
firefox-fourier without MOZ_DISABLE_RDD_SANDBOX=1, bbb_1080p30 H.264):
  - ENETDOWN count: 0
  - S_EXT_CTRLS rejected: 0  (was: fired at frame 11 every iter1-3)
  - Unable to set control(s): 0
  - Generic EINVAL: 0
  - Video stream mTime reached: 49.7 seconds
  - Audio stream mTime reached: 51.5 seconds

Cost: ~one extra MEDIA_IOC_REQUEST_ALLOC + close() per decoded frame.
Negligible (cycles below the V4L2 set_controls + queue + wait stack).

Companion fixes that landed earlier in iter4 to get to this point:
  74d8dd1 — DPB fields=V4L2_H264_FRAME_REF + skip !used entries
            (matches FFmpeg's libavcodec/v4l2_request_h264.c semantics)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-05 14:12:41 +00:00
parent 4892656b3f
commit 385dee1bbf
+13 -5
View File
@@ -461,11 +461,19 @@ VAStatus RequestSyncSurface(VADriverContextP context, VASurfaceID surface_id)
goto error; goto error;
} }
rc = media_request_reinit(request_fd); /*
if (rc < 0) { * iter4: instead of REINITing for reuse, close the request_fd here
status = VA_STATUS_ERROR_OPERATION_FAILED; * and force the next BeginPicture to allocate a fresh one. The cached
goto error; * request_fd path was hitting EINVAL on S_EXT_CTRLS for some surface
} * recycle patterns (4 individual TRY_EXT_CTRLS on the same fd all
* fail with EINVAL — the fd state is bad even though queue+wait+reinit
* appeared successful). Allocating fresh per frame is unambiguous and
* sidesteps any state-lifecycle issue. Tradeoff: ~one extra ioctl per
* frame (MEDIA_IOC_REQUEST_ALLOC + close), negligible cost.
*/
close(request_fd);
surface_object->request_fd = -1;
(void)0; /* placeholder for the now-removed reinit error path */
rc = v4l2_dequeue_buffer(driver_data->video_fd, -1, output_type, rc = v4l2_dequeue_buffer(driver_data->video_fd, -1, output_type,
surface_object->source_index, 1); surface_object->source_index, 1);