Blackmagic and DirectX display

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

Stefan Pintilie

  • Posts: 1
  • Joined: Fri Oct 27, 2017 10:26 am

Blackmagic and DirectX display

PostFri Oct 27, 2017 10:54 am

Hi guys,

I am gonna share with you some tips on how to display the images captured by Blackmagic in a DirectX environment.

First thing is trying to use IDeckLinkDX9ScreenPreviewHelper interface which does everything for you. The problem with this class is that you don't have a texture in your hand so you can place it whatever you want. Anyway if you want to use this class, you will notice that it will mess up the whole scene. The trick is to have it sourrounded by Sprite::Being Sprite::End. Example

Code: Select all
m_device->SetTransform(D3DTS_WORLD, &matrix);

In my case I wanted to have a full control of the texture, and have the smallest latency possible, which I guess all developers want.

The basic idea is to use the format D3DFMT_UYVY which is supported by DirectX, at least in my case, where I have an NVIDIA QUADO 600. That means that I only process the format bmdFormat8BitYUV.

If you wanna tell to the driver to use this, you can specify it in a paramter IDeckLinkInput::EnableVideoInput function. Example:

Code: Select all
HRESULT MFDeckLinkImpl::VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode *newMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags)
      Error* error = NULL;
         //if (detectedSignalFlags & bmdDetectedVideoInputRGB444)
         //   pixelFormat = bmdFormat10BitRGB;

         HRC(m_deckLinkInput->EnableVideoInput(newMode->GetDisplayMode(), bmdFormat8BitYUV, bmdVideoInputEnableFormatDetection));

      if (error)
         return error->Hr;

      return S_OK;

This way you will force all the frames recieved to be in 8 bit YUV. For SDI you will notice that it doesn't work, but changing one settings will do the work. Go to "Blackmagic Desktop Video Setup" conversion, and choose SD->HD and Anamorphic transformation. This way the frames will be well formated with 8 bit YUV data.

Next we need to have the 8-bit YUV image transformed into a texture. The way I did it is to create an offline surface:

Code: Select all
m_device->CreateOffscreenPlainSurface(_width, _height, D3DFMT_UYVY, D3DPOOL_DEFAULT, &m_surface, NULL);

and whenever you recieved a frame in DrawFrame callback method just fill in the surface with data from "theFrame"

Code: Select all
m_surface->LockRect(&rect, 0, D3DLOCK_DISCARD);
memcpy(rect.pBits, _buffer, _bufferSize);

_buffer is coming from theFrame->GetBytes(); _bufferSize is width * height * 2 in case of 8-bit YUV;

You need to stretch the surface into a texture with RGB format, so you create the texture:

Code: Select all
m_device->CreateTexture(_width, _height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_texture, NULL);

then copy the surface:

Code: Select all
IDirect3DSurface9* surface;

m_texture->GetSurfaceLevel(0, &surface);
HRESULT hr = m_device->StretchRect(m_surface, NULL, surface,  NULL, D3DTEXF_NONE);

Now you have the texture and you can do everything that you want with it :).

You should be carefull how you design the app, usually the DrawFrame runs on a different thread than your DirectX scene, and if you use the transformation above in the DrawFrame thread, LockRect and StrechRect will cause delay. What I did instead, I have made a copy of the bytes recieved from "theFrame", that is on the DrawFrame thread, then I use the byte array and strech the image and texture before drawing it on the scene thread.

Hope this helps you to get best of performance when using DirectX and Blackmagic card.

Return to Software Developers

Who is online

Users browsing this forum: No registered users and 6 guests