Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/CHANGES.TXT
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
0.96.7 (unreleased)
-------------------
- Fix: Prevent crash in Rust timing module when logging out-of-range PTS/FTS timestamps from malformed streams.

0.96.6 (2026-02-19)
-------------------
- New: 32-bit (x86) Windows build and installer (#2116)
Expand Down
4 changes: 3 additions & 1 deletion src/rust/lib_ccxr/src/time/c_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ pub fn get_fts_max(ctx: &mut TimingContext) -> Timestamp {

/// Rust equivalent for `print_mstime_static` function in C. Uses Rust-native types as input and output.
pub fn print_mstime_static(mstime: Timestamp, sep: char) -> String {
mstime.to_hms_millis_time(sep).unwrap()
mstime
.to_hms_millis_time(sep)
.unwrap_or_else(|_| "INVALID".to_string())
}

/// Rust equivalent for `print_debug_timing` function in C. Uses Rust-native types as input and output.
Expand Down
45 changes: 35 additions & 10 deletions src/rust/lib_ccxr/src/time/timing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,29 @@ impl TimingContext {
if self.pts_set == PtsSet::No {
self.pts_set = PtsSet::Received
}
debug!(msg_type = DebugMessageFlag::VIDEO_STREAM; "PTS: {} ({:8})", self.current_pts.as_timestamp(timing_info.mpeg_clock_freq).to_hms_millis_time(':').unwrap(), self.current_pts.as_i64());
debug!(msg_type = DebugMessageFlag::VIDEO_STREAM; " FTS: {} \n", self.fts_now.to_hms_millis_time(':').unwrap());
let pts_string = self
.current_pts
.as_timestamp(timing_info.mpeg_clock_freq)
.to_hms_millis_time(':')
.unwrap_or_else(|_| "INVALID".to_string());

let fts_string = self
.fts_now
.to_hms_millis_time(':')
.unwrap_or_else(|_| "INVALID".to_string());

debug!(
msg_type = DebugMessageFlag::VIDEO_STREAM;
"PTS: {} ({:8})",
pts_string,
self.current_pts.as_i64()
);

debug!(
msg_type = DebugMessageFlag::VIDEO_STREAM;
" FTS: {} \n",
fts_string
);

// Check if PTS reset
if self.current_pts < prev_pts {
Expand Down Expand Up @@ -368,7 +389,7 @@ impl TimingContext {
debug!(
msg_type = DebugMessageFlag::TIME;
"\nFirst sync time PTS: {} {:+}ms (time before this PTS)\n",
self.min_pts.as_timestamp(timing_info.mpeg_clock_freq).to_hms_millis_time(':').unwrap(),
self.min_pts.as_timestamp(timing_info.mpeg_clock_freq).to_hms_millis_time(':').unwrap_or_else(|_| "INVALID".to_string()),
self.fts_offset.millis()
);
debug!(
Expand Down Expand Up @@ -411,7 +432,7 @@ impl TimingContext {
debug!(
msg_type = DebugMessageFlag::TIME;
"\nNew min PTS time: {} {:+}ms (time before this PTS)\n",
self.min_pts.as_timestamp(timing_info.mpeg_clock_freq).to_hms_millis_time(':').unwrap(),
self.min_pts.as_timestamp(timing_info.mpeg_clock_freq).to_hms_millis_time(':').unwrap_or_else(|_| "INVALID".to_string()),
self.fts_offset.millis()
);
}
Expand Down Expand Up @@ -506,11 +527,13 @@ impl TimingContext {
self.sync_pts
.as_timestamp(timing_info.mpeg_clock_freq)
.to_hms_millis_time(':')
.unwrap()
.unwrap_or_else(|_| "INVALID".to_string())
);
info!(
" GOP start FTS: {}\n",
gop_time.to_hms_millis_time(':').unwrap()
gop_time
.to_hms_millis_time(':')
.unwrap_or_else(|_| "INVALID".to_string())
);

// Length first GOP to last GOP
Expand All @@ -521,14 +544,16 @@ impl TimingContext {

info!(
"Last FTS: {}",
self.get_fts_max().to_hms_millis_time(':').unwrap()
self.get_fts_max()
.to_hms_millis_time(':')
.unwrap_or_else(|_| "INVALID".to_string())
);
info!(
" GOP start FTS: {}\n",
timing_info
.fts_at_gop_start
.to_hms_millis_time(':')
.unwrap()
.unwrap_or_else(|_| "INVALID".to_string())
);

let one_frame = FrameCount::new(1).as_timestamp(timing_info.current_fps);
Expand All @@ -538,10 +563,10 @@ impl TimingContext {
"Max FTS diff. to PTS: {:6}ms GOP: {:6}ms\n\n",
(self.get_fts_max() + one_frame - ptslenms)
.to_hms_millis_time(':')
.unwrap(),
.unwrap_or_else(|_| "INVALID".to_string()),
(self.get_fts_max() + one_frame - goplenms)
.to_hms_millis_time(':')
.unwrap()
.unwrap_or_else(|_| "INVALID".to_string())
);
}

Expand Down
Loading