Decode video frames at the publish rate, not the stream rate - #109
Merged
Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Re-targets #106, which was merged into #105's branch instead of
main, so this change never reachedmain. Same commit, cherry-picked ontomain; already reviewed and approved there by @miguelgarcia.Two costs in the capture loop:
capture_mutexacross everygrab(), soget_frame_jpg()waited on the lock at each publish — with a blocking network grab in between, publishing starved;retrieve()ran per publish on framesgrab()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 withgrab()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.