mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-22 23:56:17 +00:00
fmp4mux: Fixed logging for unsupported orientation tags
Fmp4mux State and Stream structs now store matrix references instead of orientation enum. The TransformMatrix is wrapped into a struct for Default trait which is needed by struct State. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1975>
This commit is contained in:
parent
aeb37c5ab1
commit
58ee9e2b9f
3 changed files with 62 additions and 49 deletions
|
@ -12,7 +12,7 @@ use gst::prelude::*;
|
||||||
use anyhow::{anyhow, bail, Context, Error};
|
use anyhow::{anyhow, bail, Context, Error};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use super::{transform_matrix, Buffer, IDENTITY_MATRIX};
|
use super::Buffer;
|
||||||
|
|
||||||
fn write_box<T, F: FnOnce(&mut Vec<u8>) -> Result<T, Error>>(
|
fn write_box<T, F: FnOnce(&mut Vec<u8>) -> Result<T, Error>>(
|
||||||
vec: &mut Vec<u8>,
|
vec: &mut Vec<u8>,
|
||||||
|
@ -522,8 +522,7 @@ fn write_mvhd(
|
||||||
v.extend([0u8; 2 + 2 * 4]);
|
v.extend([0u8; 2 + 2 * 4]);
|
||||||
|
|
||||||
// Matrix
|
// Matrix
|
||||||
let matrix = transform_matrix(&cfg.orientation);
|
v.extend(cfg.orientation.iter().flatten());
|
||||||
v.extend(matrix.iter().flatten());
|
|
||||||
|
|
||||||
// Pre defined
|
// Pre defined
|
||||||
v.extend([0u8; 6 * 4]);
|
v.extend([0u8; 6 * 4]);
|
||||||
|
@ -639,15 +638,8 @@ fn write_tkhd(
|
||||||
// Reserved
|
// Reserved
|
||||||
v.extend([0u8; 2]);
|
v.extend([0u8; 2]);
|
||||||
|
|
||||||
// Matrix
|
// Per stream orientation matrix.
|
||||||
let matrix = match s.name().as_str() {
|
v.extend(stream.orientation.iter().flatten());
|
||||||
x if x.starts_with("video/") || x.starts_with("image/") => {
|
|
||||||
transform_matrix(&stream.orientation)
|
|
||||||
}
|
|
||||||
_ => &IDENTITY_MATRIX,
|
|
||||||
};
|
|
||||||
|
|
||||||
v.extend(matrix.iter().flatten());
|
|
||||||
|
|
||||||
// Width/height
|
// Width/height
|
||||||
match s.name().as_str() {
|
match s.name().as_str() {
|
||||||
|
|
|
@ -20,6 +20,7 @@ use std::ops::Bound::Excluded;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::fmp4mux::obu::read_seq_header_obu_bytes;
|
use crate::fmp4mux::obu::read_seq_header_obu_bytes;
|
||||||
|
use crate::fmp4mux::TransformMatrix;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use super::boxes;
|
use super::boxes;
|
||||||
|
@ -257,7 +258,7 @@ struct Stream {
|
||||||
/// Language code from tags
|
/// Language code from tags
|
||||||
language_code: Option<[u8; 3]>,
|
language_code: Option<[u8; 3]>,
|
||||||
/// Orientation from tags
|
/// Orientation from tags
|
||||||
orientation: Option<gst_video::VideoOrientationMethod>,
|
orientation: &'static TransformMatrix,
|
||||||
|
|
||||||
/// Edit list entries for this stream.
|
/// Edit list entries for this stream.
|
||||||
elst_infos: Vec<super::ElstInfo>,
|
elst_infos: Vec<super::ElstInfo>,
|
||||||
|
@ -391,7 +392,7 @@ struct State {
|
||||||
/// Start DTS of the whole stream
|
/// Start DTS of the whole stream
|
||||||
start_dts: Option<gst::ClockTime>,
|
start_dts: Option<gst::ClockTime>,
|
||||||
/// Orientation from tags
|
/// Orientation from tags
|
||||||
orientation: Option<gst_video::VideoOrientationMethod>,
|
orientation: &'static TransformMatrix,
|
||||||
|
|
||||||
/// Start PTS of the current fragment
|
/// Start PTS of the current fragment
|
||||||
fragment_start_pts: Option<gst::ClockTime>,
|
fragment_start_pts: Option<gst::ClockTime>,
|
||||||
|
@ -2980,7 +2981,7 @@ impl FMP4Mux {
|
||||||
|
|
||||||
// Check if language or orientation tags have already been
|
// Check if language or orientation tags have already been
|
||||||
// received
|
// received
|
||||||
let mut orientation = None;
|
let mut orientation = Default::default();
|
||||||
let mut language_code = None;
|
let mut language_code = None;
|
||||||
pad.sticky_events_foreach(|ev| {
|
pad.sticky_events_foreach(|ev| {
|
||||||
if let gst::EventView::Tag(ev) = ev.view() {
|
if let gst::EventView::Tag(ev) = ev.view() {
|
||||||
|
@ -3000,9 +3001,9 @@ impl FMP4Mux {
|
||||||
language_code = Stream::parse_language_code(l.get());
|
language_code = Stream::parse_language_code(l.get());
|
||||||
} else if tag.get::<gst::tags::ImageOrientation>().is_some() {
|
} else if tag.get::<gst::tags::ImageOrientation>().is_some() {
|
||||||
if tag.scope() == gst::TagScope::Global {
|
if tag.scope() == gst::TagScope::Global {
|
||||||
state.orientation = gst_video::VideoOrientationMethod::from_tag(tag);
|
state.orientation = TransformMatrix::from_tag(self, ev);
|
||||||
} else {
|
} else {
|
||||||
orientation = gst_video::VideoOrientationMethod::from_tag(tag);
|
orientation = TransformMatrix::from_tag(self, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3168,9 +3169,7 @@ impl FMP4Mux {
|
||||||
caps: s.caps.clone(),
|
caps: s.caps.clone(),
|
||||||
extra_header_data: s.extra_header_data.clone(),
|
extra_header_data: s.extra_header_data.clone(),
|
||||||
language_code: s.language_code,
|
language_code: s.language_code,
|
||||||
orientation: s
|
orientation: s.orientation,
|
||||||
.orientation
|
|
||||||
.unwrap_or(gst_video::VideoOrientationMethod::Identity),
|
|
||||||
elst_infos: s.get_elst_infos().unwrap_or_else(|e| {
|
elst_infos: s.get_elst_infos().unwrap_or_else(|e| {
|
||||||
gst::error!(CAT, "Could not prepare edit lists: {e:?}");
|
gst::error!(CAT, "Could not prepare edit lists: {e:?}");
|
||||||
|
|
||||||
|
@ -3193,9 +3192,7 @@ impl FMP4Mux {
|
||||||
streams,
|
streams,
|
||||||
write_mehd: settings.write_mehd,
|
write_mehd: settings.write_mehd,
|
||||||
duration: if at_eos { duration } else { None },
|
duration: if at_eos { duration } else { None },
|
||||||
orientation: state
|
orientation: state.orientation,
|
||||||
.orientation
|
|
||||||
.unwrap_or(gst_video::VideoOrientationMethod::Identity),
|
|
||||||
write_edts,
|
write_edts,
|
||||||
start_utc_time: if variant == super::Variant::ONVIF {
|
start_utc_time: if variant == super::Variant::ONVIF {
|
||||||
state
|
state
|
||||||
|
@ -3772,10 +3769,10 @@ impl AggregatorImpl for FMP4Mux {
|
||||||
state.need_new_header = true;
|
state.need_new_header = true;
|
||||||
if tag.scope() == gst::TagScope::Stream {
|
if tag.scope() == gst::TagScope::Stream {
|
||||||
let stream = state.mut_stream_from_pad(aggregator_pad).unwrap();
|
let stream = state.mut_stream_from_pad(aggregator_pad).unwrap();
|
||||||
stream.orientation = gst_video::VideoOrientationMethod::from_tag(tag);
|
stream.orientation = TransformMatrix::from_tag(self, ev);
|
||||||
stream.tag_changed = true;
|
stream.tag_changed = true;
|
||||||
} else {
|
} else {
|
||||||
state.orientation = gst_video::VideoOrientationMethod::from_tag(tag);
|
state.orientation = TransformMatrix::from_tag(self, ev);
|
||||||
// Global orientation change implies tag
|
// Global orientation change implies tag
|
||||||
// change on all streams
|
// change on all streams
|
||||||
for stream in &mut state.streams {
|
for stream in &mut state.streams {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
use crate::fmp4mux::imp::CAT;
|
use crate::fmp4mux::imp::CAT;
|
||||||
use gst::glib;
|
use gst::glib;
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
|
use gst::subclass::prelude::*;
|
||||||
|
|
||||||
mod boxes;
|
mod boxes;
|
||||||
mod imp;
|
mod imp;
|
||||||
|
@ -75,14 +76,56 @@ pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransformMatrix = [[u8; 4]; 9];
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct TransformMatrix([[u8; 4]; 9]);
|
||||||
|
|
||||||
|
impl std::ops::Deref for TransformMatrix {
|
||||||
|
type Target = [[u8; 4]; 9];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for &TransformMatrix {
|
||||||
|
fn default() -> &'static TransformMatrix {
|
||||||
|
&IDENTITY_MATRIX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransformMatrix {
|
||||||
|
fn from_tag(obj: &impl ObjectSubclass, tag: &gst::event::Tag) -> &'static TransformMatrix {
|
||||||
|
gst_video::VideoOrientationMethod::from_tag(tag.tag()).map_or(Default::default(), {
|
||||||
|
|orientation| match orientation {
|
||||||
|
gst_video::VideoOrientationMethod::Identity => &IDENTITY_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::_90r => &ROTATE_90R_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::_180 => &ROTATE_180_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::_90l => &ROTATE_90L_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::Horiz => &FLIP_HORZ_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::Vert => &FLIP_VERT_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::UrLl => &FLIP_ROTATE_90R_MATRIX,
|
||||||
|
gst_video::VideoOrientationMethod::UlLr => &FLIP_ROTATE_90L_MATRIX,
|
||||||
|
_ => {
|
||||||
|
gst::info!(
|
||||||
|
CAT,
|
||||||
|
imp = obj,
|
||||||
|
"Orientation {:?} not yet supported",
|
||||||
|
orientation
|
||||||
|
);
|
||||||
|
&IDENTITY_MATRIX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! tm {
|
macro_rules! tm {
|
||||||
( $($v:expr),* ) => {
|
( $($v:expr),* ) => {
|
||||||
[
|
TransformMatrix([
|
||||||
$(
|
$(
|
||||||
(($v << 16) as i32).to_be_bytes(),
|
(($v << 16) as i32).to_be_bytes(),
|
||||||
)*
|
)*
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,25 +172,6 @@ const FLIP_ROTATE_90L_MATRIX: TransformMatrix = tm!(0, 1, 0,
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 0, (1 << 14));
|
0, 0, (1 << 14));
|
||||||
|
|
||||||
pub(crate) fn transform_matrix(
|
|
||||||
orientation: &gst_video::VideoOrientationMethod,
|
|
||||||
) -> &'static TransformMatrix {
|
|
||||||
match orientation {
|
|
||||||
gst_video::VideoOrientationMethod::Identity => &IDENTITY_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::_90r => &ROTATE_90R_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::_180 => &ROTATE_180_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::_90l => &ROTATE_90L_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::Horiz => &FLIP_HORZ_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::Vert => &FLIP_VERT_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::UrLl => &FLIP_ROTATE_90R_MATRIX,
|
|
||||||
gst_video::VideoOrientationMethod::UlLr => &FLIP_ROTATE_90L_MATRIX,
|
|
||||||
_ => {
|
|
||||||
gst::info!(CAT, "Orientation {:?} not yet supported", orientation);
|
|
||||||
&IDENTITY_MATRIX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct HeaderConfiguration {
|
pub(crate) struct HeaderConfiguration {
|
||||||
variant: Variant,
|
variant: Variant,
|
||||||
|
@ -162,7 +186,7 @@ pub(crate) struct HeaderConfiguration {
|
||||||
|
|
||||||
write_mehd: bool,
|
write_mehd: bool,
|
||||||
duration: Option<gst::ClockTime>,
|
duration: Option<gst::ClockTime>,
|
||||||
orientation: gst_video::VideoOrientationMethod,
|
orientation: &'static TransformMatrix,
|
||||||
|
|
||||||
/// Start UTC time in ONVIF mode.
|
/// Start UTC time in ONVIF mode.
|
||||||
/// Since Jan 1 1601 in 100ns units.
|
/// Since Jan 1 1601 in 100ns units.
|
||||||
|
@ -194,7 +218,7 @@ pub(crate) struct HeaderStream {
|
||||||
|
|
||||||
// Tags meta for audio language and video orientation
|
// Tags meta for audio language and video orientation
|
||||||
language_code: Option<[u8; 3]>,
|
language_code: Option<[u8; 3]>,
|
||||||
orientation: gst_video::VideoOrientationMethod,
|
orientation: &'static TransformMatrix,
|
||||||
|
|
||||||
/// Edit list clipping information
|
/// Edit list clipping information
|
||||||
elst_infos: Vec<ElstInfo>,
|
elst_infos: Vec<ElstInfo>,
|
||||||
|
|
Loading…
Reference in a new issue