Structure of The OFX and the Image Effect API

The Structure Of The Generic OFX API

OFX is actually several things. At its base it is a generic plug-in architecture which can be used to implement a variety of plug-in APIs. The first such API to be implemented on the core architecture is the OFX Image Effect Plug-in API.

It is all specified using the ‘C’ programming language. C and C++ are the languages mainly used to write visual effects applications (the initial target for OFX plug-in APIs) and have a very wide adoption across most operating systems with many available compilers. By making the API C, rather than C++, you remove the whole set of problems around C++ symbol mangling between the host and plug-in.

APIs are defined in OFX by only a set of C header files and associated documentation. There are no binary libraries for a plug-in or host to link against.

Hosts rely on two symbols within a plug-in, all other communication is boot strapped from those two symbols. The plug-in has no symbolic dependencies from the host. This minimal symbolic dependency allows for run-time determination of what features to provide over the API, making implementation much more flexible and less prone to backwards compatibility problems.

Plug-ins, via the two exposed symbols, indicate the API they implement, the version of the API, their name, their version and their main entry point.

A host communicates with a plug-in via sending ‘actions’ to the plug-in’s main entry function. Actions are C strings that indicate the specific operation to be carried out. They are associated with sets of properties, which allows the main entry function to behave as a generic function.

A plug-in communicates with a host by using sets of function pointers given it by the host. These sets of function pointers, known as ‘suites’, are named via a C string and a version number. They are returned on request from the host as pointers within a C struct.

Properties are typed value/name pairs that exist on the various OFX objects and are action argument values to the plug-in’s main entry point. They are how a plug-in and host pass individual values back and forth to each other. The property suite, defined inside ofxProperty.h is used to do this.

OFX APIs

An OFX plug-in API is a named set of actions, properties and suites to perform some specific set of tasks. The first such API that has been defined on the OFX core is the OFX Image Effect API. The set of actions, properties and suites that constitute the API makes up the major part of this document.

Various suites and actions have been defined for the OFX image effect API, however many are actually quite generic and could be reused by other APIs. The property suite definitely has to be used by all other APIs, while the memory allocation suite, the parameter suite and several others would probably be useful for all other APIs. For example the parameter suite could be re-used to specify user visible parameters to the other APIs.

Several types are common to all OFX APIs, and as such are defined in ofxCore.h. Most objects passed back to a plug-in are generally specified by blind data handles, for example:

typedef struct OfxPropertySetStruct *OfxPropertySetHandle

Blind data structure to manipulate sets of properties through.

This allows for strong typing on functions but allows the implementation of the object to be hidden from the plug-in.

  • OfxStatus

    Used to define a set of status codes indicating the success or failure of an action or suite function

  • OfxHost

    A C struct that is used by a plug-in to get access to suites from a host and properties about the host

  • OfxStatus() OfxPluginEntryPoint (const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)

    Entry point for plug-ins.

    • action ASCII c string indicating which action to take

    • instance object to which action should be applied, this will need to be cast to the appropriate blind data type depending on the action

    • inData handle that contains action specific properties

    • outData handle where the plug-in should set various action specific properties

    This is how the host generally communicates with a plug-in. Entry points are used to pass messages to various objects used within OFX. The main use is within the OfxPlugin struct.

    The exact set of actions is determined by the plug-in API that is being implemented, however all plug-ins can perform several actions. For the list of actions consult OFX Actions.

    A typedef for functions used as main entry points for a plug-in (and several other objects),

  • OfxPlugin

    A C struct that a plug-in fills in to describe itself to a host.

Several general assumptions have been made about how hosts and plug-ins communicate, which specific APIs are allowed to break. The main is the distinction between…

  • Descriptors

    Which hosts and plug-ins use to define the general behaviour of an object, e.g. the object used to specify what bit depths an Image Effect Plug-in is willing to accept,

  • Instances

    Which hosts and plug-ins use to control the behaviour of a specific live object.

In most APIs descriptors are typically passed from a host to a plug-in during the kOfxActionDescribe action, whilst all other actions are passed an instance, e.g: the object passed to the kOfxActionCreateInstance action.

The OFX Image Effect API.

The OFX Image Effect Plug-in API is designed for image effect plug-ins for 2D visual effects. This includes such host applications as compositors, editors, rotoscoping tools and colour grading systems.

At heart the image effect API allows a host to send a plug-in a set of images, state the value of a set of parameters and get a resulting image back. However how it does this is somewhat complicated, as the plug-in and host have to negotiate what kind of images are handled, how they can be processed and much more.

Extending OFX

Since items are named using strings, private extensions to OFX can be done simply by #define-ing a new string value in a header that is used by both the host and the plug-in. However, to prevent naming collisions, it is important to prefix your new string with a unique identifier. The recommended format is the reverse domain name format of the developer, for example “uk.co.thefoundry”, followed by the new item name.

This applies to anything which could collide, such as suite names, actions, parameter types, pixel depths, image components, contexts, etc. Function names used inside a suite do not need a prefix.

If a private extension is later suggested as and promoted to a standard part of OFX, the standard name will not use a prefix, and it is often the case that during standardization details of the extension might change.

For details on extending the OFX standard, see [Contributing to OpenFX](https://github.com/AcademySoftwareFoundation/openfx/blob/main/CONTRIBUTING.md), [OpenFX Standard Update Process](https://github.com/AcademySoftwareFoundation/openfx/blob/main/STANDARD_PROCESS.md), and [OpenFX Project Governance](https://github.com/AcademySoftwareFoundation/openfx/blob/main/GOVERNANCE.md).