fix(portal): convert PipeWire nanosecond PTS to encoder frame-number units
PipeWire spa_meta_header.pts is CLOCK_MONOTONIC in nanoseconds, but the encoder expects frame-number units (time_base = 1/fps). The raw nanosecond value was assigned directly to AVFrame.pts, causing the encoder/muxer to interpret timestamps as billions of frames, producing corrupted duration metadata and broken rate control. Fix: record the first frame's PTS as a nanosecond base, compute elapsed nanoseconds for each subsequent frame, then convert to frame numbers via elapsed_ns * fps / 1_000_000_000. Using elapsed time avoids i64 overflow on absolute timestamps (~10^18 ns). Matches the WLR path pattern (state.rs:525-527) which converts microseconds to frame numbers for the same encoder.
This commit is contained in:
@@ -25,6 +25,7 @@ pub struct StatePortal {
|
|||||||
errored: bool,
|
errored: bool,
|
||||||
first_frame: bool,
|
first_frame: bool,
|
||||||
drm_device: PathBuf,
|
drm_device: PathBuf,
|
||||||
|
first_pts_ns: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatePortal {
|
impl StatePortal {
|
||||||
@@ -43,6 +44,7 @@ impl StatePortal {
|
|||||||
errored: false,
|
errored: false,
|
||||||
first_frame: true,
|
first_frame: true,
|
||||||
drm_device,
|
drm_device,
|
||||||
|
first_pts_ns: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,9 +176,16 @@ impl StatePortal {
|
|||||||
bail!("av_hwframe_transfer_data failed: error {ret}");
|
bail!("av_hwframe_transfer_data failed: error {ret}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Set PTS
|
// 7. Set PTS — convert PipeWire nanoseconds to encoder frame-number units
|
||||||
|
// PipeWire PTS is CLOCK_MONOTONIC in nanoseconds.
|
||||||
|
// Encoder time_base = 1/fps, so PTS must be in frame numbers.
|
||||||
|
// Use elapsed time since first frame to avoid i64 overflow on absolute timestamps.
|
||||||
|
let fps_i64 = self.args.fps as i64;
|
||||||
|
let base_ns = *self.first_pts_ns.get_or_insert(frame.pts.max(0));
|
||||||
|
let elapsed_ns = (frame.pts.max(0) - base_ns).max(0);
|
||||||
|
let pts = elapsed_ns * fps_i64 / 1_000_000_000;
|
||||||
unsafe {
|
unsafe {
|
||||||
(*hw_frame.as_mut_ptr()).pts = frame.pts;
|
(*hw_frame.as_mut_ptr()).pts = pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Encode
|
// 8. Encode
|
||||||
|
|||||||
Reference in New Issue
Block a user