Chaining pad_added callback for multiple dynamic pad elements

129 Views Asked by At

I am working with a rtsp stream where the one of the channels is video and other could be either audio or onvif data.

I need to detect if the second rtspsrc pad(channel) is audio and then setup the pipeline to decode the audio stream.

First I detect if the newly added pad in rtspsrc is audio by adding a connect_pad_added. When it is audio then I create a decodebin and then attached to the src_pad and add another connect_pad_added to the decodebin this time to receive the src_pad and then create the rest of the pipeline.

Somehow the first connect_pad_added to the rtspsrc gets called but not the one I connect to the decode bin.

Is it not okay to chain the pad_added connections like that? What is a better way to do it in such a scenario?

Here is a code snippet of what I am doing.

From the pipeline launched through parse_launch I get the rtspsrc element let rtspsrc=pipeline.by_name("basesrc").

rtspsrc.connect_pad_added(|src, src_pad| {
    // get the pad struct and detect media type
    let media_type = src_pad.current_caps().and_then(|caps| {
        let new_pad_struct = caps
            .structure(0)
            .expect("Failed to get first structure of caps for audio");
        for i in 0..new_pad_struct.n_fields() {
            match new_pad_struct.nth_field_name(i).unwrap() {
                "media" => {
                    // check if field value starts with audio
                    audio = true
                }
                _ => {}
            }
        }
        Some(audio)
    });

    match media_type {
        Some(is_audio) => {
            if is_audio {
                let audio_decode = gst::ElementFactory::make("decodebin", None)
                    .expect("unable to create decodebin");
                pipeline
                    .add_many(&[&audio_decode])
                    .expect("unable to add audio decoder to pipeline bin");
                let sink_pad = audio_decode.static_pad("sink").ok_or(/*...*/);
                src_pad
                    .link(&sink_pad)
                    .expect("unable to link src_pad to audio_decode sinkpad");
                audio_decode.connect_pad_added(move |dbin, audio_src_pad| {
                    // setup the rest of pipeline audiodecoder ! encoder ! tee name=t t.! hlssink2.. t. ! hlssink2
                    //.....
                });
            }
        }
        None => {
            log::warn!("failed to get media_type from pad after pad added");
        }
    }
});
1

There are 1 best solutions below

0
Gatothgaj On BEST ANSWER

The issue was that once the pipeline is in running state, the newly added decodebin is not in same state as the rest of the pipeline.

calling decodebin.sync_state_with_parent() after linking the rtspsrc.src->decodebin.sink fixed the problem.