Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mux
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2023-06-01 17:16:21 +0300
committerSebastian Dröge <sebastian@centricular.com>2023-06-01 19:25:44 +0300
commita5fcd66c95ad72b80cf200a1d3bb69b751a090e1 (patch)
treed7f5796df3dac495ffaceb25e13cbfaea242e87c /mux
parent80582923bb84445fb06c01fa7f4b28aac7633cb2 (diff)
fmp4mux: Consider a stream filled if the earliest GOP starts after the current chunk
There's not going to be any buffer to output for this stream in the current chunk. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1229>
Diffstat (limited to 'mux')
-rw-r--r--mux/fmp4/src/fmp4mux/imp.rs99
1 files changed, 81 insertions, 18 deletions
diff --git a/mux/fmp4/src/fmp4mux/imp.rs b/mux/fmp4/src/fmp4mux/imp.rs
index 1985847dd..856831258 100644
--- a/mux/fmp4/src/fmp4mux/imp.rs
+++ b/mux/fmp4/src/fmp4mux/imp.rs
@@ -1007,6 +1007,24 @@ impl FMP4Mux {
// First check if the next split should be the end of a fragment or the end of a chunk.
// If both are the same then a fragment split has preference.
if fragment_end_pts <= chunk_end_pts {
+ // If the first GOP already starts after the fragment end PTS then this stream is
+ // filled in the sense that it will not have any buffers for this chunk.
+ if let Some(gop) = stream.queued_gops.back() {
+ gst::trace!(
+ CAT,
+ obj: stream.sinkpad,
+ "GOP {} start PTS {}, GOP end PTS {}",
+ stream.queued_gops.len() - 1,
+ gop.start_pts,
+ gop.end_pts,
+ );
+ if gop.start_pts > fragment_end_pts {
+ gst::debug!(CAT, obj: stream.sinkpad, "Stream's first GOP starting after this fragment");
+ stream.fragment_filled = true;
+ return;
+ }
+ }
+
// We can only finish a fragment if a full GOP with final end PTS is queued and it
// ends at or after the fragment end PTS.
if let Some((gop_idx, gop)) = stream
@@ -1031,6 +1049,26 @@ impl FMP4Mux {
}
if !stream.fragment_filled {
+ // If the first GOP already starts after the chunk end PTS then this stream is
+ // filled in the sense that it will not have any buffers for this chunk.
+ if let Some(gop) = stream.queued_gops.back() {
+ gst::trace!(
+ CAT,
+ obj: stream.sinkpad,
+ "GOP {} start PTS {}, GOP end PTS {}",
+ stream.queued_gops.len() - 1,
+ gop.start_pts,
+ gop.end_pts,
+ );
+ if gop.start_pts > chunk_end_pts {
+ gst::debug!(CAT, obj: stream.sinkpad, "Stream's first GOP starting after this chunk");
+ stream.chunk_filled = true;
+ return;
+ }
+ }
+
+ // We can only finish a chunk if a full GOP with final end PTS is queued and it
+ // ends at or after the fragment end PTS.
let (gop_idx, gop) = match stream.queued_gops.iter().enumerate().find(
|(_idx, gop)| gop.final_earliest_pts || all_eos || stream.sinkpad.is_eos(),
) {
@@ -1065,10 +1103,39 @@ impl FMP4Mux {
}
}
} else {
- let gop = match stream
+ // Check if the end of the latest finalized GOP is after the fragment end
+ let fragment_end_pts = fragment_start_pts + settings.fragment_duration;
+ gst::trace!(
+ CAT,
+ obj: stream.sinkpad,
+ "Current fragment start {}, current fragment end {}",
+ fragment_start_pts,
+ fragment_start_pts + settings.fragment_duration,
+ );
+
+ // If the first GOP already starts after the fragment end PTS then this stream is
+ // filled in the sense that it will not have any buffers for this fragment.
+ if let Some(gop) = stream.queued_gops.back() {
+ gst::trace!(
+ CAT,
+ obj: stream.sinkpad,
+ "GOP {} start PTS {}, GOP end PTS {}",
+ stream.queued_gops.len() - 1,
+ gop.start_pts,
+ gop.end_pts,
+ );
+ if gop.start_pts > fragment_end_pts {
+ gst::debug!(CAT, obj: stream.sinkpad, "Stream's first GOP starting after this fragment");
+ stream.fragment_filled = true;
+ return;
+ }
+ }
+
+ let (gop_idx, gop) = match stream
.queued_gops
.iter()
- .find(|gop| gop.final_end_pts || all_eos || stream.sinkpad.is_eos())
+ .enumerate()
+ .find(|(_gop_idx, gop)| gop.final_end_pts || all_eos || stream.sinkpad.is_eos())
{
Some(gop) => gop,
None => {
@@ -1080,21 +1147,11 @@ impl FMP4Mux {
gst::trace!(
CAT,
obj: stream.sinkpad,
- "GOP start PTS {}, GOP end PTS {}",
+ "GOP {gop_idx} start PTS {}, GOP end PTS {}",
gop.start_pts,
gop.end_pts,
);
- // Check if the end of the latest finalized GOP is after the fragment end
- let fragment_end_pts = fragment_start_pts + settings.fragment_duration;
- gst::trace!(
- CAT,
- obj: stream.sinkpad,
- "Current fragment start {}, current fragment end {}",
- fragment_start_pts,
- fragment_start_pts + settings.fragment_duration,
- );
-
if gop.end_pts >= fragment_end_pts {
gst::debug!(CAT, obj: stream.sinkpad, "Stream queued enough data for this fragment");
stream.fragment_filled = true;
@@ -1729,20 +1786,26 @@ impl FMP4Mux {
let mut min_start_dts_position = None;
let mut chunk_end_pts = None;
+ let fragment_start_pts = state.fragment_start_pts.unwrap();
+ let chunk_start_pts = state.chunk_start_pts.unwrap();
+ let fragment_start = fragment_start_pts == chunk_start_pts;
+
// In fragment mode, each chunk is a full fragment. Otherwise, in chunk mode,
// this fragment is filled if it is filled for the first non-EOS stream
+ // that has a GOP inside this chunk
let fragment_filled = settings.chunk_duration.is_none()
|| state
.streams
.iter()
- .find(|s| !s.sinkpad.is_eos())
+ .find(|s| {
+ !s.sinkpad.is_eos()
+ && s.queued_gops.back().map_or(false, |gop| {
+ gop.start_pts <= fragment_start_pts + settings.fragment_duration
+ })
+ })
.map(|s| s.fragment_filled)
== Some(true);
- let fragment_start_pts = state.fragment_start_pts.unwrap();
- let chunk_start_pts = state.chunk_start_pts.unwrap();
- let fragment_start = fragment_start_pts == chunk_start_pts;
-
// The first stream decides how much can be dequeued, if anything at all.
//
// In chunk mode: