Question

The COM-based Blackmagic DeckLink API is available for both Windows and OS X. I wish to address it in OS X but using FireMonkey (FMX) in C++. The problem is that their sample code* is written for Cocoa and I have no idea how to rewrite it for FireMonkey. Does anyone have any experience with this, is it even possible.

Or, is there a generic way in which libraries with a COM interface can be addressed in FireMonkey/OS X?

Here's part of the code for Cocoa, per request.

void    InitDeckLinkAPI (void)
{
    CFURLRef        bundleURL;

    bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true);
    if (bundleURL != NULL)
    {
        gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL);
        if (gDeckLinkAPIBundleRef != NULL)
        {
            gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0002"));
            gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001"));
            gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001"));
            gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001"));
            gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001"));
        }
        CFRelease(bundleURL);
    }
}

bool        IsDeckLinkAPIPresent (void)
{
    // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller
    if (gDeckLinkAPIBundleRef != NULL)
        return true;

    return false;
}

IDeckLinkIterator*      CreateDeckLinkIteratorInstance (void)
{
    pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);

    if (gCreateIteratorFunc == NULL)
        return NULL;

    return gCreateIteratorFunc();
}

*Too long to include here but you can download it here.

Was it helpful?

Solution

On platforms without native COM support (such as OS X) a C entry point should be provided to access an Interface and in DeckLink API there is such factory methods :

IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance();

Thus you can simply use DeckLink API in C++Builder. But there is a problem, C++Builder has defined some COM types such as IUnknown in sysmac.h (is included by System.hpp) which conflicts with same types have been defined in CFPluginCOM.h, If your project includes System.hpp such as all firemonkey projects the compiler displays an error:

[bccosx Error] sysmac.h(287): E2238 Multiple declaration for 'IUnknown'

There is a sample named DeckControl in samples directory of DeckLink API which is a console program and you can compile it by C++Builder:

  1. Create a console project and specify main.cpp as project source.
  2. Select "None" as Target Framework
  3. Add "OSX" Platform

The project is compiled successfuly.

And what about Fmx project (uses System.hpp) ?
Create a wrapper unit (For example bcb_deck) put needed APIs in it. Note that do not include "DeckLinkAPI.h" in unit header, this causes same problems described above, but put it in cpp (bcb_deck.cpp), for example:

bcb_deck.cpp:

void* createDeckLinkIteratorInstance() // use camel case to prevent conflict
{
    return (void*) CreateDeckLinkIteratorInstance();
}

bool deckLinkIteratorNext(void *hDeckLinkIterator, void *hDeckLink)
{
    IDeckLinkIterator *deckLinkIterator = (IDeckLinkIterator*) hDeckLinkIterator;
    IDeckLink *deckLink = (IDeckLink*) hDeckLink;

    return deckLinkIterator->Next(&deckLink) == S_OK;
}

Usage:

#include "bcb_deck.h"
void *hDeckLinkIterator, *hDeckLink;
hDeckLinkIterator = createDeckLinkIteratorInstance();
if (hDeckLinkIterator)
{
    // Enumerate all cards in this system
    while (deckLinkIteratorNext(hDeckLinkIterator, hDeckLink))
    {
        // ...
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top