mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-25 21:11:00 +00:00
fmp4mux: Ensure that DTS (or PTS for intra-only streams) are monotonically increasing
This commit is contained in:
parent
402500f79c
commit
e52d1fa317
1 changed files with 63 additions and 16 deletions
|
@ -101,6 +101,10 @@ struct Stream {
|
||||||
// Difference between the first DTS and 0 in case of negative DTS
|
// Difference between the first DTS and 0 in case of negative DTS
|
||||||
dts_offset: Option<gst::ClockTime>,
|
dts_offset: Option<gst::ClockTime>,
|
||||||
|
|
||||||
|
// Current position (DTS, or PTS for intra-only) to prevent
|
||||||
|
// timestamps from going backwards when queueing new buffers
|
||||||
|
current_position: gst::ClockTime,
|
||||||
|
|
||||||
last_force_keyunit_time: Option<gst::ClockTime>,
|
last_force_keyunit_time: Option<gst::ClockTime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +171,7 @@ impl FMP4Mux {
|
||||||
let duration = buffer.duration();
|
let duration = buffer.duration();
|
||||||
let end_pts_position = duration.map_or(pts_position, |duration| pts_position + duration);
|
let end_pts_position = duration.map_or(pts_position, |duration| pts_position + duration);
|
||||||
|
|
||||||
let pts = match segment.to_running_time_full(pts_position) {
|
let mut pts = match segment.to_running_time_full(pts_position) {
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
gst::error!(CAT, obj: &stream.sinkpad, "Couldn't convert PTS to running time");
|
gst::error!(CAT, obj: &stream.sinkpad, "Couldn't convert PTS to running time");
|
||||||
return Err(gst::FlowError::Error);
|
return Err(gst::FlowError::Error);
|
||||||
|
@ -179,7 +183,7 @@ impl FMP4Mux {
|
||||||
(_, Some(pts)) => pts,
|
(_, Some(pts)) => pts,
|
||||||
};
|
};
|
||||||
|
|
||||||
let end_pts = match segment.to_running_time_full(end_pts_position) {
|
let mut end_pts = match segment.to_running_time_full(end_pts_position) {
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
gst::error!(
|
gst::error!(
|
||||||
CAT,
|
CAT,
|
||||||
|
@ -195,6 +199,23 @@ impl FMP4Mux {
|
||||||
(_, Some(pts)) => pts,
|
(_, Some(pts)) => pts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enforce monotonically increasing PTS for intra-only streams
|
||||||
|
if intra_only {
|
||||||
|
if pts < stream.current_position {
|
||||||
|
gst::warning!(
|
||||||
|
CAT,
|
||||||
|
obj: &stream.sinkpad,
|
||||||
|
"Decreasing PTS {} < {} for intra-only stream",
|
||||||
|
pts,
|
||||||
|
stream.current_position,
|
||||||
|
);
|
||||||
|
pts = stream.current_position;
|
||||||
|
} else {
|
||||||
|
stream.current_position = pts;
|
||||||
|
}
|
||||||
|
end_pts = std::cmp::max(end_pts, pts);
|
||||||
|
}
|
||||||
|
|
||||||
let (dts_position, dts, end_dts) = if intra_only {
|
let (dts_position, dts, end_dts) = if intra_only {
|
||||||
(None, None, None)
|
(None, None, None)
|
||||||
} else {
|
} else {
|
||||||
|
@ -204,7 +225,7 @@ impl FMP4Mux {
|
||||||
let end_dts_position =
|
let end_dts_position =
|
||||||
duration.map_or(dts_position, |duration| dts_position + duration);
|
duration.map_or(dts_position, |duration| dts_position + duration);
|
||||||
|
|
||||||
let dts = match segment.to_running_time_full(dts_position) {
|
let mut dts = match segment.to_running_time_full(dts_position) {
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
gst::error!(CAT, obj: &stream.sinkpad, "Couldn't convert DTS to running time");
|
gst::error!(CAT, obj: &stream.sinkpad, "Couldn't convert DTS to running time");
|
||||||
return Err(gst::FlowError::Error);
|
return Err(gst::FlowError::Error);
|
||||||
|
@ -231,7 +252,7 @@ impl FMP4Mux {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let end_dts = match segment.to_running_time_full(end_dts_position) {
|
let mut end_dts = match segment.to_running_time_full(end_dts_position) {
|
||||||
(_, None) => {
|
(_, None) => {
|
||||||
gst::error!(
|
gst::error!(
|
||||||
CAT,
|
CAT,
|
||||||
|
@ -261,6 +282,24 @@ impl FMP4Mux {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enforce monotonically increasing DTS for intra-only streams
|
||||||
|
// NOTE: PTS stays the same so this will cause a bigger PTS/DTS difference
|
||||||
|
// FIXME: Is this correct?
|
||||||
|
if dts < stream.current_position {
|
||||||
|
gst::warning!(
|
||||||
|
CAT,
|
||||||
|
obj: &stream.sinkpad,
|
||||||
|
"Decreasing DTS {} < {}",
|
||||||
|
dts,
|
||||||
|
stream.current_position,
|
||||||
|
);
|
||||||
|
dts = stream.current_position;
|
||||||
|
} else {
|
||||||
|
stream.current_position = dts;
|
||||||
|
}
|
||||||
|
end_dts = std::cmp::max(end_dts, dts);
|
||||||
|
|
||||||
(Some(dts_position), Some(dts), Some(end_dts))
|
(Some(dts_position), Some(dts), Some(end_dts))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -316,8 +355,9 @@ impl FMP4Mux {
|
||||||
pts,
|
pts,
|
||||||
dts.display(),
|
dts.display(),
|
||||||
);
|
);
|
||||||
prev_gop.end_pts = pts;
|
|
||||||
prev_gop.end_dts = dts;
|
prev_gop.end_pts = std::cmp::max(prev_gop.end_pts, pts);
|
||||||
|
prev_gop.end_dts = std::cmp::max(prev_gop.end_dts, dts);
|
||||||
|
|
||||||
if intra_only {
|
if intra_only {
|
||||||
prev_gop.final_end_pts = true;
|
prev_gop.final_end_pts = true;
|
||||||
|
@ -368,15 +408,17 @@ impl FMP4Mux {
|
||||||
gop.earliest_pts_position = pts_position;
|
gop.earliest_pts_position = pts_position;
|
||||||
|
|
||||||
if let Some(prev_gop) = stream.queued_gops.get_mut(1) {
|
if let Some(prev_gop) = stream.queued_gops.get_mut(1) {
|
||||||
gst::debug!(
|
if prev_gop.end_pts < pts {
|
||||||
CAT,
|
gst::debug!(
|
||||||
obj: &stream.sinkpad,
|
CAT,
|
||||||
"Updating previous GOP starting PTS {} end time from {} to {}",
|
obj: &stream.sinkpad,
|
||||||
pts,
|
"Updating previous GOP starting PTS {} end time from {} to {}",
|
||||||
prev_gop.end_pts,
|
pts,
|
||||||
pts
|
prev_gop.end_pts,
|
||||||
);
|
pts
|
||||||
prev_gop.end_pts = pts;
|
);
|
||||||
|
prev_gop.end_pts = pts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +708,10 @@ impl FMP4Mux {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let duration = end_timestamp.saturating_sub(timestamp);
|
// Timestamps are enforced to monotonically increase when queueing buffers
|
||||||
|
let duration = end_timestamp
|
||||||
|
.checked_sub(timestamp)
|
||||||
|
.expect("Timestamps going backwards");
|
||||||
|
|
||||||
let composition_time_offset = if stream.intra_only {
|
let composition_time_offset = if stream.intra_only {
|
||||||
None
|
None
|
||||||
|
@ -982,6 +1027,7 @@ impl FMP4Mux {
|
||||||
queued_gops: VecDeque::new(),
|
queued_gops: VecDeque::new(),
|
||||||
fragment_filled: false,
|
fragment_filled: false,
|
||||||
dts_offset: None,
|
dts_offset: None,
|
||||||
|
current_position: gst::ClockTime::ZERO,
|
||||||
last_force_keyunit_time: None,
|
last_force_keyunit_time: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1432,6 +1478,7 @@ impl AggregatorImpl for FMP4Mux {
|
||||||
for stream in &mut state.streams {
|
for stream in &mut state.streams {
|
||||||
stream.queued_gops.clear();
|
stream.queued_gops.clear();
|
||||||
stream.dts_offset = None;
|
stream.dts_offset = None;
|
||||||
|
stream.current_position = gst::ClockTime::ZERO;
|
||||||
stream.last_force_keyunit_time = None;
|
stream.last_force_keyunit_time = None;
|
||||||
stream.fragment_filled = false;
|
stream.fragment_filled = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue