VideoInputFormatChanged() sometimes not called

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

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

VideoInputFormatChanged() sometimes not called

PostWed Apr 22, 2015 3:59 pm

Most of the time our VideoInputFormatChanged()
callback gets called, but sometimes it doesn't.

Typically, the problem is easiest to reproduce when exactly 2 of the 4 inputs on a DeckLink Quad
card are plugged in and changing format simultaneously.

When this happens, our VideoInputFrameArrived() callback continues to get called with flag
'bmdFrameHasNoInputSource'

Is there any API to force the VideoInputFormatChanged callback to happen, or to query what the last callback was.

One thing I don't want to do is poll continuously. I want to retry exactly once after a failure and a timeout.

If there was an inexpensive API which I could poll to detect a missed format change,
this would solve our issues.
By inexpensive, I mean an API which requires no semaphore locking in my code OR in SDK driver code.


I don't want this question to devolve into a discussion about machine sleep.
Putting the machine to sleep is an unfair test.
However, in general I’ve found that if my code can handle unfair tests, like waking from sleep,
then it can handle just about any dicey situation.
Our Macs have sleep disabled, power saving disabled, as well as many other System Preferences which could slow down the Mac or cause apps to nap.
This bug is very difficult to reproduce, but one way to reproduce this bug every time is to put the Mac to sleep, then make a change, then wake Mac up from sleep.

Code: Select all
I use this design pattern for this type of thing:

driver code:
int globalChangeIncrement; // increments after every change

driver code:
if ( changeDetected )
{
globalChangeIncrement++;

// sometimes I use this instead, when multiple threads could be writing this:
#include <libkern/OSAtomic.h>
OSAtomicIncrement32Barrier( & globalChangeIncrement );


callbackToCustomersCode(); // such as VideoInputFormatChanged()
}

SDK API:
static int IDeckLinkInput::GetGlobalChangeIncrement()
{
return globalChangeIncrement;
}


USAGE EXAMPLE

static int sCustomerChangeIncrement;

HRESULT DeckLinkInput::VideoInputFormatChanged (BMDVideoInputFormatChangedEvents evt, IDeckLinkDisplayMode* newmode, BMDDetectedVideoInputFormatFlags flags)
{
sCustomerChangeIncrement = decklinkinput-> GetGlobalChangeIncrement()
… process change
}



I could then write code that polls this variable once every 5 seconds:

if ( decklink_is_not_working &&
no_changes_in_last_5_seconds &&
sCustomerChangeIncrement != decklinkinput-> GetGlobalChangeIncrement() )
{
scheduleCleanUpAndReInit(); // which calls StopStreams, etc, etc.
}




We use the DeckLink SDK extensively. We have at least 100 machines with DeckLink cards.
Offline
User avatar

Roman Ryltsov

  • Posts: 21
  • Joined: Sun May 12, 2013 6:52 pm
  • Location: Kharkov, Ukraine

Re: VideoInputFormatChanged() sometimes not called

PostWed Apr 22, 2015 7:12 pm

If you suffer from lost VideoInputFormatChanged notifications, perhaps your best strategy would be restart streaming once you have been receiving bmdFrameHasNoInputSource for a few seconds. On restart you get another chance to get VideoInputFormatChanged.
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostWed Apr 22, 2015 7:52 pm

We have considered this strategy, but restarting is an expensive operation.

In fact, I *think* we have tried this strategy in the past, and decided to back out the change.
We never want to do an expensive operation which could temporarily affect performance.

However, if we could know for sure that the operation is necessary, then it makes sense to do it.

Correct me if I'm wrong:
bmdFrameHasNoInputSource means that an input has gone away, but it may come back seamlessly at any moment. When it comes back, it may not require a VideoInputFormatChanged() called.
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostTue Jan 12, 2016 6:06 pm

Still having intermittent, hard to reproduce problem where VideoFormatChanged() not always being called.
Again, is there an undocumented way to periodically do an inexpensive poll for a change?

Is my question unreasonable?
Offline

Nicholas Gill

Blackmagic Design

  • Posts: 169
  • Joined: Mon May 04, 2015 10:28 pm

Re: VideoInputFormatChanged() sometimes not called

PostThu Jan 14, 2016 12:09 am

Hi Keith,

Could you please describe the scenario which results in a missed VideoInputFormatChanged callback?

It would also be helpful to have a description of the specific API calls your application uses to handle mode detection.

One possibility specific to the DeckLink Quad exists if the application uses the bmdDeckLinkConfigBypass feature.

With the DeckLink Quad, if the bypass relays are triggered, the input is directly connected to the output and capture (and by extension, mode detection) will not be possible until capture is restarted or the bypass setting re-enabled.

Cheers,

-nick
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostSat Jul 28, 2018 12:26 am

3 years later, I'm still having similar problems managing DeckLink inputs.

Here's a scenario that so far *seems* to be reproducible every time.
Mind you I have yet to reboot my computers, and maybe this problem will not be reproducible once I reboot my machine(s).
Now, granted, putting a machine to sleep and waking from nightmare is always a dicey situation for device drivers.
However, if your hardware/software can successfully wake from nightmare, then you have come a long way in providing a bulletproof system.

Here's a scenario with 2 Macs:
[1]Computer A has DeckLink quad card (connected to older Mac Pro with a *real* PCI bus)
[2]Computer B has Ultrastudio 4k (connected via thunderbolt to Mac Pro 2013)
[3]Create a camera loop by having UltraStudio SDI output -> DeckLink quad SDI input
[4]Complete the loop by having one of the quad card SDIs used as an output in Outputs tab.
[5]Put Computer A asleep (the one with Quad card)… this takes effort cuz the Mac actually resists going to sleep with all the sleep-prevention mechanisms we have built in, but when it does finally sleep, you hear the Quad cards relays click!
[6]Wake up Computer A
[7]Quad cards input doesn’t seem to be detected (no checkmark)
[8]To fix it, you have to mess with the UltraStudio in Prefs tab… just deselecting/reselecting UltraStudio popup in Prefs tab seems to wake up the Quad cards input on the *other* computer ???

[9]I verified that Ultrastudio is outputting valid video on its SDI output. I verified by moving the mini SDI input to another input on the Quad card, and it picked up the signal from the UltraStudio SDI just fine.

[10]So this seems to confirm that the problem is on the Quad card's input.
However, after further tests, sometimes moving the SDI input to other inputs on the Quad card does *not* always work. Sometimes I have to re-initialize the Ultrastudio by


Here's a sampling of our code for steps [8] & [10] above (tear down and recreate DeckLinkInput):
Code: Select all
   
   if(decklinkinput) // were we successful last time?
   {
      decklinkinput->StopStreams();
      decklinkinput->FlushStreams();
      decklinkinput->DisableVideoInput();
      
      // are we selecting a different card?
      parent->lockMutex();
      bool sourceChanged = ([[params objectForKey:@"SourceID"] intValue] != [[parent->setupDict objectForKey:@"SourceID"] intValue]);
        sourceChanged |= ([[params objectForKey:kDeviceUIDKey] intValue] != [[parent->setupDict objectForKey:kDeviceUIDKey] intValue]);
      parent->unlockMutex();

      if (sourceChanged || (iSetupFlags & kVideoInputSetupForce) )
      {
         decklinkinput->Release();
         decklinkinput = NULL;
         if (decklink) decklink->Release();
         decklink = NULL;
            persist_id = 0;
         
         // no size yet
         parent->width = parent->height = 0;
         mode = 0;
      }
   }

        // ...iterate through devices using standard DeckLink iterator, to find matching UID...
        // <code omitted here>

       // once we've located matching device:
      err = decklinkinput->EnableVideoInput(mode, pixelFormat, formatDetectionFlag);
      if(err) printf("######## EnableVideoInput error %d (0x%x)\n", (int)err, (unsigned int)err);
      bool alreadyInUse = (err == E_ACCESSDENIED);
      bool eNOTIMPL = (err == E_NOTIMPL); // unknown
      err = decklinkinput->StartStreams();
      if(err) printf("######## StartStreams error %d (0x%x)\n", (int)err, (unsigned int)err);

      if(alreadyInUse || eNOTIMPL)
      {
         if ( alreadyInUse )
            parent->setErrorString((char*)"(Already In Use)");
         else
            parent->setErrorString((char*)"(E_NOTIMPL)"); // I have no clue what E_NOTIMPL means
         
         Cleanup();
      }
      else if ( err )
      {
         parent->setErrorString((char*)"Error (see log)" );
         Cleanup();
      }
      else
      {
         parent->setErrorString((char*)"");
      }





One question I have... I wonder if there's something in the SDI specification whereby the sender can essentially 'wake up' a receiver? For example is there something like an EDID exchange process that gets kicked off when you reinitialize a DeckLink device?
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostMon Jul 30, 2018 4:40 pm

FYI, I am working with Matt Corke.
However, note that my 'wake-from-sleep' test case is different then our clients' case. Our clients definitely do not put the computer to sleep. I personally have not been able to reproduce the clients' E_NOTIMPL case.


Here's related support email correspondence between Matt and Cameron Nichols:
Thanks for your detailed error report.

Are you able to share the code for calling EnableVideoInput, based on invalid --> valid source? There are a few reasons for E_NOTIMPL return and I wish to try to replicate this locally. Also, can you provide a debug log, including EnableVideoInput entry values for displayMode, pixelFormat, flags, and return would be also useful for analysis.


Here's a sample of our log for the wake-from-sleep test case (again, different from clients E_NOTIMPL case).
After computer A wake-from-sleep machine wakes up, its configured with '24ps' format, and with auto-format enabled.

I go to the computer B (the one with the Ultrastudio 4K that was NOT sleeping),
and re-configure its output.

Computer A then sees the format change and starts working normally.

1:33:53.263 formatchg 'hp60'
11:34:03.153 formatchg '24ps'
11:34:03.161 ### DeckLink input #2 acquired signal, new: √ DLink 2: 1920x1080 '24ps'
11:34:04.242 videoInput setup [255.242]:
11:34:04.242 --- 'DeckLinkUID', old: 3148288 new: 3148288
11:34:04.242 --- 'ShowSubstitute', old: 0 new: 0
11:34:04.242 --- 'SourceID', old: 1 new: 1
11:34:04.242 --- 'QuarterSize', old: 0 new: 0
11:34:04.242 --- 'SourceFormat', old: 24ps new: 24ps
11:34:04.242 --- 'SourceDescription', old: Disabled new: Disabled
11:34:04.242 --- 'SourceType', old: Blackmagic new: Blackmagic
11:34:04.242 ### DeckLink input #2 init: '24ps'
11:34:04.630 ### DeckLink input #2 lost signal
11:34:04.967 ### DeckLink input #2 acquired signal, new: √ DLink 2: 1920x1080 '24ps'


If your client is confident that they are using the same display mode, it may be possible to remove the repeated call to EnableVideoInput, and replace with StopStreams, FlushStreams and StartStreams to restart capture.


Note that my 'wake-from-sleep' test case is different then our clients' case. Our clients definitely do not put the computer to sleep. I personally have not been able to reproduce the clients' E_NOTIMPL case.

The StartStreams return E_UNEXPECTED would be likely due to earlier failure at EnableVideoInput, as the driver would be still in a disabled input state.

Kind Regards
Cameron Nichols
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostMon Jul 30, 2018 5:04 pm

Just tested the suggestion to StopStreams, FlushStreams, StartStreams. It does not fix the wake-from-sleep problem.

Some of the time, deleting and re-creating using EnableVideoInput fixes the wake-from-sleep problem.
When that doesn't work, deleting and re-creating on the other computer fixes the wake-from-sleep problem.
Offline

Keith Knauber

  • Posts: 14
  • Joined: Wed Apr 22, 2015 3:41 pm

Re: VideoInputFormatChanged() sometimes not called

PostTue Jul 31, 2018 12:37 am

I just discovered another subtle difference.


I'm outputting from Quad card output #1 to the UltraStudio SDI "IN A" connector.
Then I connect from SDI "LOOP A" back to the Quad card input #2.
-OR- I connect from SDI "OUT A" back to the Quad card input #2.

The Ultrastudio 4k’s SDI ‘LOOP A’ connector is much more reliable than the SDI ‘OUT A’ connector when running my tests. About 20% of the time, when using the ‘OUT A’ connector, the Quad card on the other side fails to reacquire signal after reconfiguring. However, when connected to ‘LOOP A’, it never even loses signal while reconfiguring. I suppose this makes sense if the "LOOP A" connector is a direct physical loop that doesn't go through any buffering.

The wake-from-sleep test still fails when using either connector, though.

Return to Software Developers

Who is online

Users browsing this forum: Google [Bot] and 1 guest