Skip to content

Commit bcb0ed4

Browse files
committed
fix: resolve cumulative clock drift in video file splitting
1 parent 3725b09 commit bcb0ed4

2 files changed

Lines changed: 25 additions & 33 deletions

File tree

src/recorder/recorder_manager.cpp

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -135,43 +135,36 @@ RecorderManager::RecorderManager(Args config)
135135
auto_start_(true),
136136
header_written_(false),
137137
has_first_keyframe(false),
138-
time_reset_pending_(false),
139-
record_path(config.record_path),
140-
elapsed_time_(0.0) {}
138+
record_path(config.record_path) {}
141139

142140
void RecorderManager::SubscribeVideoSource(std::shared_ptr<VideoCapturer> video_src) {
143141
video_subscription_ = video_src->Subscribe(
144142
[this](V4L2FrameBufferRef buffer) {
145-
// waiting first keyframe to start recorders.
146-
if (auto_start_ && !has_first_keyframe &&
147-
((buffer->flags() & V4L2_BUF_FLAG_KEYFRAME) ||
148-
video_src_->format() != V4L2_PIX_FMT_H264)) {
149-
Start();
150-
last_created_time_ = buffer->timestamp();
151-
}
143+
bool is_keyframe = (buffer->flags() & V4L2_BUF_FLAG_KEYFRAME) ||
144+
(video_src_->format() != V4L2_PIX_FMT_H264);
152145

153-
// restart to write in the new file on the next keyframe boundary.
154-
if (has_first_keyframe && elapsed_time_ >= config.file_duration &&
155-
((buffer->flags() & V4L2_BUF_FLAG_KEYFRAME) ||
156-
video_src_->format() != V4L2_PIX_FMT_H264)) {
157-
Stop();
146+
// waiting first keyframe to start recorders.
147+
if (auto_start_ && !has_first_keyframe && is_keyframe) {
158148
Start();
149+
base_start_time_ = buffer->timestamp();
150+
next_generate_time_ = ++file_index_ * config.file_duration;
159151
}
160152

161-
if (has_first_keyframe && video_recorder) {
162-
video_recorder->OnBuffer(buffer);
163-
}
164-
165-
// Sync last_created_time_ to V4L2 time base on first callback after Start()
166-
if (time_reset_pending_) {
167-
last_created_time_ = buffer->timestamp();
168-
elapsed_time_ = 0.0;
169-
time_reset_pending_ = false;
170-
} else {
171-
int64_t elapsed_us =
172-
(int64_t)(buffer->timestamp().tv_sec - last_created_time_.tv_sec) * 1000000LL +
173-
(int64_t)(buffer->timestamp().tv_usec - last_created_time_.tv_usec);
174-
elapsed_time_ = elapsed_us / 1e6;
153+
int64_t total_elapsed_us =
154+
(int64_t)(buffer->timestamp().tv_sec - base_start_time_.tv_sec) * 1000000LL +
155+
(int64_t)(buffer->timestamp().tv_usec - base_start_time_.tv_usec);
156+
double total_elapsed_time = total_elapsed_us / 1e6;
157+
158+
if (has_first_keyframe) {
159+
if (total_elapsed_time >= next_generate_time_ && is_keyframe) {
160+
Stop();
161+
Start();
162+
next_generate_time_ = ++file_index_ * config.file_duration;
163+
}
164+
165+
if (video_recorder) {
166+
video_recorder->OnBuffer(buffer);
167+
}
175168
}
176169
},
177170
config.record_stream_idx);
@@ -283,8 +276,6 @@ void RecorderManager::Start() {
283276
}
284277

285278
has_first_keyframe = true;
286-
elapsed_time_ = 0.0;
287-
time_reset_pending_ = true;
288279
}
289280

290281
void RecorderManager::Stop() {

src/recorder/recorder_manager.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,17 @@ class RecorderManager {
5454
void SubscribeAudioSource(std::shared_ptr<AudioCapturer> audio_src);
5555

5656
private:
57-
double elapsed_time_;
5857
bool auto_start_;
58+
int file_index_ = 0;
59+
double next_generate_time_;
5960
std::atomic<bool> header_written_;
6061
std::atomic<bool> time_reset_pending_;
6162
std::mutex rotation_mtx_;
6263
std::condition_variable rotation_cv_;
6364
std::atomic<bool> rotation_abort_;
6465
std::atomic<bool> rotation_requested_;
6566
std::thread rotation_thread_;
66-
struct timeval last_created_time_;
67+
struct timeval base_start_time_;
6768
std::shared_ptr<VideoCapturer> video_src_;
6869

6970
std::string current_filepath_;

0 commit comments

Comments
 (0)