Skip to content

Decode video frames at the publish rate, not the stream rate - #109

Merged
leandropineda merged 1 commit into
mainfrom
perf/decode-at-publish-rate
Jul 29, 2026
Merged

Decode video frames at the publish rate, not the stream rate#109
leandropineda merged 1 commit into
mainfrom
perf/decode-at-publish-rate

Conversation

@leandropineda

Copy link
Copy Markdown
Member

Re-targets #106, which was merged into #105's branch instead of main, so this change never reached main. Same commit, cherry-picked onto main; already reviewed and approved there by @miguelgarcia.

Two costs in the capture loop:

  • it held capture_mutex across every grab(), so get_frame_jpg() waited on the lock at each publish — with a blocking network grab in between, publishing starved;
  • retrieve() ran per publish on frames grab() had already decoded, paying the YUV→BGR conversion and copy twice (4.5ms vs 7.1ms per frame at 1080p).

Now only the capture thread touches self.capture, so the loop takes no lock: it drains with grab() and converts into a buffer at twice the publish rate. get_frame_jpg() encodes the buffer and never touches the capture.

Suite green (149), flake8/black clean. #107 and #108 are stacked on this branch.

The grab loop held capture_mutex across every grab(), so get_frame_jpg()
had to wait for the lock on each publish -- with a blocking network grab
in between, that starved publishing for seconds at a time. And retrieve()
ran once per publish on a capture whose every frame had already been
decoded, paying the YUV->BGR conversion and copy again (4.5ms vs 7.1ms
per frame at 1080p: 13.5% vs 21.3% of a core at 30fps).

Only the capture thread touches self.capture now, so the grab loop takes
no lock: it drains the stream with grab() and converts a frame into a
buffer at twice the publish rate. get_frame_jpg() encodes whatever is in
the buffer and never touches the capture. Frame size comes from the frame
itself instead of two CAP_PROP queries per publish.

Tests: 1 new case in test_video.py (grabs >> retrieves, publishing does
not touch the capture).
@leandropineda
leandropineda merged commit 8da9892 into main Jul 29, 2026
24 checks passed
@leandropineda
leandropineda deleted the perf/decode-at-publish-rate branch July 29, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant