Read access violation (this-> X was nullptr) - Decklink SDK

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

makoe29

  • Posts: 16
  • Joined: Wed Apr 14, 2021 11:53 am
  • Real Name: Marco Könemann

Read access violation (this-> X was nullptr) - Decklink SDK

PostWed Jun 16, 2021 1:08 pm

Hello,

i write a little program depending on the Blackmagic Decklink SDK which should capture incoming video and audio. When I use the DeckLinkInput interface I get the read access violation message "this->dl_input was nulltr". After hours of debugging I have no idea how to fix this issue.

Code: Select all
class ControlVideo {
   
public:
    HRESULT result;
   
    IDeckLink *deckLink;
    IDeckLinkInput *dl_input;
    IDeckLinkInputCallback *theCallback;
    IDeckLinkDisplayMode *dl_displayMode;
    IDeckLinkDisplayModeIterator* dl_displayModeIterator;
           
    bool inputCallback(IDeckLinkInput* dl_input);
    bool startCapture();
};
   
/**
 * Function that initializes the input callback
 * The callback will be called for each incoming frame
 */
bool ControlVideo::inputCallback(IDeckLinkInput *dl_input) {
       
    if (dl_input->SetCallback(theCallback) == S_OK) {
        std::cout << "Input Callback called. \n";
        return true;
    }
    else {
        std::cout << "DeckLink Callback fails. \n";
        return false;
    }
}
   

/**
 * Function that start the stream
 */
bool ControlVideo::startCapture() {
   
    ControlVideo ctrlVideo;
   
    //make a callback for each incoming frame
    ctrlVideo.inputCallback(dl_input);
   
    if (dl_input->StartStreams() == S_OK) {
        std::cout << "Stream has been started. \n";
        return true;
    }
    else {
        throw std::runtime_error("Error: Stream can not been started. \n");
        return false;
    }
}
   
int main() {
    //Create object and initialize the DeckLink
    InitializeDecklink init;
    init.initializeDevice();
    init.printDevice();
   
    ControlVideo ctrlVideo;
    ctrlVideo.startCapture();
       
    return 0;
}


The callback function is only a sample. I also have a function for enabeling the input and for checking the display mode - there I got this message too.
Maybe someone have a advice why dl_input is a nullpointer?

Regards
Marco
Offline

Cameron Nichols

Blackmagic Design

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

Re: Read access violation (this-> X was nullptr) - Decklink

PostFri Jun 18, 2021 5:39 am

Hi Marco,

The IDeckLinkInputCallback is a callback interface which should be implemented by the user. You should not infer IDeckLinkInputCallback directly. The following is an example of a class template, you will need to implement all interface methods:
Code: Select all
class MyDeckLinkInputCallback : public IDeckLinkInputCallback
{
public:
   explicit MyDeckLinkInputCallback();
   virtual ~MyDeckLinkInputCallback();

   // IUnknown interface
   HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) override;
   ULONG   STDMETHODCALLTYPE AddRef() override;
   ULONG.  STDMETHODCALLTYPE Release() override;

   // IDeckLinkInputCallback interface
   HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents notificationEvents, IDeckLinkDisplayMode* newDisplayMode, BMDDetectedVideoInputFormatFlags detectedSignalFlags) override;
   HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioPacket) override;
...

private:
   std::atomic<ULONG> m_refCount;
...
};

There are a number of SDK samples that implement the IDeckLinkInputCallback interface, including CapturePreview, CaptureStills, FileCapture and InputLoopThrough.

Regards
Cameron
Offline

makoe29

  • Posts: 16
  • Joined: Wed Apr 14, 2021 11:53 am
  • Real Name: Marco Könemann

Re: Read access violation (this-> X was nullptr) - Decklink

PostFri Jul 09, 2021 3:44 pm

Hi Cameron,

thank you for your advice. I have a further question. I want to check if the single functions of my programm works. For this I create instances in the main function. For my class ControlVideo I do it like this:
Code: Select all
int main() {
   CComPtr<IDeckLink> deckLink;

   auto ctrlVideo = std::make_unique<ControlVideo>(deckLink);
   ctrlVideo->listDisplayMode();
   ctrlVideo->startVideo(bmdModeHD1080p25, bmdFormat8BitYUV, bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 8, bmdVideoInputEnableFormatDetection);
   
   return 0;
}

My constructor looks like this:
Code: Select all
ControlVideo(CComPtr<IDeckLink> &deckLink);
ControlVideo() = delete;

ControlVideo::ControlVideo(CComPtr<IDeckLink>& deckLink)
   : deckLink(deckLink), deckLinkInput(deckLink), referenceCounter(1) {

   if (!deckLinkInput) {
       throw std::runtime_error("No connected input device found.");
   }
}

When I run the code I get the message that the deckLinkInput is NULL. When I debug the code I can also see, that the deckLink member is NULL. I think the cause of the error is the "deckLink parameter" I initialize the constructor with.

In the sample codes I didn't find a solution how to create instances for calling functions. So I'am not sure if the initilization with the deckLink parameter is correct.

Edit: Meanwhile I found that instances are created with the
Code: Select all
Attach()
or the Smart-Pointer-Solution
Code: Select all
make_shared<>
. I prefer make_shared, but I'am not sure how to handle the hand over of the deckLink parameter to the constructor in the main-function

Kind regards
Marco
Offline

Cameron Nichols

Blackmagic Design

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

Re: Read access violation (this-> X was nullptr) - Decklink

PostMon Jul 12, 2021 6:22 am

Hi Marco,

Thanks for sharing your code. I believe the issue is that
Code: Select all
CComPtr<IDeckLink> deckLink;
is not initialized, either with IDeckLinkDiscovery or IDeckLinkIterator interfaces. Attempt to cast a CComQIPtr from a null object will also return a null object.

I think you are using CapturePreview as a reference, please refer to DeckLinkDeviceDiscovery.h/.cpp as reference how to discovery IDeckLink objects. Other samples, such as InputLoopThrough use IDeckLinkIterator, which may be suitable if you don't need to handle attach/removal of USB or Thunderbolt devices.

We use CComPtr/CComQIPtr smart pointer in several Windows samples to simplify maintaining reference counts of COM objects. You will also find com_ptr.h in a number of samples, including InputLoopThrough, that performs the same and is designed to be cross-platform.

Regards
Cameron
Offline

makoe29

  • Posts: 16
  • Joined: Wed Apr 14, 2021 11:53 am
  • Real Name: Marco Könemann

Re: Read access violation (this-> X was nullptr) - Decklink

PostTue Jul 13, 2021 10:23 am

Hi Cameron,

I initialize the DeckLink (thunderbolt) device with the deckLinkIterator in a seperate class. This class I also called in the main-function.

Code: Select all
bool InitializeDecklink::initializeDevice() {

   //initializing COM
   result = CoInitialize(nullptr);

   if (result != S_OK) {
      std::cout << "COM can't be initialized";
      return false;
   }

   //check if driver is installed
   result = CoCreateInstance(CLSID_CDeckLinkIterator, nullptr, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&deckLinkIterator);

   if (result != S_OK) {
      std::cout << "DeckLink Driver is not installed. \n";
      return false;
   }
   else {
      std::cout << "DeckLink Driver is installed. \n";
      return true;
   }
}


Code: Select all
auto init = std::make_unique<InitializeDecklink>();
init->initializeDevice();


I'am not sure if I understand you right, because I found no information in the documentation or on any other place in the net: The DeckLinkDiscovery interface should be used for Thunderbolt and USB devices? And the DeckLinkInterator for any other devices? If this is true, the program can't work because I use the Iterator for initialization. But that would be very sursprising for me.
Offline

makoe29

  • Posts: 16
  • Joined: Wed Apr 14, 2021 11:53 am
  • Real Name: Marco Könemann

Re: Read access violation (this-> X was nullptr) - Decklink

PostWed Jul 14, 2021 9:09 pm

Now I create a DeckLinkDiscovery Instance for my UltraStudio Recoder 3G. And I get the error message that the variable m_deckLinkDiscovery has the value NULL. I think this message is absolutly okay, because m_deckLinkDiscovery is initialized with nullptr.

This is a snippet of my class DeviceNotification which use the Discovery interface. In the main.cpp I create the function initializer(), where I create a new DeviceNotification object.

//DeviceNotification.cpp
Code: Select all
DeviceNotification::DeviceNotification() : m_deckLinkDiscovery(nullptr), referenceCounter(1) {

   HRESULT result = CoCreateInstance(CLSID_CDeckLinkDiscovery, NULL, CLSCTX_ALL, IID_IDeckLinkDiscovery, (void**)&m_deckLinkDiscovery);

   if (result != S_OK) {
      throw std::runtime_error("Creating a DeckLinkDiscovery interface object fails.");
   }
   
}
HRESULT __stdcall DeviceNotification::QueryInterface(REFIID riid, void** outputInterface) {

   if (outputInterface == nullptr) return E_INVALIDARG;

   *outputInterface = nullptr;
   

   if (riid == IID_IUnknown) {
      *outputInterface = this;
      AddRef();
      return S_OK;
   }
   else if (riid == IID_IDeckLinkDeviceNotificationCallback) {
      *outputInterface = static_cast<IDeckLinkDeviceNotificationCallback*>(this);
      AddRef();
      return S_OK;
   }

   return E_NOINTERFACE;
}

/**
* Function that increment the reference of an object interface.
*/
ULONG __stdcall   DeviceNotification::AddRef() {

   return ++referenceCounter;
}

/**
* Function that decrement the reference of an object interface.
*/
ULONG __stdcall   DeviceNotification::Release() {

   ULONG newReference = --referenceCounter;
   if (newReference == 0) {
      delete this;
   }

   return newReference;
}

//main.cpp
bool initializer() {

   CComPtr<IDeckLink>deckLink;

   auto deckLinkDiscovery = std::make_unique<DeviceNotification>();

   if (!deckLinkDiscovery || (!deckLinkDiscovery->enableNotification()))
   {
      std::cout << "Please install the Blackmagic Desktop Video drivers to use the features of this application." << std::endl;
      return true;
   }
}

int main() {

   initializer();
   
   return 0;
}



First I initialized the programm with the DeckLinkIterator (as shown in 2.3.1 in the doc) in a own class. The "init-object" I called in the main-function of the programm, and this process works and also prints the devices to the console.

I rebuild my classes referenced to the filecapture.cpp and capturepreview.cpp samples, but that shows me the messages that either deckLinkInput or deckLinkDiscovery is NULL. I don't understand whats going wrong there.
Offline

Cameron Nichols

Blackmagic Design

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

Re: Read access violation (this-> X was nullptr) - Decklink

PostFri Jul 16, 2021 1:51 am

Hi Marco,

I'am not sure if I understand you right, because I found no information in the documentation or on any other place in the net: The DeckLinkDiscovery interface should be used for Thunderbolt and USB devices? And the DeckLinkInterator for any other devices? If this is true, the program can't work because I use the Iterator for initialization. But that would be very sursprising for me.

This is not quite correct, please let me clarify:
  • The IDeckLinkIterator interface will iterate through all connected PCIe, Thunderbolt and USB devices.
  • The IDeckLinkDiscovery interface provides registering of a class that implements the IDeckLinkDeviceNotificationCallback interface. The callback interface provides notification when a device is connected or removed. This may be more suitable for Thunderbolt or USB desktop video products which may be connected or disconnected while the application is running.
With the issue with DeviceNotification class, please ensure that you have enabled COM on the current thread. In main(), ensure you are calling similar to:
Code: Select all
// Initialize COM on this thread
HRESULT result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(result))
{
   fprintf(stderr, "Initialization of COM failed - result = %08x.\n", result);
   return 1;
}

Regards
Cameron

Return to Software Developers

Who is online

Users browsing this forum: No registered users and 4 guests