Using ConvertFrame

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

Andrea Liste

  • Posts: 2
  • Joined: Thu Jul 21, 2016 2:30 pm
  • Location: London

Using ConvertFrame

PostFri Jul 22, 2016 8:44 am

Hi!

I am new here and I am new using this SDK. I developed some part of the code using C#. I was able to make a simple application which detects the Black Magic Card, and reproduce on a picture box a SDI input signal. But I would like to go to the next step. I'm able to get the SDI signal on 8BitYUV pixel format. What I do now is using a "manual" method in order to convert this format to 24bppRgb format. But I would like to take advantage of ConvertFrame method, although I am not able to use it.

My code is something like that... This is a method that I call after the callback after each frame received.

Code: Select all
void Change_Format(IDeckLinkVideoFrame frame)
{
            int width = frame.GetWidth();
            int height = frame.GetHeight();
            int rowBytes = frame.GetRowBytes();
            int noBytes = rowBytes * height;

            // Get output interface for conversion.
            IDeckLinkOutput m_deckLinkOutput = null;

            //    Convert video frame to RGB format.
            IDeckLinkVideoFrame outFrame = null;

            // Create new frame.
            m_deckLinkOutput.CreateVideoFrame(width, height, rowBytes, _BMDPixelFormat.bmdFormat8BitARGB, 0, outFrame);

            IDeckLinkVideoConversion frameConverter = null;
        //    frameConverter = IDeckLinkVideoConversion.CreateVideoConversionInstance();
            frameConverter.ConvertFrame(frame, outFrame); // Segmentation fault here.

        }


But I have errors that I can't solve. I don't understand the way that I can give the format property that I want for the conversion. I would like to obtain the image from 10BitYUV format to 12BitRGB format. Only for showing on a picturebox.

Thank you very much for your help.
Offline

Gary Adams

Blackmagic Design

  • Posts: 1395
  • Joined: Sat Aug 25, 2012 6:14 am

Re: Using ConvertFrame

PostFri Jul 22, 2016 8:41 pm

Hello Andrea. You should be posting this in the Developer's section of the forum where there should be better help. Sorry I'm not a developer of current technology or I would help.

Regards, Gary
Gary Adams
Blackmagic Design
Offline

Nicholas Gill

Blackmagic Design

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

Re: Using ConvertFrame

PostMon Jul 25, 2016 3:25 am

Hi Andrea,

Could you please describe the specific issues you are encountering, and advise if the code shown is the literal code used by your application?

If so, the segmentation fault appears because the frameConverter instance is null.

I suspect the code shown is pseudocode, as the m_deckLinkOutput variable is also null and would fail when attempting to create the destination video frame outFrame.

Cheers,

-nick
Offline

Andrea Liste

  • Posts: 2
  • Joined: Thu Jul 21, 2016 2:30 pm
  • Location: London

Re: Using ConvertFrame

PostMon Jul 25, 2016 10:13 am

This code is written in C#. It isn't pseudocode, is working only for image reception.

I have these global variables:
Code: Select all
        // SDI Input variables. Black Magic SDK
        private IDeckLink m_deckLink;
        private IDeckLink m_deckLink2;
        private IDeckLinkInput m_deckLinkInput;
        public IDeckLinkOutput m_deckLinkOutput;

        IDeckLinkDisplayMode videoDisplayMode;
        _BMDPixelFormat pixelFormat;
        _BMDVideoInputFlags videoInputFlags;
        IDeckLinkVideoConversion videoConversion;

        private bool m_running = false;
        private int m_frameWidth;
        private int m_frameHeight;
        private long m_frameDuration;
        private long m_frameTimescale;
        private uint m_framesPerSecond;


This is my initialisation method:
It's very similar to SignalGenCSharp sample and CapturePreview sample.
Code: Select all
public void SDICardInit()
        {
            m_running = false;

            IDeckLinkIterator deckLinkIterator = new CDeckLinkIterator();

            if (deckLinkIterator == null)
            {
                groupBox1.Text = "DeckLink card/device not detected";
                return;
            }
            // Get the first DeckLink card
            deckLinkIterator.Next(out m_deckLink);
            if (m_deckLink == null)
            {
                groupBox1.Text = "DeckLink card/device not detected";
                return;
            }


            m_deckLink2 = m_deckLink;

            // Get the IDeckLinkOutput interface
            m_deckLinkInput = (IDeckLinkInput)m_deckLink;

            // Set capture callback
            m_deckLinkInput.SetCallback(this);
            m_deckLinkInput.SetScreenPreviewCallback(this);


            IDeckLinkDisplayModeIterator displayModeIterator;

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

            m_deckLinkInput.GetDisplayModeIterator(out displayModeIterator);

            while (true)
            {
                IDeckLinkDisplayMode deckLinkDisplayMode;

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

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

            comboBoxVideoFormat.EndUpdate();

            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;


            //Output
            m_deckLinkOutput = (IDeckLinkOutput)m_deckLink2;
}


This is my method when I push a Start_Capture_button:
Code: Select all
        public void StartRunning()
        {
            //- Extract the IDeckLinkDisplayMode from the display mode popup menu

            videoInputFlags = _BMDVideoInputFlags.bmdVideoInputFlagDefault;

            pixelFormat = _BMDPixelFormat.bmdFormat8BitYUV;

            videoDisplayMode = ((DisplayModeEntry)comboBoxVideoFormat.SelectedItem).displayMode;
            m_frameWidth = videoDisplayMode.GetWidth();
            m_frameHeight = videoDisplayMode.GetHeight();
            videoDisplayMode.GetFrameRate(out m_frameDuration, out m_frameTimescale);

            // Calculate the number of frames per second, rounded up to the nearest integer.
            m_framesPerSecond = (uint)((m_frameTimescale + (m_frameDuration - 1)) / m_frameDuration);

            // Set the video input mode
            m_deckLinkInput.EnableVideoInput(videoDisplayMode.GetDisplayMode(), pixelFormat, videoInputFlags);

            // Start the capture
            m_deckLinkInput.StartStreams();

            //Output
            m_deckLinkOutput.EnableVideoOutput(videoDisplayMode.GetDisplayMode(), _BMDVideoOutputFlags.bmdVideoOutputFlagDefault);

            m_running = true;

           
        }


And these are the methods for callback and frame conversion:
Code: Select all
        #region callbacks
        void IDeckLinkInputCallback.VideoInputFrameArrived(IDeckLinkVideoInputFrame videoFrame, IDeckLinkAudioInputPacket audioPacket)
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(videoFrame);
        }

        void IDeckLinkScreenPreviewCallback.DrawFrame(IDeckLinkVideoFrame theFrame)
        {
            Change_Format(theFrame);

            System.Runtime.InteropServices.Marshal.ReleaseComObject(theFrame);
        }
        #endregion

        void Change_Format(IDeckLinkVideoFrame frame)
        {

            int width = frame.GetWidth();
            int height = frame.GetHeight();
            int rowBytes = frame.GetRowBytes();
            int noBytes = rowBytes * height;

            // Get output interface for conversion.

            //    Convert video frame to RGB format.
            IDeckLinkMutableVideoFrame outFrame ;

            // Create new frame.
            m_deckLinkOutput.CreateVideoFrame(width, height, rowBytes, _BMDPixelFormat.bmdFormat8BitARGB, 0, out outFrame);

            IDeckLinkVideoConversion frameConverter;
            frameConverter.ConvertFrame(frame, outFrame); // Segmentation fault here.

        }



Now I have an exception when I execute m_deckLinkOutput.EnableVideoOutput(videoDisplayMode.GetDisplayMode(), _BMDVideoOutputFlags.bmdVideoOutputFlagDefault);

after execute m_deckLinkInput.EnableVideoInput(videoDisplayMode.GetDisplayMode(), pixelFormat, videoInputFlags);

At the beginning, m_deckLinkInput and m_deckLinkOuput used the same m_deckLink "global" interface. I thought that this fact was the problem and I tried to copy the m_deckLink interface to another one new and I tried to enableVideoOutput using a m_deckLinkOutput object initialised using m_deckLink2 but I obtain the same problem. The exception says this:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

I don't know how I can manage an input and an output at the same time.

After that, if I try to don't execute the EnableVideoOutput method, the next exception appears on CreateVideoFrame method and says this:
Unable to cast COM object of type 'System.__ComObject' to interface type 'DeckLinkAPI.IDeckLinkOutput'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

So I don't how I can continue. I only want to get an input frame and convert it to another pixel format. I am not really interested in showing a video output.

Thank you in advance for your help! :)
Offline

Nicholas Gill

Blackmagic Design

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

Re: Using ConvertFrame

PostTue Aug 09, 2016 1:49 am

Hi Andrea,

Thanks for the clarifications.

Based on the behaviour described, I am going to guess that you have a pre-4k DeckLink / Intensity / UltraStudio device. These devices are half-duplex and are capable of playback and capture, but not both simultaneously - The 4K architecture devices are full-duplex and are capable of simultaneous capture and playback.

However, enabling video output is not a requirement for your use case - video output does not need to be enabled in order to create a video frame.

Regarding casting IDeckLink to IDeckLinkOutput, please check to ensure that the thread used to interact with the DeckLink API is created as a multithreaded apartment, as this is a common issue experienced in this case.

It would also not be possible to obtain a reference to IDeckLinkOutput if the device is capture-only, e.g. the UltraStudio Mini Recorder.

Assuming that the device has an IDeckLinkOutput interface, your application will then be able to use the IDeckLinkOutput instance to create a video frame (via CreateFrame).

I think the primary issue is that the code shown never creates an instance of IDeckLinkVideoConversion:
Code: Select all
            IDeckLinkVideoConversion frameConverter;
            frameConverter.ConvertFrame(frame, outFrame); // Segmentation fault here.

The application will first have to create an instance of IDeckLinkVideoConversion, e.g.
Code: Select all
frameConverter = new CDeckLinkVideoConversion();

To use IDeckLinkVideoConversion with capture-only devices, instead of creating the destination video frame via IDeckLinkOutput, the application can create a class which implements the IDeckLinkVideoFrame interface and use an instance of this class directly as the destination video frame.

Cheers,

-nick
Offline

mmddgghh

  • Posts: 2
  • Joined: Thu Nov 19, 2020 10:16 am
  • Real Name: Eladio Martinez

Re: Using ConvertFrame

PostSat Nov 21, 2020 7:31 pm

Hi,

The part that you have done is exactly what I need now. Could you pass me the project where you show the input frames into a picturebox? I am a newbie and it's complicated for me.

Thank you very much.

Return to Software Developers

Who is online

Users browsing this forum: BartReynaard, Bing [Bot], Larry Masters and 29 guests