diff --git a/src/h265.c b/src/h265.c index dd5104e..ba764ee 100644 --- a/src/h265.c +++ b/src/h265.c @@ -526,28 +526,10 @@ int h265_set_controls(struct request_data *driver_data, bool iqmatrix_set = surface_object->params.h265.iqmatrix_set; unsigned int num_slices = surface_object->params.h265.num_slices; - /* - * iter18 α-21: heap-allocate the HEVC control structs (was stack - * locals) to preserve pointer lifetime past MEDIA_REQUEST_IOC_QUEUE. - * - * iter17 kernel pr_info found: rkvdec sees all-zero SPS/PPS/decode_params - * for libva HEVC despite the userspace strace showing correct - * S_EXT_CTRLS payload bytes. Hypothesis: kernel defers - * copy_from_user for compound controls with which=REQUEST_VAL until - * IOC_QUEUE actually runs. Libva's stack locals are freed when - * h265_set_controls returns — before EndPicture's IOC_QUEUE fires. - * - * Quick-test with `static` storage: same struct shape, pointer - * persists indefinitely. If this fixes Bug 5, the leading hypothesis - * is confirmed; will refactor to heap-allocate per-surface in a - * follow-up commit. The static approach IS NOT THREAD-SAFE if libva - * ever has concurrent h265 decode contexts; current campaign single- - * codec single-context isn't impacted. - */ - static struct v4l2_ctrl_hevc_sps sps; - static struct v4l2_ctrl_hevc_pps pps; - static struct v4l2_ctrl_hevc_decode_params decode_params; - static struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_pps pps; + struct v4l2_ctrl_hevc_decode_params decode_params; + struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix; struct v4l2_ctrl_hevc_slice_params *slice_params_array = NULL; struct v4l2_ext_control controls[5]; @@ -645,17 +627,7 @@ int h265_set_controls(struct request_data *driver_data, surface_object->request_fd, controls, n); - /* - * iter18 α-21: do NOT free slice_params_array here. The kernel may - * defer copy_from_user for compound controls with which=REQUEST_VAL - * until MEDIA_REQUEST_IOC_QUEUE runs in EndPicture — after this - * function returns. Freeing here = stale pointer = kernel reads zero. - * - * Leak this per call for now; if α-21 succeeds we'll refactor to - * either store on surface_object (freed at DestroySurfaces) or - * use a per-context arena that recycles between frames. - */ - (void)slice_params_array; /* deliberately leaked: see comment above */ + free(slice_params_array); if (rc < 0) return VA_STATUS_ERROR_OPERATION_FAILED;