Page 1 of 1

IDeckLinkVideoOutputCallback in C# Events not Firing

PostPosted: Mon Feb 27, 2017 9:05 pm
by christopher.c.pond
I have created a simple form that implements the IDeckLinkVideoOutputCallback interface in the same way that the SignalGenCSharp example appears to do so. However, when I run my application, the IDeckLinkVideoOutputCallback.ScheduledFrameCompleted callback is never triggered. If I run the exact same code from the SignalGen project, it runs fine. I suspect I am missing a setting required in my Forms project, but for the life of me I can't find what! Is there a hidden setting I need somewhere to enable this type of callback? Maybe in a Manifest somewhere? I am stumped!

For reference in the signal gen code I have done the following:
    1:Migrated the code environment from VS2010(?) to VS2015.
    2:Changed the API reference to DecklinkAPI64* for consistency with my app.
    3:Commented out the entirety of the SignalGen constructor (excluding InitializeComponent() and my code.
    4:Removed and then re-added the Audio Callback stuff to test if it was needed (it wasn't).

I am in DotNet 4.6 and VS2015, and a fresh Windows Forms project. I have referenced DecklinkAPI64.dll* from the program files location.


*(C:\Program Files (x86)\Blackmagic Design\Blackmagic Desktop Video\DecklinkAPI64.dll)

Here is my project code:

Code: Select all
public partial class Form1 : Form, IDeckLinkVideoOutputCallback
    {
        IDeckLinkOutput deck;
        IDeckLinkMutableVideoFrame frame;
        IDeckLink d;
        public Form1()
        {
            InitializeComponent();
            IDeckLinkIterator idl = new CDeckLinkIterator();
           
            idl.Next(out d);
            deck = (IDeckLinkOutput)d;
            deck.SetScheduledFrameCompletionCallback(this);
            deck.EnableVideoOutput(_BMDDisplayMode.bmdModeHD720p5994,_BMDVideoOutputFlags.bmdVideoOutputFlagDefault);
            deck.CreateVideoFrame(1280, 720, 1280 * 4, _BMDPixelFormat.bmdFormat8BitBGRA,_BMDFrameFlags.bmdFrameFlagDefault, out frame);
            for(int I =0; I < 60; I++)
            {
                deck.ScheduleVideoFrame(frame, I * 1001, 1001, 60000);
            }
            deck.StartScheduledPlayback(0, 60000, 1);
        }

  void IDeckLinkVideoOutputCallback.ScheduledFrameCompleted(IDeckLinkVideoFrame completedFrame, _BMDOutputFrameCompletionResult result)
        {
            //If Input Present, schedule frames from there. Otherwise Schedule output frames here.
            //This is just to catch a breakpoint...
            int i = 0;

        }

        void IDeckLinkVideoOutputCallback.ScheduledPlaybackHasStopped()
        {

        }
    }




in the Signal Gen code here is my constructor if helpful:

Code: Select all
IDeckLinkOutput deck;
        IDeckLinkMutableVideoFrame frame;
        IDeckLink d;
public SignalGenerator()
        {
            InitializeComponent();
  IDeckLinkIterator idl = new CDeckLinkIterator();           
            idl.Next(out d);
            deck = (IDeckLinkOutput)d;
            deck.SetScheduledFrameCompletionCallback(this);
            deck.EnableVideoOutput(_BMDDisplayMode.bmdModeHD720p5994, _BMDVideoOutputFlags.bmdVideoOutputFlagDefault);
            deck.CreateVideoFrame(1280, 720, 1280 * 4, _BMDPixelFormat.bmdFormat8BitBGRA, _BMDFrameFlags.bmdFrameFlagDefault, out frame);
            FillColourBars(frame);
            for(int I =0; I< 60; I++)
            {
                deck.ScheduleVideoFrame(frame, I * 1001, 60 * 1001, 60000);
            }
            deck.StartScheduledPlayback(0, 60000, 1);
            //Original commented out code below:
            //   m_running = false;

            //   // Create the COM instance
            //   IDeckLinkIterator deckLinkIterator = new CDeckLinkIterator();
            //   if (deckLinkIterator == null)
            //   {
            //       MessageBox.Show("This application requires the DeckLink drivers installed.\nPlease install the Blackmagic DeckLink drivers to use the features of this application", "Error");
            //       Environment.Exit(1);
            //   }

            //   // Get the first DeckLink card
            //   deckLinkIterator.Next(out m_deckLink);
            //   if (m_deckLink == null)
            //   {
            //       MessageBox.Show("This application requires a DeckLink PCI card.\nYou will not be able to use the features of this application until a DeckLink PCI card is installed.", "Error");
            //       Environment.Exit(1);
            //   }

            //   // Get the IDeckLinkOutput interface
            //   m_deckLinkOutput = (IDeckLinkOutput)m_deckLink;

            //   // Provide this class as a delegate to the audio and video output interfaces
            //   m_deckLinkOutput.SetScheduledFrameCompletionCallback(this);
            //   m_deckLinkOutput.SetAudioCallback(this);

            //// Populate the display mode combo with a list of display modes supported by the installed DeckLink card
            //IDeckLinkDisplayModeIterator      displayModeIterator;

            //comboBoxVideoFormat.BeginUpdate();
            //   comboBoxVideoFormat.Items.Clear();

            //   m_deckLinkOutput.GetDisplayModeIterator(out displayModeIterator);

            //   while (true)
            //   {
            //       IDeckLinkDisplayMode deckLinkDisplayMode;

            //       displayModeIterator.Next(out deckLinkDisplayMode);
            //       if (deckLinkDisplayMode == null)
            //           break;

            //       comboBoxVideoFormat.Items.Add(new DisplayModeEntry(deckLinkDisplayMode));
            //   }

            //   comboBoxVideoFormat.EndUpdate();

            //   // Output signal combo box
            //   comboBoxOutputSignal.BeginUpdate();
            //   comboBoxOutputSignal.Items.Clear();
            //   comboBoxOutputSignal.Items.Add(new StringObjectPair<OutputSignal>("Pip", OutputSignal.kOutputSignalPip));
            //   comboBoxOutputSignal.Items.Add(new StringObjectPair<OutputSignal>("Drop", OutputSignal.kOutputSignalDrop));
            //   comboBoxOutputSignal.EndUpdate();

            //   // Audio channels combo box
            //   comboBoxAudioChannels.BeginUpdate();
            //   comboBoxAudioChannels.Items.Clear();
            //   comboBoxAudioChannels.Items.Add("2");
            //   comboBoxAudioChannels.Items.Add("8");
            //   comboBoxAudioChannels.Items.Add("16");
            //   comboBoxAudioChannels.EndUpdate();

            //   // Audio depth combo box
            //   comboBoxAudioDepth.BeginUpdate();
            //   comboBoxAudioDepth.Items.Clear();
            //   comboBoxAudioDepth.Items.Add(new StringObjectPair<_BMDAudioSampleType>("16 Bit", _BMDAudioSampleType.bmdAudioSampleType16bitInteger));
            //   comboBoxAudioDepth.Items.Add(new StringObjectPair<_BMDAudioSampleType>("32 Bit", _BMDAudioSampleType.bmdAudioSampleType32bitInteger));
            //   comboBoxAudioDepth.EndUpdate();

            //   comboBoxVideoFormat.SelectedIndex = 0;
            //   comboBoxOutputSignal.SelectedIndex = 0;
            //   comboBoxAudioChannels.SelectedIndex = 0;
            //   comboBoxAudioDepth.SelectedIndex = 0;

         
        }


Re: IDeckLinkVideoOutputCallback in C# Events not Firing

PostPosted: Tue Feb 28, 2017 4:31 pm
by christopher.c.pond
I helpful, I am including my Dummy project.

Re: IDeckLinkVideoOutputCallback in C# Events not Firing

PostPosted: Mon Apr 24, 2017 9:46 pm
by christopher.c.pond
The fix:
The callbacks need to live under an [MTATHREAD] thread. I was unaware of this limitation, although in hindsight it makes sense...

Man this was frustrating though. If any Decklink engineers happen to look at this, that might be a handy thing to mention on the documentation PDF. A quick search of the PDF does not mention this anywhere. I had to resort to running a DIFF on the signal generator vs my code. Hope this helps someone else.

In short, windows forms default to [STATHREAD] (set in program.cs) and needs to be changed to [MTATHREAD]. Or generate everything on an System.Threading.Thread started as MTA. Haven't tried that last bit yet, but it should be correct...ish.