DeckLinkInputDevice - StopStreams

Ask software engineering and SDK questions for developers working on Mac OS X, Windows or Linux.
  • Author
  • Message
Offline

tomsap

  • Posts: 19
  • Joined: Tue Mar 03, 2020 4:17 pm
  • Real Name: Tom Saplonsky

DeckLinkInputDevice - StopStreams

PostWed Sep 23, 2020 7:02 am

hello,

I have blackmagic 4k extreme. I use a code that similar to StillsCSharp. I got an error at the end of the program in the finally block (at stiils.cs) in this line:

Code: Select all
m_selectedCaptureDevice.StopCapture();


than we go to this function(at DeckLinkInputDevice.cs):

Code: Select all
        public void StopCapture()
        {
            if (!m_currentlyCapturing)
                return;

            RemoveAllListeners();

            // Stop the capture
            m_deckLinkInput.StopStreams();

            // Disable video input
            m_deckLinkInput.DisableVideoInput();

            // Disable callbacks
            m_deckLinkInput.SetScreenPreviewCallback(null);
            m_deckLinkInput.SetCallback(null);

            m_currentlyCapturing = false;
        }


And the program gets stuck in this function:
Code: Select all
m_deckLinkInput.StopStreams();
and does not continue to run, just stuck in there.

Why this can happen?

Thanks,

Tom.
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostWed Sep 23, 2020 11:12 am

Hi Tom,

The most likely the reason for lockup is that you are calling IDeckLinkInput::StopStreams from the context of the IDeckLinkInputCallback::VideoInputFrameArrived callback. Please move the call to StopCapture method to main thread (eg UI thread) or from another another context outside of DeckLinkAPI thread.

Regards
Cameron
Offline

tomsap

  • Posts: 19
  • Joined: Tue Mar 03, 2020 4:17 pm
  • Real Name: Tom Saplonsky

Re: DeckLinkInputDevice - StopStreams

PostWed Sep 23, 2020 12:04 pm

Hi Cameron,

I did not quite understand, should I move the call to

Code: Select all
m_deckLinkInput.StopStreams();


from IDeckLinkInputCallback.VideoInputFrameArrived in DeckLinkInputDevice.cs?

Here is the code:

Code: Select all
void IDeckLinkInputCallback.VideoInputFrameArrived(IDeckLinkVideoInputFrame videoFrame, IDeckLinkAudioInputPacket audioPacket)
        {
            if (videoFrame != null)
            {
             
                bool inputSignalAbsent = videoFrame.GetFlags().HasFlag(_BMDFrameFlags.bmdFrameHasNoInputSource);

                // Detect change in input signal, restart stream when valid stream detected
                if (!inputSignalAbsent && m_prevInputSignalAbsent)
                {
                    m_deckLinkInput.StopStreams();
                    m_deckLinkInput.FlushStreams();
                    m_deckLinkInput.StartStreams();
                }
                m_prevInputSignalAbsent = inputSignalAbsent;

                // Register video frame received event
                var handler = VideoFrameArrivedHandler;

                // Check whether there are any subscribers to VideoFrameArrivedHandler
                if (handler != null)
                {
                    handler(this, new DeckLinkVideoFrameArrivedEventArgs(videoFrame, inputSignalAbsent));
                }
            }

            if (audioPacket != null)
            {
                // Register audio packet received event
                var handler = AudioPacketArrivedHandler;

                // Check whether there are any subscribers to AudioPacketArrivedHandler
                if (handler != null)
                {
                    handler(this, new DeckLinkAudioPacketArrivedEventArgs(audioPacket));
                }
            }

            System.Runtime.InteropServices.Marshal.ReleaseComObject(videoFrame);
        }


And where should I move it?

Thanks,

Tom.
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostThu Sep 24, 2020 2:27 am

Hi Tom,

Thanks for raising this, I notice that this is an issue also in the StillsCSharp SDK sample and we will fix in a future release. The actual process to stop, flush and restart stream should be conducted outside of the callback to avoid deadlock.

To resolve:
1. Create EventArgs for change in signal validity, similar to other EventArgs in DeckLinkInputDevice.cs
Code: Select all
public class DeckLinkInputSignalValidChangedEventArgs : EventArgs
{
    public bool SignalValid { get; }
    public DeckLinkInputSignalValidChangedEventArgs(bool signalValid)
    {
        SignalValid = signalValid;
    }
}

2. Create EventHandler for signal valid change in DeckLinkInputDevice class:
Code: Select all
public event EventHandler<DeckLinkInputSignalValidChangedEventArgs> SignalValidChangedHandler;

3. Call event handler from IDeckLinkInputCallback.VideoInputFrameArrived callback when signal valid state changes:
Code: Select all
// Detect change in input signal, restart stream when valid stream detected
if (inputSignalAbsent != m_prevInputSignalAbsent)
{
    SignalValidChangedHandler?.Invoke(this, new DeckLinkInputSignalValidChangedEventArgs(!inputSignalAbsent));
}
m_prevInputSignalAbsent = inputSignalAbsent;

4. Finally register to event handler to process in another thread:
Code: Select all
m_deckLinkInput.SignalValidChangedHandler += new EventHandler<DeckLinkInputSignalValidChangedEventArgs>((s,e) => this.BeginInvoke((Action)(() => RestartStream()(s,e))));
Then implement RestartStream to call the StopStreams/FlushStreams/StartStreams. Importantly use BeginInvoke (or Tasks) to dispatch the action asynchronously as not to block callback.

As a final note, the reason for adding the StopStreams/FlushStreams/StartStreams code is to ensure that the stream times for incoming video frames and audio packets are aligned after signal discontinuity. Please note this is not a AV sync issue, only that the stream times may have an offset. You can read more at the Desktop Video Developer Support FAQ at https://www.blackmagicdesign.com/support/faq/59024 under topic Audio / Video stream time offset when capturing with DeckLink Duo 2 / Quad 2 in Half Duplex

If you are only interested in video frames, not using DeckLink Duo 2/Quad 2 or not concerned with stream time offset, then you can remove this segment of code completely

Regards
Cameron
Offline

tomsap

  • Posts: 19
  • Joined: Tue Mar 03, 2020 4:17 pm
  • Real Name: Tom Saplonsky

Re: DeckLinkInputDevice - StopStreams

PostThu Sep 24, 2020 7:46 am

Thanks Cameron for the replay this is very helpful!

I don't really understand how the implementation of RestartStream function should be?
And also where should I place the function in the StillsCSharp? in Stiils.cs?

Thanks,

Tom
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostMon Sep 28, 2020 12:15 am

Hi Tom,

The RestartStreams would be a small method that calls StopStreams/FliushStreams/StartStreams and should be implemented in class DeckLinkInputDevice, where the IDeckLinkInput object is a member.

But, please review my final comment in my previous post, you may find that this code segment is not required for your application. It is only required for applications video and audio stream times are important, and you are capturing when capture device is configured with a half-duplex profile. You can check current duplex mode with DeviceStatusCSharp SDK sample (in 11.6 SDK).

Regards
Cameron
Offline

tomsap

  • Posts: 19
  • Joined: Tue Mar 03, 2020 4:17 pm
  • Real Name: Tom Saplonsky

Re: DeckLinkInputDevice - StopStreams

PostMon Sep 28, 2020 6:19 pm

Hi Cameron,

If I understand you correctly when times is not important in my application, I can ignore from the RestartStreams method and delete from IDeckLinkInputCallback.VideoInputFrameArrived this segment of code:

Code: Select all
                if (!inputSignalAbsent && m_prevInputSignalAbsent)
                {
                    m_deckLinkInput.StopStreams();
                    m_deckLinkInput.FlushStreams();
                    m_deckLinkInput.StartStreams();
                }


?

Thanks!

Tom.
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostMon Oct 05, 2020 5:02 am

Hi Tom,

Yes, you should only be concerned about this code segment if:
  • You are using a device where the individual SDI connectors can be configured for output or input, such as the DeckLink Duo 2, and
  • Your application has a dependency on the alignment of the captured video and audio stream times.
For StillsCSharp SDK sample, we will consider removing this code segment in the future, as the sample captures video frames and not audio.

Regards
Cameron
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostMon Oct 26, 2020 1:15 am

Hi Tom,

I rechecked this issue and realised my previous post was incorrect. It is not expected that StopStreams will lock in the thread context of IDeckLinkInputCallback::VideoInputFrameArrived.

I now suspect you are calling StopStreams from within UI thread, potentially with STAThread apartment state?

Regards
Cameron
Offline

paulcarson

  • Posts: 7
  • Joined: Wed Aug 07, 2019 1:51 pm
  • Real Name: Paul Carson

Re: DeckLinkInputDevice - StopStreams

PostFri Jul 02, 2021 7:26 am

Hi,

I've the same issue on a significantly modified StillsCSharp GUI and so require input on the changes I should make. I only need to capture video (no audio or outputting required).
Original SDK was v11.2.
Hardware Eng so not the greatest understanding of OO or Threading.
Thanks,
Paul
Offline

lwy1255

  • Posts: 5
  • Joined: Wed Mar 23, 2022 7:45 am
  • Real Name: li yan

Re: DeckLinkInputDevice - StopStreams

PostWed Apr 06, 2022 9:58 am

I have same issue when I call IDecklinkInput->StopStream, the function doesn't return. I have a decklink quad 2 card with 2 cameras linked to.

Code: Select all
    for (int i = 0; i < inputList.size(); i++)
    {
//        result = inputList[i]->FlushStreams();

        // Stop capture
        result = inputList[i]->StopStreams();

        // Disable the video input interface
        result = inputList[i]->DisableVideoInput();

        inputList[i]->Release();
        deckLinkList[i]->Release();
    }


I call this from UI thread. My cameras indexed 2 and 3, so when i is 0 or 1, the stopstream can return, when i = 2, the program just waiting there.

Any clues?
Offline

Cameron Nichols

Blackmagic Design

  • Posts: 443
  • Joined: Mon Sep 04, 2017 4:05 am

Re: DeckLinkInputDevice - StopStreams

PostSun Apr 10, 2022 11:50 pm

Hi Li,

Check that your calling threads to DeckLinkAPI are managed in a MTAThread apartment state, as this may be causing threading issues that is leading to lockup. Usually this is achieved by single [MTAThread] prior to Main().

If your application requires STA thread, such as if running in WPF, then you should manage calls between STA and MTA apartment states. Please see the SDK sample DeviceStatusCSharp for an example of this.

Regards
Cameron

Return to Software Developers

Who is online

Users browsing this forum: No registered users and 7 guests