codec_store_buffer: resize / re-allocate source_data on resolution upshift (root cause for #13) #15
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #13 (closed by PR #14) — the bounds checks landed in PR #14 are the memory-safety floor, not the actual fix. With them in place a resolution upshift produces a graceful
VA_STATUS_ERROR_ALLOCATION_FAILEDto libavcodec instead of a SIGSEGV inside thememcpy, which gives the consumer a chance to re-create the surface — but it still means that decoded frame is dropped and the consumer has to do the recovery itself. The right behaviour is for the libva backend to absorb the resize transparently.Where the buffer comes from
surface_object->source_datais mirrored inBeginPicturefrom an OUTPUT-pool slot:The slot's
data/sizewere set once inrequest_pool_init:i.e. the kernel driver's negotiated
sizeimagefrom theS_FMTthat ran duringCreateContext. That number is fixed for the life of the pool — no path in the backend ever re-S_FMTs OUTPUT or re-mmaps the slot.So any stream-level resolution upshift that lifts the per-frame slice budget past the original
S_FMT'ssizeimagewill trip the new bounds check forever, until the libva client tears down the context and re-creates one.Two viable shapes for the proper fix
Shape A — re-
S_FMT+ re-init the OUTPUT pool on detected upshiftcodec_store_buffer, when the bounds check would fire, call a newoutput_pool_resize(driver_data, needed_bytes)instead of returning the error immediately.output_pool_resizeissuesVIDIOC_STREAMOFF, re-doesS_FMTwith the newsizeimage(or just a generous round-up), re-CREATE_BUFS, re-mmaps, and re-STREAMON. Updates each surface'ssource_data/source_sizemirror on nextBeginPicture.S_FMTif the dimensions don't match the negotiated CAPTURE format on stateless decoders, so the resize has to be coordinated.Gotcha: any surface that's mid-
Begin..Render..Endcycle must finish (or be aborted) before the streamoff. The existing single-context, single-render-surface invariant inpicture.cmakes that tractable — there's only ever one render-surface-id in flight per context.Shape B — over-allocate the OUTPUT pool at
CreateContexttimeIf the libva client tells us the peak dimensions up front (it does —
vaCreateContexttakespicture_widthandpicture_height), oversize the OUTPUTS_FMT'ssizeimageto e.g. 2× the spec maximum slice for that resolution + profile combo. Simpler, but wastes mmap until the libva client tells us the max.The daedalus_v4l2 daemon path is mid-stream-resolution-change-tolerant on its own side (libavcodec rebuilds its parser on a fresh SPS), so the libva-side fix doesn't need to coordinate with the daemon — only with the kernel S_FMT state machine.
Why this matters beyond the SIGSEGV class of failures
Adaptive streaming (DASH/HLS) flips resolution multiple times per minute on cellular. Every flip currently means a destroyed VA context on the consumer side. mpv copes; Firefox's RDD process can be made to cope but the tear-down/rebuild is a stutter the user sees. A libva-side transparent resize would let the same VA context survive a mid-stream upshift.
Sequencing
This is independent of:
Depends on:
cap_pool_init) — that one will need the same kind of resize hook.Suggested label
backlog,refactor,memory-safety(this is the proper fix; PR #14 was the floor).