mp4mux: Store language tags per stream and not globally

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2193>
This commit is contained in:
Sebastian Dröge 2025-04-14 15:43:28 +03:00 committed by GStreamer Marge Bot
parent 269e469a7b
commit 3224cf6f06
3 changed files with 28 additions and 9 deletions

View file

@ -433,7 +433,7 @@ fn language_code(lang: impl std::borrow::Borrow<[u8; 3]>) -> u16 {
fn write_mdhd(
v: &mut Vec<u8>,
header: &super::Header,
_header: &super::Header,
stream: &super::Stream,
creation_time: u64,
) -> Result<(), Error> {
@ -456,7 +456,7 @@ fn write_mdhd(
v.extend(duration.to_be_bytes());
// Language as ISO-639-2/T
if let Some(lang) = header.language_code {
if let Some(lang) = stream.language_code {
v.extend(language_code(lang).to_be_bytes());
} else {
v.extend(language_code(b"und").to_be_bytes());

View file

@ -148,6 +148,9 @@ struct Stream {
extra_header_data: Option<Vec<u8>>,
/// Language code from tags
language_code: Option<[u8; 3]>,
/// Orientation from tags
orientation: Option<ImageOrientation>,
}
@ -282,9 +285,6 @@ struct State {
/// Size of the `mdat` as written so far.
mdat_size: u64,
/// Language code from tags
language_code: Option<[u8; 3]>,
}
#[derive(Default)]
@ -1220,6 +1220,7 @@ impl MP4Mux {
end_pts: None,
running_time_utc_time_mapping: None,
extra_header_data: None,
language_code: None,
orientation: None,
});
}
@ -1434,7 +1435,9 @@ impl AggregatorImpl for MP4Mux {
self.parent_sink_event_pre_queue(aggregator_pad, event)
}
EventView::Tag(ev) => {
if let Some(tag_value) = ev.tag().get::<gst::tags::LanguageCode>() {
let tag = ev.tag();
if let Some(tag_value) = tag.get::<gst::tags::LanguageCode>() {
let lang = tag_value.get();
gst::trace!(
CAT,
@ -1451,7 +1454,21 @@ impl AggregatorImpl for MP4Mux {
for (out, c) in Iterator::zip(language_code.iter_mut(), lang.chars()) {
*out = c as u8;
}
state.language_code = Some(language_code);
if tag.scope() == gst::TagScope::Global {
gst::info!(
CAT,
imp = self,
"Language tags scoped 'global' are considered stream tags",
);
}
for stream in &mut state.streams {
if &stream.sinkpad == aggregator_pad {
stream.language_code = Some(language_code);
break;
}
}
}
} else if let Some(tag_value) = ev.tag().get::<gst::tags::ImageOrientation>() {
let orientation = tag_value.get();
@ -1736,6 +1753,7 @@ impl AggregatorImpl for MP4Mux {
image_sequence: stream.image_sequence_mode(),
chunks: stream.chunks,
extra_header_data: stream.extra_header_data.clone(),
language_code: stream.language_code,
orientation: stream.orientation,
});
}
@ -1744,7 +1762,6 @@ impl AggregatorImpl for MP4Mux {
variant: self.obj().class().as_ref().variant,
movie_timescale: settings.movie_timescale,
streams,
language_code: state.language_code,
})
.map_err(|err| {
gst::error!(CAT, imp = self, "Failed to create moov box: {err}");

View file

@ -203,6 +203,9 @@ pub(crate) struct Stream {
// More data to be included in the fragmented stream header
extra_header_data: Option<Vec<u8>>,
// Language code from tags
language_code: Option<[u8; 3]>,
/// Orientation from tags
orientation: Option<ImageOrientation>,
@ -220,7 +223,6 @@ pub(crate) struct Header {
/// Pre-defined movie timescale if not 0.
movie_timescale: u32,
streams: Vec<Stream>,
language_code: Option<[u8; 3]>,
}
#[allow(clippy::upper_case_acronyms)]