fmp4mux: Renamed caps_changed to need_new_header

Because the header update is needed in case of language code or
orientation changes as well that come with tag events.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1762>
This commit is contained in:
Jochen Henneberg 2024-09-20 13:52:28 +02:00
parent 1be92c4b86
commit c0f3eff18e

View file

@ -249,7 +249,7 @@ struct State {
/// Set to true if the caps of *any* sinkpad have changed or on /// Set to true if the caps of *any* sinkpad have changed or on
/// new language code or image orientation. /// new language code or image orientation.
caps_changed: bool, need_new_header: bool,
/// Sequence number of the current fragment. /// Sequence number of the current fragment.
sequence_number: u32, sequence_number: u32,
@ -1406,7 +1406,7 @@ impl FMP4Mux {
for stream in &state.streams { for stream in &state.streams {
let (stream_earliest_pts, stream_start_dts) = match stream.queued_gops.back() { let (stream_earliest_pts, stream_start_dts) = match stream.queued_gops.back() {
None => { None => {
if !all_eos && !timeout && !state.caps_changed { if !all_eos && !timeout && !state.need_new_header {
earliest_pts = None; earliest_pts = None;
start_dts = None; start_dts = None;
break; break;
@ -1414,7 +1414,10 @@ impl FMP4Mux {
continue; continue;
} }
Some(oldest_gop) => { Some(oldest_gop) => {
if !all_eos && !timeout && !state.caps_changed && !oldest_gop.final_earliest_pts if !all_eos
&& !timeout
&& !state.need_new_header
&& !oldest_gop.final_earliest_pts
{ {
earliest_pts = None; earliest_pts = None;
start_dts = None; start_dts = None;
@ -1448,7 +1451,7 @@ impl FMP4Mux {
"Got earliest PTS {}, start DTS {} (timeout: {timeout}, all eos: {all_eos}, caps changed: {})", "Got earliest PTS {}, start DTS {} (timeout: {timeout}, all eos: {all_eos}, caps changed: {})",
earliest_pts, earliest_pts,
start_dts.display(), start_dts.display(),
state.caps_changed, state.need_new_header,
); );
let fragment_start_pts = earliest_pts; let fragment_start_pts = earliest_pts;
@ -1535,7 +1538,7 @@ impl FMP4Mux {
&self, &self,
settings: &Settings, settings: &Settings,
stream: &mut Stream, stream: &mut Stream,
caps_changed: bool, need_new_header: bool,
timeout: bool, timeout: bool,
all_eos: bool, all_eos: bool,
fragment_end_pts: gst::ClockTime, fragment_end_pts: gst::ClockTime,
@ -1546,7 +1549,7 @@ impl FMP4Mux {
) -> Result<Vec<Gop>, gst::FlowError> { ) -> Result<Vec<Gop>, gst::FlowError> {
assert!( assert!(
timeout timeout
|| caps_changed || need_new_header
|| stream.sinkpad.is_eos() || stream.sinkpad.is_eos()
|| stream.queued_gops.get(1).map(|gop| gop.final_earliest_pts) == Some(true) || stream.queued_gops.get(1).map(|gop| gop.final_earliest_pts) == Some(true)
|| settings.chunk_duration.is_some() || settings.chunk_duration.is_some()
@ -1598,7 +1601,7 @@ impl FMP4Mux {
"Fragment filled, current GOP start {} end {} (final {})", "Fragment filled, current GOP start {} end {} (final {})",
gop.start_pts, gop.start_pts,
gop.end_pts, gop.end_pts,
gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed, gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header,
); );
// If we have a final GOP then include it as long as it's either // If we have a final GOP then include it as long as it's either
@ -1607,7 +1610,7 @@ impl FMP4Mux {
// //
// The second case would happen if no GOP ends between the last chunk of the // The second case would happen if no GOP ends between the last chunk of the
// fragment and the fragment duration. // fragment and the fragment duration.
if (gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed) if (gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header)
&& (gop.end_pts <= dequeue_end_pts && (gop.end_pts <= dequeue_end_pts
|| (gops.is_empty() && chunk_end_pts.is_none())) || (gops.is_empty() && chunk_end_pts.is_none()))
{ {
@ -1624,7 +1627,7 @@ impl FMP4Mux {
// //
// If this is not the first stream then take an incomplete GOP. // If this is not the first stream then take an incomplete GOP.
if gop.start_pts >= dequeue_end_pts if gop.start_pts >= dequeue_end_pts
|| (!gop.final_earliest_pts && !stream.sinkpad.is_eos() && !caps_changed) || (!gop.final_earliest_pts && !stream.sinkpad.is_eos() && !need_new_header)
{ {
gst::trace!(CAT, obj = stream.sinkpad, "GOP starts after fragment end",); gst::trace!(CAT, obj = stream.sinkpad, "GOP starts after fragment end",);
break; break;
@ -1645,17 +1648,17 @@ impl FMP4Mux {
"Chunk filled, current GOP start {} end {} (final {})", "Chunk filled, current GOP start {} end {} (final {})",
gop.start_pts, gop.start_pts,
gop.end_pts, gop.end_pts,
gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header
); );
} }
if gop.end_pts <= dequeue_end_pts if gop.end_pts <= dequeue_end_pts
&& (gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed) && (gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header)
{ {
gst::trace!(CAT, obj = stream.sinkpad, "Pushing whole GOP",); gst::trace!(CAT, obj = stream.sinkpad, "Pushing whole GOP",);
gops.push(stream.queued_gops.pop_back().unwrap()); gops.push(stream.queued_gops.pop_back().unwrap());
} else if gop.start_pts >= dequeue_end_pts } else if gop.start_pts >= dequeue_end_pts
|| (!gop.final_earliest_pts && !stream.sinkpad.is_eos() && !caps_changed) || (!gop.final_earliest_pts && !stream.sinkpad.is_eos() && !need_new_header)
{ {
gst::trace!(CAT, obj = stream.sinkpad, "GOP starts after chunk end",); gst::trace!(CAT, obj = stream.sinkpad, "GOP starts after chunk end",);
break; break;
@ -1692,7 +1695,7 @@ impl FMP4Mux {
// The last buffer of the GOP starts before the chunk end but ends // The last buffer of the GOP starts before the chunk end but ends
// after the end. We still take it here and remove the whole GOP. // after the end. We still take it here and remove the whole GOP.
if split_index == gop.buffers.len() - 1 { if split_index == gop.buffers.len() - 1 {
if gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed { if gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header {
gst::trace!(CAT, obj = stream.sinkpad, "Pushing whole GOP",); gst::trace!(CAT, obj = stream.sinkpad, "Pushing whole GOP",);
gops.push(stream.queued_gops.pop_back().unwrap()); gops.push(stream.queued_gops.pop_back().unwrap());
} else { } else {
@ -1779,7 +1782,7 @@ impl FMP4Mux {
"Current GOP start {} end {} (final {})", "Current GOP start {} end {} (final {})",
gop.start_pts, gop.start_pts,
gop.end_pts, gop.end_pts,
gop.final_end_pts || stream.sinkpad.is_eos() || caps_changed gop.final_end_pts || stream.sinkpad.is_eos() || need_new_header
); );
// If this GOP is not complete then we can't pop it yet. // If this GOP is not complete then we can't pop it yet.
@ -1787,7 +1790,7 @@ impl FMP4Mux {
// If there was no complete GOP at all yet then it might be bigger than the // If there was no complete GOP at all yet then it might be bigger than the
// fragment duration. In this case we might not be able to handle the latency // fragment duration. In this case we might not be able to handle the latency
// requirements in a live pipeline. // requirements in a live pipeline.
if !gop.final_end_pts && !stream.sinkpad.is_eos() && !caps_changed { if !gop.final_end_pts && !stream.sinkpad.is_eos() && !need_new_header {
gst::trace!( gst::trace!(
CAT, CAT,
obj = stream.sinkpad, obj = stream.sinkpad,
@ -2073,7 +2076,7 @@ impl FMP4Mux {
let gops = self.drain_buffers_one_stream( let gops = self.drain_buffers_one_stream(
settings, settings,
stream, stream,
state.caps_changed, state.need_new_header,
timeout, timeout,
all_eos, all_eos,
fragment_end_pts, fragment_end_pts,
@ -2422,7 +2425,7 @@ impl FMP4Mux {
gst::info!(CAT, imp = self, "Draining at EOS"); gst::info!(CAT, imp = self, "Draining at EOS");
} else if timeout { } else if timeout {
gst::info!(CAT, imp = self, "Draining at timeout"); gst::info!(CAT, imp = self, "Draining at timeout");
} else if state.caps_changed { } else if state.need_new_header {
gst::info!(CAT, imp = self, "Draining on caps change"); gst::info!(CAT, imp = self, "Draining on caps change");
} else { } else {
for stream in &state.streams { for stream in &state.streams {
@ -2624,7 +2627,7 @@ impl FMP4Mux {
// Update for the start PTS of the next fragment / chunk // Update for the start PTS of the next fragment / chunk
if fragment_filled || state.caps_changed { if fragment_filled || state.need_new_header {
state.fragment_start_pts = Some(chunk_end_pts); state.fragment_start_pts = Some(chunk_end_pts);
state.fragment_end_pts = Some(self.get_fragment_end_pts( state.fragment_end_pts = Some(self.get_fragment_end_pts(
&state.manual_fragment_boundaries, &state.manual_fragment_boundaries,
@ -3419,7 +3422,7 @@ impl AggregatorImpl for FMP4Mux {
// Only care of caps if streams have been setup // Only care of caps if streams have been setup
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if !state.streams.is_empty() { if !state.streams.is_empty() {
state.caps_changed = if let Some(stream) = state state.need_new_header = if let Some(stream) = state
.streams .streams
.iter_mut() .iter_mut()
.find(|s| *aggregator_pad == s.sinkpad) .find(|s| *aggregator_pad == s.sinkpad)
@ -3471,7 +3474,7 @@ impl AggregatorImpl for FMP4Mux {
&& self.caps_change_allowed() && self.caps_change_allowed()
{ {
state.language_code = language_code; state.language_code = language_code;
state.caps_changed = true; state.need_new_header = true;
} }
} }
} else if let Some(tag_value) = ev.tag().get::<gst::tags::ImageOrientation>() { } else if let Some(tag_value) = ev.tag().get::<gst::tags::ImageOrientation>() {
@ -3504,7 +3507,7 @@ impl AggregatorImpl for FMP4Mux {
&& self.caps_change_allowed() && self.caps_change_allowed()
{ {
state.orientation = orientation; state.orientation = orientation;
state.caps_changed = true; state.need_new_header = true;
} }
} }
@ -3605,7 +3608,7 @@ impl AggregatorImpl for FMP4Mux {
let mut caps = None; let mut caps = None;
let mut buffers = vec![]; let mut buffers = vec![];
let mut upstream_events = vec![]; let mut upstream_events = vec![];
let (caps_changed, res) = { let (need_new_header, res) = {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
// Create streams // Create streams
@ -3655,7 +3658,7 @@ impl AggregatorImpl for FMP4Mux {
&mut upstream_events, &mut upstream_events,
); );
(state.caps_changed, res) (state.need_new_header, res)
}; };
for (sinkpad, event) in upstream_events { for (sinkpad, event) in upstream_events {
@ -3672,15 +3675,15 @@ impl AggregatorImpl for FMP4Mux {
self.obj().finish_buffer_list(buffer_list)?; self.obj().finish_buffer_list(buffer_list)?;
} }
// all drained then check if a caps change is pending // all drained then check if a new header is needed
if caps_changed { if need_new_header {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
gst::info!( gst::info!(
CAT, CAT,
imp = self, imp = self,
"Reset state, update stream caps and send new header on caps changed" "Reset state, update stream caps and send new header"
); );
state.caps_changed = false; state.need_new_header = false;
state.stream_header = None; state.stream_header = None;
state.sent_headers = false; state.sent_headers = false;
for stream in state.streams.iter_mut().filter(|s| s.next_caps.is_some()) { for stream in state.streams.iter_mut().filter(|s| s.next_caps.is_some()) {