transcriberbin: fix naming of subtitle pads

When subtitle pads are added dynamically, the suffix used was
"synthesis" instead of the expected "subtitle".

This fixes it by refactoring the code to define a new enum with a name()
parameter for the types of custom output channels.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2318>
This commit is contained in:
Mathieu Duponchelle 2025-06-25 16:34:07 +02:00 committed by GStreamer Marge Bot
parent efb0ae5e1f
commit c269ef50dd

View file

@ -126,13 +126,28 @@ struct CaptionChannel {
caption_streams: HashSet<String>, caption_streams: HashSet<String>,
} }
#[derive(Clone, Copy)]
enum CustomOutputChannelType {
Synthesis,
Subtitle,
}
impl CustomOutputChannelType {
fn name(&self) -> &str {
match self {
Self::Synthesis => "synthesis",
Self::Subtitle => "subtitle",
}
}
}
#[derive(Clone)] #[derive(Clone)]
struct CustomOutputChannel { struct CustomOutputChannel {
bin_description: String, bin_description: String,
bin: gst::Bin, bin: gst::Bin,
language: String, language: String,
latency: gst::ClockTime, latency: gst::ClockTime,
suffix: String, type_: CustomOutputChannelType,
} }
/* Locking order: State, Settings, PadState, PadSettings */ /* Locking order: State, Settings, PadState, PadSettings */
@ -346,10 +361,11 @@ impl TranscriberBin {
Ok(()) Ok(())
} }
fn construct_synthesis_channel( fn construct_custom_output_channel(
&self, &self,
lang: &str, lang: &str,
bin_description: &str, bin_description: &str,
type_: CustomOutputChannelType,
) -> Result<CustomOutputChannel, Error> { ) -> Result<CustomOutputChannel, Error> {
let bin = gst::Bin::new(); let bin = gst::Bin::new();
let queue = gst::ElementFactory::make("queue").build()?; let queue = gst::ElementFactory::make("queue").build()?;
@ -379,44 +395,7 @@ impl TranscriberBin {
bin, bin,
language: String::from(lang), language: String::from(lang),
latency, latency,
suffix: "synthesis".to_string(), type_,
})
}
fn construct_subtitle_channel(
&self,
lang: &str,
bin_description: &str,
) -> Result<CustomOutputChannel, Error> {
let bin = gst::Bin::new();
let queue = gst::ElementFactory::make("queue").build()?;
let processor = gst::parse::bin_from_description_full(
bin_description,
true,
None,
gst::ParseFlags::NO_SINGLE_ELEMENT_BINS,
)?;
let latency = query_latency(&processor)?;
bin.add_many([&queue, &processor])?;
gst::Element::link_many([&queue, &processor])?;
queue.set_property("max-size-buffers", 0u32);
queue.set_property("max-size-time", 0u64);
let sinkpad = gst::GhostPad::with_target(&queue.static_pad("sink").unwrap()).unwrap();
bin.add_pad(&sinkpad)?;
let srcpad = gst::GhostPad::with_target(&processor.static_pad("src").unwrap()).unwrap();
bin.add_pad(&srcpad)?;
Ok(CustomOutputChannel {
bin_description: bin_description.to_string(),
bin,
language: String::from(lang),
latency,
suffix: "subtitle".to_string(),
}) })
} }
@ -1254,7 +1233,7 @@ impl TranscriberBin {
internal_bin: &gst::Bin, internal_bin: &gst::Bin,
serial: Option<u32>, serial: Option<u32>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut pad_name = format!("src_{}_{}", channel.suffix, channel.language); let mut pad_name = format!("src_{}_{}", channel.type_.name(), channel.language);
let srcpad = pad_transcription_bin.static_pad(&pad_name).unwrap(); let srcpad = pad_transcription_bin.static_pad(&pad_name).unwrap();
let _ = pad_transcription_bin.remove_pad(&srcpad); let _ = pad_transcription_bin.remove_pad(&srcpad);
@ -1392,7 +1371,11 @@ impl TranscriberBin {
let bin_description = value.get::<String>()?; let bin_description = value.get::<String>()?;
pad_state.synthesis_channels.insert( pad_state.synthesis_channels.insert(
language.to_string(), language.to_string(),
self.construct_synthesis_channel(language, &bin_description)?, self.construct_custom_output_channel(
language,
&bin_description,
CustomOutputChannelType::Synthesis,
)?,
); );
} }
@ -1414,7 +1397,11 @@ impl TranscriberBin {
let bin_description = value.get::<String>()?; let bin_description = value.get::<String>()?;
pad_state.subtitle_channels.insert( pad_state.subtitle_channels.insert(
language.to_string(), language.to_string(),
self.construct_subtitle_channel(language, &bin_description)?, self.construct_custom_output_channel(
language,
&bin_description,
CustomOutputChannelType::Subtitle,
)?,
); );
} }
@ -1567,7 +1554,7 @@ impl TranscriberBin {
&self, &self,
languages: &Option<gst::Structure>, languages: &Option<gst::Structure>,
channels_map: &mut HashMap<String, CustomOutputChannel>, channels_map: &mut HashMap<String, CustomOutputChannel>,
channel_type_logname: &str, channel_type: CustomOutputChannelType,
) -> Result<(Vec<CustomOutputChannel>, Vec<CustomOutputChannel>), Error> { ) -> Result<(Vec<CustomOutputChannel>, Vec<CustomOutputChannel>), Error> {
let mut updates = HashMap::new(); let mut updates = HashMap::new();
let mut old_languages: HashSet<String> = channels_map.keys().cloned().collect(); let mut old_languages: HashSet<String> = channels_map.keys().cloned().collect();
@ -1599,36 +1586,42 @@ impl TranscriberBin {
for (language_code, update) in updates { for (language_code, update) in updates {
match update { match update {
CustomChannelUpdate::Remove => { CustomChannelUpdate::Remove => {
let synthesis_channel = channels_map.remove(&language_code).unwrap(); let channel = channels_map.remove(&language_code).unwrap();
channels_to_remove.push(synthesis_channel); channels_to_remove.push(channel);
gst::debug!( gst::debug!(
CAT, CAT,
imp = self, imp = self,
"{channel_type_logname} channel {language_code} will be removed" "{} channel {language_code} will be removed",
channel_type.name()
); );
} }
CustomChannelUpdate::Upsert(bin_description) => { CustomChannelUpdate::Upsert(bin_description) => {
if let Some(synthesis_channel) = channels_map.remove(&language_code) { if let Some(channel) = channels_map.remove(&language_code) {
channels_to_remove.push(synthesis_channel); channels_to_remove.push(channel);
gst::debug!( gst::debug!(
CAT, CAT,
imp = self, imp = self,
"{channel_type_logname} channel {language_code} will be removed" "{} channel {language_code} will be removed",
channel_type.name()
); );
} }
let synthesis_channel = let channel = self.construct_custom_output_channel(
self.construct_synthesis_channel(&language_code, &bin_description)?; &language_code,
channels_to_add.push(synthesis_channel.clone()); &bin_description,
channels_map.insert(language_code.clone(), synthesis_channel); channel_type,
)?;
channels_to_add.push(channel.clone());
channels_map.insert(language_code.clone(), channel);
gst::debug!( gst::debug!(
CAT, CAT,
imp = self, imp = self,
"{channel_type_logname} channel {language_code} will be added" "{} channel {language_code} will be added",
channel_type.name()
); );
} }
} }
@ -1870,7 +1863,7 @@ impl TranscriberBin {
serial: Option<u32>, serial: Option<u32>,
channel: &CustomOutputChannel, channel: &CustomOutputChannel,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut pad_name = format!("src_{}_{}", channel.suffix, channel.language); let mut pad_name = format!("src_{}_{}", channel.type_.name(), channel.language);
let srcpad = gst::GhostPad::builder_with_target(&channel.bin.static_pad("src").unwrap()) let srcpad = gst::GhostPad::builder_with_target(&channel.bin.static_pad("src").unwrap())
.unwrap() .unwrap()
.name(&pad_name) .name(&pad_name)
@ -1958,14 +1951,14 @@ impl TranscriberBin {
.prepare_custom_output_channel_updates( .prepare_custom_output_channel_updates(
&pad_settings.synthesis_languages, &pad_settings.synthesis_languages,
&mut pad_state.synthesis_channels, &mut pad_state.synthesis_channels,
"synthesis", CustomOutputChannelType::Synthesis,
)?; )?;
let (subtitle_channels_to_remove, subtitle_channels_to_add) = self let (subtitle_channels_to_remove, subtitle_channels_to_add) = self
.prepare_custom_output_channel_updates( .prepare_custom_output_channel_updates(
&pad_settings.subtitle_languages, &pad_settings.subtitle_languages,
&mut pad_state.subtitle_channels, &mut pad_state.subtitle_channels,
"subtitle", CustomOutputChannelType::Subtitle,
)?; )?;
let (languages_to_remove, languages_to_add) = let (languages_to_remove, languages_to_add) =
@ -2273,7 +2266,7 @@ impl TranscriberBin {
fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool { fn src_query(&self, pad: &gst::Pad, query: &mut gst::QueryRef) -> bool {
use gst::QueryViewMut; use gst::QueryViewMut;
gst::log!(CAT, obj = pad, "Handling query {:?}", query); gst::trace!(CAT, obj = pad, "Handling query {:?}", query);
match query.view_mut() { match query.view_mut() {
QueryViewMut::Latency(q) => { QueryViewMut::Latency(q) => {
@ -2364,7 +2357,7 @@ impl TranscriberBin {
fn video_sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool { fn video_sink_event(&self, pad: &gst::Pad, event: gst::Event) -> bool {
use gst::EventView; use gst::EventView;
gst::log!(CAT, obj = pad, "Handling event {:?}", event); gst::trace!(CAT, obj = pad, "Handling event {:?}", event);
match event.view() { match event.view() {
EventView::Caps(e) => { EventView::Caps(e) => {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();