# Frame Decoder (NVDEC + Software Fallback) **Task**: AZ-658_frame_ingest_decoder **Name**: H.264/265 decoder (NVDEC primary, software fallback) + monotonic timestamps **Description**: Decode H.264/265 to raw frames using NVDEC on Jetson Orin Nano, with software fallback. Stamp each frame with a monotonic capture timestamp + sequence number at the earliest practical point in the pipeline. **Complexity**: 5 points **Dependencies**: AZ-640_initial_structure, AZ-657_frame_ingest_rtsp_session **Component**: frame_ingest **Tracker**: AZ-658 **Epic**: AZ-627 ## Problem Every frame downstream needs a monotonic capture timestamp so `movement_detector` can detect telemetry skew. Decoding must use the hardware decoder (NVDEC on Jetson) where present and fall back to software otherwise, without changing the emitted `Frame` shape. Decode errors on a single frame must be dropped (counted), not abort the stream — cold-start latency is observable once but not an alert by itself. ## Outcome - `FrameDecoder::decode(packet) -> Result` emits a `Frame { seq, capture_ts_monotonic, decode_ts_monotonic, pixels: Arc, width, height, pix_fmt, ai_locked }`. - NVDEC code path is used when available; software fallback otherwise (selection is automatic and observable in health). - Single-frame errors are dropped and counted as `decode_errors_total`; the stream is never aborted on a single frame. - Cold-start latency (first-frame decode time) is surfaced as `decode_ms_first_frame` once per session open. - Health surface: `decode_ms_p50`, `decode_ms_p99`, `decoder_backend ∈ {NVDEC, Software}`, `decode_errors_total`. ## Scope ### Included - NVDEC binding (via Jetson Multimedia API or GStreamer `nvv4l2decoder`). - Software decoder fallback (FFmpeg `libavcodec`). - Monotonic timestamping at the earliest point in the decode pipeline. - Sequence-number generation (monotonic u64 per session). - Single-frame error handling. ### Excluded - RTSP session lifecycle (task 18). - Multi-consumer publisher (task 20). ## Acceptance Criteria **AC-1: Software-path decode of a sample stream** Given a sample H.264 RTSP stream at 1080p / 30 fps and a host without NVDEC When the decoder runs for 10 s Then ≥285 frames are emitted; `decoder_backend = "Software"`; sequence numbers are strictly monotonic. **AC-2: NVDEC-path selection on Jetson** Given the host has NVDEC available When the decoder is initialized Then `decoder_backend = "NVDEC"`; functional correctness is identical to software path. **AC-3: Single-frame decode error does not abort the stream** Given the input contains one corrupted frame When the decoder runs Then that single frame is dropped, `decode_errors_total` increments by 1, and subsequent frames continue to be emitted. **AC-4: Monotonic timestamps** Given a sequence of decoded frames When their `capture_ts_monotonic` is read Then values are strictly monotonically increasing. ## Non-Functional Requirements **Performance** - End-to-end RTSP-rx → publish ≤30 ms p99 on Jetson Orin Nano (per `description.md §8`); decoder portion of that budget ≤20 ms p99. **Reliability** - Single-frame errors do not abort the stream. - Cold-start latency surfaced once; not an alert. ## Runtime Completeness - **Named capability**: H.264/265 decode (NVDEC primary, software fallback) — production decode path required. - **Production code that must exist**: real NVDEC binding; real software fallback; real monotonic timestamping. - **Unacceptable substitutes**: software-only decode on Jetson is acceptable as fallback but the NVDEC code path MUST exist (otherwise the latency target cannot be met).