mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-02 01:33:47 +00:00
fmp4mux: Only allow caps-related header updates if header-update-mode=caps
In none mode nothing is expecting updated headers, in the other existing modes the goal is to get an updated header at the end with the duration. So add a new mode specifically for caps changes. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2193>
This commit is contained in:
parent
f86e7e6c33
commit
c5e4181613
4 changed files with 108 additions and 9 deletions
|
@ -3598,6 +3598,11 @@
|
|||
"desc": "Update",
|
||||
"name": "update",
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"desc": "Caps",
|
||||
"name": "caps",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -921,14 +921,14 @@ impl FMP4Mux {
|
|||
}
|
||||
|
||||
// Caps/tag changes are allowed only in case that the
|
||||
// header-update-mode is None.
|
||||
// header-update-mode is Caps.
|
||||
//
|
||||
// CAUTION: This function logs an error if operation is not
|
||||
// allowed so it should be evaluated only in case the caps/tags
|
||||
// would change otherwise (e. g. right-most operand in boolean
|
||||
// expressions).
|
||||
fn header_update_allowed(&self, reason: &str) -> bool {
|
||||
if self.settings.lock().unwrap().header_update_mode == super::HeaderUpdateMode::None {
|
||||
if self.settings.lock().unwrap().header_update_mode == super::HeaderUpdateMode::Caps {
|
||||
gst::debug!(
|
||||
CAT,
|
||||
imp = self,
|
||||
|
@ -3643,17 +3643,30 @@ impl FMP4Mux {
|
|||
let class = aggregator.class();
|
||||
let variant = class.as_ref().variant;
|
||||
|
||||
if settings.header_update_mode == super::HeaderUpdateMode::None && at_eos {
|
||||
if [super::HeaderUpdateMode::None, super::HeaderUpdateMode::Caps]
|
||||
.contains(&settings.header_update_mode)
|
||||
&& at_eos
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
assert!(!at_eos || state.streams.iter().all(|s| s.queued_gops.is_empty()));
|
||||
|
||||
let duration = state
|
||||
.end_pts
|
||||
.opt_checked_sub(state.earliest_pts)
|
||||
.ok()
|
||||
.flatten();
|
||||
let duration = if at_eos
|
||||
&& [
|
||||
super::HeaderUpdateMode::Update,
|
||||
super::HeaderUpdateMode::Rewrite,
|
||||
]
|
||||
.contains(&settings.header_update_mode)
|
||||
{
|
||||
state
|
||||
.end_pts
|
||||
.opt_checked_sub(state.earliest_pts)
|
||||
.ok()
|
||||
.flatten()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let streams = state
|
||||
.streams
|
||||
|
@ -3750,7 +3763,7 @@ impl FMP4Mux {
|
|||
match updated_header {
|
||||
Ok(Some((buffer_list, caps))) => {
|
||||
match settings.header_update_mode {
|
||||
super::HeaderUpdateMode::None => unreachable!(),
|
||||
super::HeaderUpdateMode::None | super::HeaderUpdateMode::Caps => unreachable!(),
|
||||
super::HeaderUpdateMode::Rewrite => {
|
||||
let mut q = gst::query::Seeking::new(gst::Format::Bytes);
|
||||
if self.obj().src_pad().peer_query(&mut q) && q.result().0 {
|
||||
|
|
|
@ -326,14 +326,51 @@ pub(crate) struct FragmentOffset {
|
|||
offset: u64,
|
||||
}
|
||||
|
||||
/**
|
||||
* GstFMP4MuxHeaderUpdateMode:
|
||||
*
|
||||
* How and when updating of the header (`moov`, initialization segment) is allowed.
|
||||
*/
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, glib::Enum)]
|
||||
#[repr(i32)]
|
||||
#[enum_type(name = "GstFMP4MuxHeaderUpdateMode")]
|
||||
pub(crate) enum HeaderUpdateMode {
|
||||
/**
|
||||
* GstFMP4MuxHeaderUpdateMode:none:
|
||||
*
|
||||
* Don't allow and do any header updates at all.
|
||||
*
|
||||
* Caps changes are not allowed in this mode.
|
||||
*/
|
||||
None,
|
||||
/**
|
||||
* GstFMP4MuxHeaderUpdateMode:rewrite:
|
||||
*
|
||||
* Try rewriting the initial header with the overall duration at the very end.
|
||||
*
|
||||
* Caps changes are not allowed in this mode.
|
||||
*/
|
||||
Rewrite,
|
||||
/**
|
||||
* GstFMP4MuxHeaderUpdateMode:update:
|
||||
*
|
||||
* Send an updated version of the initial header with the overall duration at
|
||||
* the very end.
|
||||
*
|
||||
* Caps changes are not allowed in this mode.
|
||||
*/
|
||||
Update,
|
||||
/**
|
||||
* GstFMP4MuxHeaderUpdateMode:caps:
|
||||
*
|
||||
* Send an updated header whenever caps or tag changes are pending that affect the initial
|
||||
* header. The updated header does not have the duration set and will always be followed by a
|
||||
* new fragment.
|
||||
*
|
||||
* Since: plugins-rs-0.14.0
|
||||
*/
|
||||
Caps,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, glib::Enum, Default)]
|
||||
|
|
|
@ -2501,6 +2501,10 @@ fn test_caps_change_at_gop_boundary() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -2541,6 +2545,10 @@ fn test_language_change_at_gop_boundary() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -2603,6 +2611,10 @@ fn test_caps_change_at_gop_boundary_multi_stream() {
|
|||
let mut h1 = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
let mut h2 = gst_check::Harness::with_element(&h1.element().unwrap(), Some("sink_1"), None);
|
||||
|
||||
h1.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps1 = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -2770,6 +2782,10 @@ fn test_caps_change_at_gop_boundary_chunked_multi_stream() {
|
|||
let mut h1 = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
let mut h2 = gst_check::Harness::with_element(&h1.element().unwrap(), Some("sink_1"), None);
|
||||
|
||||
h1.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps1 = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -2918,6 +2934,10 @@ fn test_caps_change_at_gop_boundary_compatible() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1280i32)
|
||||
.field("height", 720i32)
|
||||
|
@ -2959,6 +2979,10 @@ fn test_caps_change_at_gop_boundary_not_allowed() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -3004,6 +3028,10 @@ fn test_caps_change_within_gop() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -3044,6 +3072,10 @@ fn test_caps_change_within_gop_start_without_key() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -3083,6 +3115,10 @@ fn test_caps_change_within_gop_chunked() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -3130,6 +3166,10 @@ fn test_caps_change_within_gop_no_key() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
@ -3171,6 +3211,10 @@ fn test_caps_change_before_first_frame() {
|
|||
|
||||
let mut h = gst_check::Harness::with_padnames("isofmp4mux", Some("sink_0"), Some("src"));
|
||||
|
||||
h.element()
|
||||
.unwrap()
|
||||
.set_property_from_str("header-update-mode", "caps");
|
||||
|
||||
let caps = gst::Caps::builder("video/x-h264")
|
||||
.field("width", 1920i32)
|
||||
.field("height", 1080i32)
|
||||
|
|
Loading…
Reference in a new issue