Second step of ADR-008. A session spawns ffmpeg with the detected encoder's
args, packages the file as HLS, and is reused while it is alive so two range
requests do not start two ffmpegs.
Three things it has to get right, and all three are about not burning the GPU:
a session nobody is watching is reaped after a few minutes idle; concurrent
sessions are capped rather than queued, because a GPU encodes one or two
streams and a queue would just make everyone wait longer; and Shutdown stops
everything so a restart does not leave ffmpeg running.
Found a real bug in review, and it is the kind that only a real host catches.
The hardware args were placed BEFORE -i. ffmpeg reads options before the input
as INPUT options, so "-c:v h264_nvenc" was looked up as a decoder and failed
with "Unknown decoder 'h264_nvenc'". Transcoding would have produced nothing on
any NVENC host while looking correct in the code.
Verified against the real hardware rather than reasoned about: the same ffmpeg
command produces zero segments with the args before -i and a valid playlist and
segments with them after. The test now asserts the ordering directly and names
the reason, so a future reordering fails with an explanation instead of two arg
lists. Red-green: moving them back fails with "the hardware args must follow
the input".
Verified end-to-end on this host: the Manager started a session against a real
20-second file and produced a 132-byte EVENT playlist and segments.
Known limit: a stopped session leaves its segment directory on disk, so the
cache directory needs pruning out of band.
First step of ADR-008. internal/transcode answers one question: can this host
hardware-transcode, and with which encoder.
The rule the package exists to enforce is that a device node is not proof. A
node can exist while the driver cannot encode, and that produces the worst
outcome ADR-008 describes: a transcode that starts, looks like it works, and
then cannot keep up. So every candidate runs a real two-frame probe encode and
is dropped unless that encode exits cleanly.
This host is a perfect illustration and the reason the rule is not theoretical:
it has /dev/dri/renderD128 AND Nvidia nodes. The render node exists, but VAAPI
fails to initialise against it ("Failed to initialise VAAPI connection"). A
detection that trusted the node would have picked VAAPI and been wrong. The
probe rejected it and selected NVENC, which was verified independently with
ffmpeg outside this code.
The probe is injected, so every branch is testable with no hardware present,
including the important one: device present, probe fails. Verified red-green -
ignoring the probe result fails TestDetectProbeFails with "got vaapi, want no
capability".
One real bug found while proving it: the probe used testsrc=size=64x48, below
NVENC's minimum frame size, so a host with working NVENC would have reported no
capability at all. Raised to 320x240, still two frames.
Also added internal/transcode to the arch layer map as a layer-1 primitive
beside probe and engine, which the arch rule caught immediately.
Not wired into the engine registry or playback yet - that is the next step.