-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Refactor EventStream::sendFrame to use reusable filepath member #4616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
678562a
a843684
a335da1
f61a2e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -845,27 +845,29 @@ bool EventStream::sendFrame(Microseconds delta_us) { | |
| curr_frame_id = std::clamp(curr_frame_id, 1, (int)event_data->frames.size()); | ||
| } | ||
|
|
||
| std::string filepath; | ||
| // Reusable string member avoids per-frame heap allocations. | ||
| // After the first frame, the string's buffer is reused (unless path exceeds capacity). | ||
| reuse_filepath_.clear(); | ||
| struct stat filestat = {}; | ||
|
|
||
| // This needs to be abstracted. If we are saving jpgs, then load the capture file. | ||
| // If we are only saving analysis frames, then send that. | ||
| if ((frame_type == FRAME_ANALYSIS) && (event_data->SaveJPEGs & 2)) { | ||
| filepath = stringtf(staticConfig.analyse_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(filepath.c_str(), &filestat) < 0) { | ||
| Debug(1, "analyze file %s not found will try to stream from other", filepath.c_str()); | ||
| filepath = stringtf(staticConfig.capture_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(filepath.c_str(), &filestat) < 0) { | ||
| Debug(1, "capture file %s not found either", filepath.c_str()); | ||
| filepath = ""; | ||
| reuse_filepath_ = stringtf(staticConfig.analyse_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(reuse_filepath_.c_str(), &filestat) < 0) { | ||
| Debug(1, "analyze file %s not found will try to stream from other", reuse_filepath_.c_str()); | ||
| reuse_filepath_ = stringtf(staticConfig.capture_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(reuse_filepath_.c_str(), &filestat) < 0) { | ||
| Debug(1, "capture file %s not found either", reuse_filepath_.c_str()); | ||
| reuse_filepath_.clear(); | ||
| } | ||
| } | ||
| } else if (event_data->SaveJPEGs & 1) { | ||
| filepath = stringtf(staticConfig.capture_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(filepath.c_str(), &filestat) < 0) { | ||
| reuse_filepath_ = stringtf(staticConfig.capture_file_format.c_str(), event_data->path.c_str(), curr_frame_id); | ||
| if (stat(reuse_filepath.c_str(), &filestat) < 0) { | ||
|
Comment on lines
851
to
+867
|
||
| Debug(1, "Capture file %s not found (bulk/interpolated frame %d), trying ffmpeg_input", | ||
| filepath.c_str(), curr_frame_id); | ||
| filepath = ""; | ||
| reuse_filepath.c_str(), curr_frame_id); | ||
| reuse_filepathi.clear(); | ||
| // Fall through — ffmpeg_input will be tried below if available | ||
|
Comment on lines
+866
to
871
|
||
| } | ||
| } else if (!ffmpeg_input) { | ||
|
|
@@ -874,7 +876,7 @@ bool EventStream::sendFrame(Microseconds delta_us) { | |
| } | ||
|
|
||
| if ( type == STREAM_MPEG ) { | ||
| Image image(filepath.c_str()); | ||
| Image image(reuse_filepath_.c_str()); | ||
|
|
||
| Image *send_image = prepareImage(&image); | ||
|
|
||
|
|
@@ -889,19 +891,19 @@ bool EventStream::sendFrame(Microseconds delta_us) { | |
| config.mpeg_timed_frames, | ||
| delta_us.count() * 1000); | ||
| } else { | ||
| bool send_raw = (type == STREAM_JPEG) && ((scale >= ZM_SCALE_BASE) && (zoom == ZM_SCALE_BASE)) && !filepath.empty(); | ||
| bool send_raw = (type == STREAM_JPEG) && ((scale >= ZM_SCALE_BASE) && (zoom == ZM_SCALE_BASE)) && !reuse_filepath_.empty(); | ||
|
|
||
| if (send_raw) { | ||
| fprintf(stdout, "--" BOUNDARY "\r\n"); | ||
| if (!send_file(filepath)) { | ||
| Error("Can't send %s: %s", filepath.c_str(), strerror(errno)); | ||
| if (!send_file(reuse_filepath_)) { | ||
| Error("Can't send %s: %s", reuse_filepath_.c_str(), strerror(errno)); | ||
| return false; | ||
| } | ||
| } else { | ||
| Image *image = nullptr; | ||
|
|
||
| if (!filepath.empty()) { | ||
| image = new Image(filepath.c_str()); | ||
| if (!reuse_filepath_.empty()) { | ||
| image = new Image(reuse_filepath_.c_str()); | ||
| } else if (ffmpeg_input) { | ||
| // Get the frame from the mp4 input | ||
| const FrameData *frame_data = &event_data->frames[curr_frame_id-1]; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -127,6 +127,7 @@ class EventStream : public StreamBase { | |||||
| bool send_buffer(uint8_t * buffer, int size); | ||||||
| Storage *storage; | ||||||
| FFmpeg_Input *ffmpeg_input; | ||||||
| std::string reuse_filepath_; // reused across sendFrame calls to avoid per-frame heap alloc | ||||||
|
||||||
| std::string reuse_filepath_; // reused across sendFrame calls to avoid per-frame heap alloc | |
| std::string reuse_filepath_; // reused across sendFrame calls to reuse capacity and reduce per-frame heap allocations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new comments claim this avoids per-frame heap allocations, but
stringtf()allocates a heap buffer (unique_ptr<char[]>) on every call. Reusing the destinationstd::stringcapacity only avoids reallocation ofreuse_filepath_itself, not the allocations insidestringtf(). To actually eliminate per-frame heap allocations, keep the priorsnprintf/stack-buffer approach or introduce a formatter that writes directly intoreuse_filepath_(e.g.,vsnprintfinto a resized string buffer).