mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-18 05:45:14 +00:00
fmp4mux: Add support for ONVIF timed XML metadata
This commit is contained in:
parent
e4634ca2fe
commit
ffea0e2d2d
2 changed files with 58 additions and 14 deletions
|
@ -644,10 +644,11 @@ fn write_hdlr(
|
||||||
|
|
||||||
let s = caps.structure(0).unwrap();
|
let s = caps.structure(0).unwrap();
|
||||||
let (handler_type, name) = match s.name() {
|
let (handler_type, name) = match s.name() {
|
||||||
"video/x-h264" | "video/x-h265" | "image/jpeg" => (b"vide", b"VideoHandler\0"),
|
"video/x-h264" | "video/x-h265" | "image/jpeg" => (b"vide", b"VideoHandler\0".as_slice()),
|
||||||
"audio/mpeg" | "audio/x-alaw" | "audio/x-mulaw" | "audio/x-adpcm" => {
|
"audio/mpeg" | "audio/x-alaw" | "audio/x-mulaw" | "audio/x-adpcm" => {
|
||||||
(b"soun", b"SoundHandler\0")
|
(b"soun", b"SoundHandler\0".as_slice())
|
||||||
}
|
}
|
||||||
|
"application/x-onvif-metadata" => (b"meta", b"MetadataHandler\0".as_slice()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -680,6 +681,11 @@ fn write_minf(
|
||||||
write_smhd(v, cfg)
|
write_smhd(v, cfg)
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
"application/x-onvif-metadata" => {
|
||||||
|
write_full_box(v, b"nmhd", FULL_BOX_VERSION_0, FULL_BOX_FLAGS_NONE, |_v| {
|
||||||
|
Ok(())
|
||||||
|
})?
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,6 +791,7 @@ fn write_stsd(
|
||||||
"audio/mpeg" | "audio/x-alaw" | "audio/x-mulaw" | "audio/x-adpcm" => {
|
"audio/mpeg" | "audio/x-alaw" | "audio/x-mulaw" | "audio/x-adpcm" => {
|
||||||
write_audio_sample_entry(v, cfg, caps)?
|
write_audio_sample_entry(v, cfg, caps)?
|
||||||
}
|
}
|
||||||
|
"application/x-onvif-metadata" => write_xml_meta_data_sample_entry(v, cfg, caps)?,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1246,6 +1253,34 @@ fn write_esds_aac(v: &mut Vec<u8>, codec_data: &[u8]) -> Result<(), Error> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_xml_meta_data_sample_entry(
|
||||||
|
v: &mut Vec<u8>,
|
||||||
|
_cfg: &super::HeaderConfiguration,
|
||||||
|
caps: &gst::CapsRef,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let s = caps.structure(0).unwrap();
|
||||||
|
let namespace = match s.name() {
|
||||||
|
"application/x-onvif-metadata" => b"http://www.onvif.org/ver10/schema",
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
write_sample_entry_box(v, b"metx", move |v| {
|
||||||
|
// content_encoding, empty string
|
||||||
|
v.push(0);
|
||||||
|
|
||||||
|
// namespace
|
||||||
|
v.extend_from_slice(namespace);
|
||||||
|
v.push(0);
|
||||||
|
|
||||||
|
// schema_location, empty string list
|
||||||
|
v.push(0);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn write_stts(v: &mut Vec<u8>, _cfg: &super::HeaderConfiguration) -> Result<(), Error> {
|
fn write_stts(v: &mut Vec<u8>, _cfg: &super::HeaderConfiguration) -> Result<(), Error> {
|
||||||
// Entry count
|
// Entry count
|
||||||
v.extend(0u32.to_be_bytes());
|
v.extend(0u32.to_be_bytes());
|
||||||
|
@ -1681,7 +1716,12 @@ fn write_traf(
|
||||||
let check_dts = matches!(s.name(), "video/x-h264" | "video/x-h265");
|
let check_dts = matches!(s.name(), "video/x-h264" | "video/x-h265");
|
||||||
let intra_only = matches!(
|
let intra_only = matches!(
|
||||||
s.name(),
|
s.name(),
|
||||||
"audio/mpeg" | "audio/x-alaw" | "audio/x-mulaw" | "audio/x-adpcm" | "image/jpeg"
|
"audio/mpeg"
|
||||||
|
| "audio/x-alaw"
|
||||||
|
| "audio/x-mulaw"
|
||||||
|
| "audio/x-adpcm"
|
||||||
|
| "image/jpeg"
|
||||||
|
| "application/x-onvif-metadata"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Analyze all buffers to know what values can be put into the tfhd for all samples and what
|
// Analyze all buffers to know what values can be put into the tfhd for all samples and what
|
||||||
|
|
|
@ -860,6 +860,9 @@ impl FMP4Mux {
|
||||||
"audio/x-adpcm" => {
|
"audio/x-adpcm" => {
|
||||||
intra_only = true;
|
intra_only = true;
|
||||||
}
|
}
|
||||||
|
"application/x-onvif-metadata" => {
|
||||||
|
intra_only = true;
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,32 +882,30 @@ impl FMP4Mux {
|
||||||
return Err(gst::FlowError::Error);
|
return Err(gst::FlowError::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort video streams first and then audio streams, and each group by pad name.
|
// Sort video streams first and then audio streams and then metadata streams, and each group by pad name.
|
||||||
state.streams.sort_by(|a, b| {
|
state.streams.sort_by(|a, b| {
|
||||||
let stream_type_of_caps = |caps: &gst::CapsRef| {
|
let order_of_caps = |caps: &gst::CapsRef| {
|
||||||
let s = caps.structure(0).unwrap();
|
let s = caps.structure(0).unwrap();
|
||||||
|
|
||||||
if s.name().starts_with("video/") {
|
if s.name().starts_with("video/") {
|
||||||
gst::StreamType::VIDEO
|
0
|
||||||
} else if s.name().starts_with("audio/") {
|
} else if s.name().starts_with("audio/") {
|
||||||
gst::StreamType::AUDIO
|
1
|
||||||
|
} else if s.name().starts_with("application/x-onvif-metadata") {
|
||||||
|
2
|
||||||
} else {
|
} else {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let st_a = stream_type_of_caps(&a.caps);
|
let st_a = order_of_caps(&a.caps);
|
||||||
let st_b = stream_type_of_caps(&b.caps);
|
let st_b = order_of_caps(&b.caps);
|
||||||
|
|
||||||
if st_a == st_b {
|
if st_a == st_b {
|
||||||
return a.sinkpad.name().cmp(&b.sinkpad.name());
|
return a.sinkpad.name().cmp(&b.sinkpad.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
if st_a == gst::StreamType::VIDEO {
|
st_a.cmp(&st_b)
|
||||||
std::cmp::Ordering::Less
|
|
||||||
} else {
|
|
||||||
std::cmp::Ordering::Greater
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1963,6 +1964,9 @@ impl ElementImpl for ONVIFFMP4Mux {
|
||||||
.field("rate", 8000i32)
|
.field("rate", 8000i32)
|
||||||
.field("bitrate", gst::List::new([16000i32, 24000, 32000, 40000]))
|
.field("bitrate", gst::List::new([16000i32, 24000, 32000, 40000]))
|
||||||
.build(),
|
.build(),
|
||||||
|
gst::Structure::builder("application/x-onvif-metadata")
|
||||||
|
.field("encoding", "utf8")
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<gst::Caps>(),
|
.collect::<gst::Caps>(),
|
||||||
|
|
Loading…
Reference in a new issue