Repository navigation
Conversation
ffmpeg's `select` on `n` assumes decoded picture *n* is message *n*. When a pass-through camera loses a keyframe, the decoder drops the pictures that depend on it (and conceals one), so every later index returned a picture shifted by the shortfall while keeping the requested message's log time: the regression below asked for messages 41 and 50 of a 60-frame stream that lost source frame 30 and got pictures 50 and 59 back, with no error. Each requested index now selects the picture nearest k/fps -- the MP4 is constant rate, so message k is the picture at that time. A picture the decoder never produced matches nothing and the existing extracted-count check reports the request instead of returning a shifted frame, which is the contract the issue asks for. The regression encodes the source frame number into each picture as ten black/white blocks, so the check compares the picture inside the returned JPEG against the message that was asked for. RED on 6cf6e98: [50, 59] instead of [42, 51]; GREEN after the change, including a request inside the gap that now raises. Refs Hebbian-Robotics#727
[Medium impact] The PR appears safe to merge; no blocking issues remain.
|
`%g` prints six significant digits, so index 250001 at 25 fps compiled to `between(t,10000,10000.1)` -- a window wide enough to also match indices 250000 and 250002, which reintroduced the shifted-picture bug this branch fixes once the selection lands past six-digit timestamps. Format both boundaries with round-trip precision and assert a large-index window stays exactly one frame wide. Signed-off-by: Ayam <ayamullahkhan04@gmail.com>
kstonekuan
left a comment
There was a problem hiding this comment.
Could you invalidate the old indexed-frame cache and add upgrade coverage? With the regression's damaged stream and indices [41, 50], I populated a workdir using main's counter selection, then reopened it on this head: it still returns pictures [50, 59]; a fresh workdir returns the correct [42, 51].
Please also change Fixes #727 to Refs #727: #731 tracks sampled frames, but the concealed-picture case from #727 still needs to stay open.
The frame cache directory is its own key, so the selection change from Hebbian-Robotics#727 left every workdir populated before it holding pictures that are shifted after a lost keyframe: reopening the same workdir returned the counter selection's output with no error, which is what a reviewer reproduced on the regression's damaged stream (indices [41, 50] returned pictures [50, 59] from a workdir built on main, [42, 51] from a fresh one). The directory name now carries a layout tag, `v2-time`, so a cache written by the counter selection is never read again. The tag is a constant rather than part of the digest because the cache key has to change when the selection semantics change, not when the indices do. The new regression recreates exactly that upgrade: it writes the pictures main produced -- frame numbers 50 and 59 -- into the directory main named, under the workdir the episode opens, and then reads the same indices from that workdir. Without the tag the call returns [50, 59]; with it, [42, 51], and every returned path is outside the retired directory. - `pytest tests/test_episode.py tests/test_end_to_end.py -q` -- 53 passed. - RED with the tag removed: `assert [50, 59] == [42, 51]`, the reported symptom. - `ruff check`, `ruff format --check`, `ty check` -- clean. Refs Hebbian-Robotics#727 Signed-off-by: Ayam <ayamullahkhan04@gmail.com>
Dismissed because a newer commit was pushed; Greptile will re-review the current head.
|
Both done in 35d358a. Cache invalidation. You were right that the stale workdir was the whole risk: the cache directory name is the key, and the selection change left it unchanged, so a workdir built on main kept serving the counter selection's pictures. The name now carries a layout tag: _FRAMES_AT_INDICES_CACHE_LAYOUT = "v2-time"
f"frames_{_sanitize_topic(topic)}_indices_{selection_digest}_"
f"count_{len(selected_frame_indices)}_{_FRAMES_AT_INDICES_CACHE_LAYOUT}"It is a constant rather than part of the digest because the key has to change when the selection semantics change, not when the indices do. Every directory written before this change is retired by name; nothing is deleted, so a concurrent reader of an old workdir is never raced or surprised mid-read. Upgrade coverage. The new regression builds your scenario directly: it takes the damaged stream from #727, writes the pictures main produced for indices
Gate on this head: |
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
What changed
frames_at_indicesselected pictures with ffmpeg'sselecton the decoded-picture countern, which assumes decoded picture n is message n. On a pass-through camera that loses a keyframe the decoder drops the pictures that depend on it (and conceals one), so every index after the gap returned a picture shifted by the shortfall while still reporting the requested message'slog_time_ns.The selection now keys on time: the MP4 is constant rate, so message k is the picture nearest
k / fps, and each requested index (or run of consecutive indices) compiles tobetween(t,(start-0.5)/fps,(end+0.5)/fps). A picture the decoder never produced matches nothing, so the existing "ffmpeg extracted X of Y selected frames" check raises instead of handing back a shifted frame, which is the contract #727's Expected behavior asks for.Validation
RED before the change, GREEN after, on the regression added here:
The regression pins content, not counts: each source picture carries its own frame number as ten black/white blocks and the test reads that number back out of the returned JPEG. It also requests frames inside the gap, which now raises.
Gate (WSL, the worktree's
uv sync --locked --all-extrasenvironment):Notes
frames_at_indicesreturns frames shifted by several positions, without an error, after a pass-through H.264 camera loses a keyframe #727: refusing or quarantining a channel with a lost reference at transform time, and catching the single concealed picture that a gap can still admit (that needs H.264frame_numor the keyframe-cadence check)._frame_selection_expression, since the expression is built from timestamps.Refs #727
Need help on this PR? Tag
@codesmith-botwith what you need.