Skip to content

Commit 0c27608

Browse files
authored
Merge pull request #12 from nicolasroche898/fix_chunk_timing
mp4ctl: rewrite recording loop to fix chunk timing inconsistencies
2 parents fde16d2 + d817799 commit 0c27608

File tree

1 file changed

+9
-68
lines changed

1 file changed

+9
-68
lines changed

src/MP4ControlSocket.cpp

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -99,32 +99,7 @@ std::array<std::shared_ptr<LoopState>, NUM_VIDEO_CHANNELS> loop_states;
9999
std::array<std::thread, NUM_VIDEO_CHANNELS> loop_threads;
100100
std::mutex loop_state_mutex;
101101

102-
std::chrono::system_clock::time_point round_up_to_minute(std::chrono::system_clock::time_point tp) {
103-
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(tp);
104-
auto epoch_seconds = seconds.time_since_epoch();
105-
auto remainder = epoch_seconds.count() % 60;
106-
if (remainder == 0) {
107-
return seconds;
108-
}
109-
return seconds + std::chrono::seconds(60 - remainder);
110-
}
111102

112-
bool sleep_until_time(std::chrono::system_clock::time_point target, std::atomic<bool> *stop_flag = nullptr) {
113-
while (true) {
114-
if (stop_flag && stop_flag->load(std::memory_order_relaxed)) {
115-
return false;
116-
}
117-
auto now = std::chrono::system_clock::now();
118-
if (now >= target) {
119-
return true;
120-
}
121-
auto remaining = std::chrono::duration_cast<std::chrono::milliseconds>(target - now);
122-
if (remaining > std::chrono::milliseconds(250)) {
123-
remaining = std::chrono::milliseconds(250);
124-
}
125-
std::this_thread::sleep_for(remaining);
126-
}
127-
}
128103

129104
struct MountEntry {
130105
fs::path mountPoint;
@@ -860,63 +835,29 @@ void loop_worker(int channel, std::shared_ptr<LoopState> state) {
860835
return;
861836
}
862837

863-
constexpr auto kMinute = std::chrono::seconds(60);
864-
constexpr auto kShortClipThreshold = std::chrono::seconds(15);
865-
866-
bool first_segment_pending = true;
867-
auto next_start = std::chrono::system_clock::now();
838+
constexpr int kShortClipSeconds = 15;
868839

869840
while (!state->stopRequested.load(std::memory_order_relaxed)) {
870-
int segment_duration_seconds = state->params.durationSeconds;
871-
std::chrono::system_clock::time_point segment_start;
872-
873-
if (first_segment_pending) {
874-
segment_start = std::chrono::system_clock::now();
875-
auto boundary = round_up_to_minute(segment_start);
876-
if (boundary <= segment_start) {
877-
boundary += kMinute;
878-
}
879-
auto span = std::chrono::duration_cast<std::chrono::seconds>(boundary - segment_start);
880-
if (span < kShortClipThreshold) {
881-
boundary += kMinute;
882-
span = std::chrono::duration_cast<std::chrono::seconds>(boundary - segment_start);
883-
}
884-
segment_duration_seconds = static_cast<int>(span.count());
885-
if (segment_duration_seconds <= 0) {
886-
segment_duration_seconds = state->params.durationSeconds;
887-
}
888-
next_start = boundary;
889-
} else {
890-
auto scheduled_start = next_start;
891-
auto now = std::chrono::system_clock::now();
892-
if (scheduled_start > now) {
893-
if (!sleep_until_time(scheduled_start, &state->stopRequested)) {
894-
break;
895-
}
896-
}
897-
segment_start = scheduled_start;
898-
segment_duration_seconds = state->params.durationSeconds;
899-
}
900-
901841
if (!wait_until_channel_idle(channel, &state->stopRequested)) {
902842
break;
903843
}
904844

905-
auto target = build_loop_target_path(state->params, segment_start);
845+
int segment_duration_seconds = state->params.durationSeconds;
846+
if (segment_duration_seconds < kShortClipSeconds) {
847+
segment_duration_seconds = kShortClipSeconds;
848+
}
849+
850+
auto now = std::chrono::system_clock::now();
851+
auto target = build_loop_target_path(state->params, now);
906852
if (target.empty()) {
907853
std::this_thread::sleep_for(std::chrono::milliseconds(250));
908854
continue;
909855
}
856+
910857
if (!begin_segment(target, channel, segment_duration_seconds)) {
911858
std::this_thread::sleep_for(std::chrono::milliseconds(500));
912859
continue;
913860
}
914-
if (!first_segment_pending) {
915-
// Advance next_start only after segment successfully started
916-
next_start = segment_start + std::chrono::seconds(segment_duration_seconds);
917-
next_start = round_up_to_minute(next_start);
918-
}
919-
first_segment_pending = false;
920861

921862
if (!wait_for_recording_completion(channel, &state->stopRequested)) {
922863
break;

0 commit comments

Comments
 (0)