LogoLogo
🛠️ Tools🗂️ SDK📄 White Paper
  • Getting Started
    • 🟣What is NDI?
    • 🆕Release Notes
    • 📄White Paper
      • Discovery & Registration
        • mDNS
        • Discovery Service
        • Manual Connection
        • NDI Groups
      • NDI Protocols
        • Reliable UDP - NDI 5
        • Multipath TCP - NDI 4
        • UDP with Forward Error Correction – NDI 3
        • Single TCP – NDI 1
      • NDI Related Network Ports
      • Getting video across the network
      • Network Layout
      • Bandwidth
        • NDI High Bandwidth based on SpeedHQ2 (8bit 4:2:2)
        • NDI High Bandwidth based on SpeedHQ7 (8bit 4:2:2:4)
        • NDI HX2 h.264 (8bit 4:2:0)
        • NDI HX2 h.265 (8bit 4:2:0)
        • NDI HX3 h.264 (8bit 4:2:0)
        • NDI HX3 h.265 (8bit 4:2:0)
        • NDI Proxy and bandwidth optimization
      • Network Interface Settings
      • NIC Selection
      • Encoding and Decoding
      • Multicast
      • NDI Administrative Settings
      • Synchronization
      • NDI in the Cloud
    • Glossary
      • NDI Terminology
      • Industry Terminology
  • Using NDI
    • Introduction
    • NDI for Video
      • Digital Video Basics
      • NDI Video Codecs and Format Matrix
      • NDI Encoding Support Matrix
        • Practical NDI Receivers Format Support
        • Practical NDI Transmitters Support
        • Summary Table
      • Interoperability Scenarios
    • NDI for Audio
      • Digital Audio Fundamentals
      • Audio Over IP
      • Technical Facts About NDI for Audio
      • Use Cases
      • Products Using NDI for Audio
    • ⚒️NDI Tools
      • Release Notes
      • Installing NDI Tools
        • Software License Agreement
        • Privacy Policy
      • NDI Tools Launcher
      • NDI Tools for Windows
        • Access Manager
        • Bridge
          • NDI Bridge automation
          • Configuring Port Forwarding
          • Bridge Tool Logging
        • Remote
        • Router
        • Screen Capture
        • Screen Capture HX
        • Studio Monitor
        • Test Patterns
        • Webcam Input
      • NDI Tools for Mac
        • Access Manager
        • Scan Converter
        • Router
        • Test Patterns
        • Video Monitor
        • Virtual Input
      • Plugins
        • NDI for After Effects
        • NDI for Premiere Pro
        • NDI Output for Final Cut Pro
        • NDI for VLC
        • Audio Direct
        • OBS
    • Utilities
      • Analysis
    • Using NDI with Software
      • Getting Started with NDI in OBS for Windows or Mac
      • Using OBS Studio as a Commentary System
      • Using NDI Tools as a virtual camera in Mac
      • Using NDI and Dante on the same Network
      • Use OBS video + audio on Zoom with macOS
    • Using NDI with Hardware
      • NDI HX upgrades for cameras
      • How to Activate Panasonic Cameras for NDI HX1 — Step-by-Step
      • Recommended Network Switch Settings for NDI
  • Developing with NDI
    • Introduction
    • 📂SDK
      • Release Notes
      • Licensing
      • Software Distribution
        • Header Files
        • Binary Files
        • Redistributables
        • Content Files
        • Libraries
        • NDI-SEND
        • NDI-FIND
        • NDI-RECEIVE
        • Utilities
        • Command Line Tools
      • CPU Requirements
      • Dynamic Loading of NDI Libraries
      • Performance and Implementation
      • Startup and Shutdown
      • Example Code
      • Port Numbers
      • 🔧Configuration Files
      • Platform Considerations
      • NDI-SEND
      • NDI-FIND
      • NDI-RECV
      • NDI Routing
      • HDR
      • Command Line Tools
      • Frame Types
        • Video Frames
        • Audio Frames
        • Metadata Frames
      • Windows DirectShow Filter
      • 3rd Party Rights
      • Support
    • Advanced SDK
      • Release Notes
      • Licensing
      • Overview
      • Configuration Files
      • NDI SDK Review
        • Sending
          • Asynchronous Sending Completions
          • NDI Sending On High Latency Connections
        • Receiving
          • Custom Allocators
            • Video Allocators
            • Audio Allocators
          • Dynamic Bandwidth Adjustment
        • Finding
        • Video Formats
          • Receiver Codec Support Level
          • Frame Synchronization
      • Genlock
      • AV Sync
        • Guidelines
        • Creating and Destroying Devices
        • Recovering Audio
      • Using H.264, H.265, and AAC Codecs
        • Sending Audio Frames
        • Sending Video Frames
        • H.264 Support
        • H.265 Support
        • AAC Support
        • OPUS Support
        • Latency of Compressed Streams
        • Stream Validation
      • External Tally Support
      • KVM Support
      • NDI Advanced SDK FPGA Example Designs
        • Prebuilt uSD Images
        • NDI FPGA Reference Design
          • FPGA Projects
            • Changelog
          • C++ Application Code
            • Changelog
          • linux_kernel
            • Changelog
          • uSD Image Builder
            • Changelog
        • Changelog
    • Utilities
      • Unreal Engine SDK
        • Release Notes
        • Licensing
        • NDI Plugin Installation
        • Simple Setup of Broadcast and Receivers
        • NDI Broadcast Actor
        • NDI Receiver Actor
        • NDI Media Assets
        • Getting Started with Example Blueprint Projects
        • Advanced
      • Free Audio
      • Bridge Service
        • Installation
          • Silent Installation
        • Configuration
          • Web UI
          • Configuration File
          • Manual API Key Management
        • Webhooks
        • WebSockets
        • API
    • NDI Certified
      • Certification Guidelines
        • Interoperability Requirements
        • Technical Requirements
      • Certification Process
        • Pre-certification Checklist
        • Device Testing Methods
          • Camera
          • HDMI Encoder
          • SDI Encoder
          • Decoder
          • NDI Controller
          • NDI Monitor
          • Multicast Testing
        • Detailed process
    • Metadata
      • Metadata Sources
      • Metadata for XML
      • XML Validation
      • Metadata Elements
      • Proposed New Metadata Messages
      • PTZ and Control Messages
      • Undocumented Mysteries
  • Developer Guides
    • Decoding with NDI
    • NDI Bridge Deployment
  • FAQ
    • Index
    • NDI Tools
      • What is the NDI Analysis Tool and where do I get it from?
      • Why does my NDI connection stay active once the source is offline?
      • Why are my changes to the NDI JSON configuration file not being saved?
      • Why is the license for my Panasonic camera not active?
      • How does registration for NDI Tools work?
      • The time code on my file is incorrect, how do I change it?
      • How can I make NDI Tools launch automatically?
      • What is the NDI ECCN?
      • How do I use NDI output with Microsoft Teams
      • Where is Screen Capture (HX) for Mac?
    • NDI Certified
      • What is the NDI Certification Program?
      • Why did you start this certification program?​
      • What happens to my device after it's certified?
      • Is certification mandatory to be a partner of NDI?​
      • I am an OEM manufacturer, can my products be certified?​
      • How long does the certification process take?
      • How do I become certified?​
      • What happens if my product doesn’t meet the requirements for Certification?​
      • Are there any fees to become NDI Certified?
    • Common Issues
      • I'm having trouble getting multicast set up.
      • I'm having trouble with my NDI HX License
      • Why can't I find my Android 14-based NDI devices on my network?
      • Why won’t NDI Tools install on my Windows PC?
      • How do I enable NDI in “New” Microsoft Teams (Windows only)?
      • Why can’t HX Capture display the full resolution of my iPad or iPhone?
      • The NDI HX Camera app won't launch on older phones and iOS
      • Why won't MacOS Sonoma (14.1) recognize NDI Tools as a virtual camera?
      • I'm having issues with Virtual Input for macOS
      • I'm having issues with Final Cut Pro
      • NDI Camera App Issue
    • SDK
      • Where can I find the source code for the FPGA board?
      • What system resources are required to support a design including the NDI FPGA Codecs?
      • Why can’t my h264/265 video be received by an NDI receiver when using the embedded SDK?
      • Can I use the Unreal SDK on Mac?
      • What are the Differences Between the NDI SDK and the NDI Advanced SDK
    • ✨NDI 6
      • Do I need to upgrade to NDI 6 if I'm not using the new features?
      • Is there a fee to upgrade to NDI 6
      • Why doesn't my existing Vendor ID work with NDI 6?
      • How can I get a previous version of NDI Tools or the SDK?
    • NDI HX License Upgrades
      • What is happening with NDI HX Upgrades?
      • Will my existing HX-upgraded camera be affected?
      • I bought a camera before June 30, 2025, but didn't buy an HX license. Can I still get one?
      • I bought a license and a camera but didn't redeem it until after. Can I still get an HX license?
      • If my HX upgrade fails can I transfer the license?
      • Can I sell my upgraded HX camera and keep the license?
      • Will my NDI version work with my current HX license?
      • What does the HX upgrade sunset program mean for camera manufacturers?
      • What will NDI Support do for licenses after the sunset date?
      • I factory reset my camera and forgot the license. Can you help me get it back?
Powered by GitBook

2024 @ NDI Vizrt AB.

  1. Developing with NDI
  2. Advanced SDK
  3. NDI SDK Review
  4. Receiving

Custom Allocators

The Advanced SDK allows you to provide custom memory allocators for receiving audio and video frames either in compressed or uncompressed formats. This allows you to ask NDI to decompress or receive data into a buffer allocated by you own application.

Some possible use cases for this are:

  • Decompress into your own memory buffers for use in inter-process memory sharing; when you might want one or more NDI inputs to exist in their own process.

  • You wish to fill in buffers that might be more optimally accessible by dedicated hardware, including GPUs.

  • Minimizing memory copies does to the internal structure of your own application.

  • Allocating a buffer with memory alignment that matches your need.

  • This allows you to enter your own video or audio stride, allowing you to have NDI provide buffers that closely match the needs of your own application.

It is often assumed that decompressing into a GPU accessible buffer will yield improved performance, however often these buffers are allocated using write combining memory that is not commonly CPU cacheable. Often decoding into these buffers is slower than decoding them into a regular memory buffer and performing a memcpy that is specifically optimized for copying into write combining memory,

If you are going to simply use your own pooled memory allocator, it is unlikely that it will give you significant performance enhancements over what the NDI SDK already has implemented internally. The NDI SDK uses a lock-free memory pooling mechanism to offer very quick frame allocation.

It is important to know that the allocations will occur on a thread that is called by the NDI SDK, you should ensure that you return quickly from this allocation or free call if you wish to avoid video or audio stalling. Your code should be re-entrant since it might be called from multiple threads at once. The allocators can be changed at any time, including at run-time. When you provide an allocation and free callback, the free callback is called exactly once for every allocation call, even if the allocators are changed out. There are some error conditions under which it is possible that a frame will be allocated, but not returned by the SDK since there might be a network or data integrity problem. In this case the frame is simply freed using your customer de-allocator.

Video Allocators

To replace a memory allocator, one should implement two functions with one to allocate a new video frame and set the stride, and one to free that frame when the SDK no longer needs it. If you are implementing a memory allocator for use with uncompressed video frames, you should check the requested frame format within the allocator and fill in the p_buffer and line_stride_in_bytes members with the NDIlib_video_frame_v2_t structure that is passed into the function. When the SDK is free with the frame the corresponding de-allocation function will be called and you should free the p_buffer member using whatever means you might need.

The p_opaque pointer that may be passed into the function setup is your own custom data that will then be passed each time that an allocator or de-allocator is called.

An example uncompressed video frame allocator might look as follows. Note that you need not always support allocating under all possible frame formats since your allocator will only be called for the formats specified when receiving video with the SDK. This example is provided to illustrate how all formats might be used.

bool video_custom_allocator(void* p_opaque, NDIlib_video_frame_v2_t* p_video_data)
{
    switch (p_video_data->FourCC) {
        case NDIlib_FourCC_video_type_UYVY:
            p_video_data->line_stride_in_bytes = p_video_data->xres * 2;
            p_video_data->p_data = (uint8_t*)malloc(
                p_video_data->line_stride_in_bytes * p_video_data->yres
            );
            break;

        case NDIlib_FourCC_video_type_UYVA:
            p_video_data->line_stride_in_bytes = p_video_data->xres * 2;
            p_video_data->p_data = (uint8_t*)malloc(
                /* UYVY  */p_video_data->line_stride_in_bytes * p_video_data->yres +
                /* Alpha */p_video_data->line_stride_in_bytes / 2 * p_video_data->yres
            );
            break;

        case NDIlib_FourCC_video_type_P216:
            p_video_data->line_stride_in_bytes = p_video_data->xres * sizeof(uint16_t);
            p_video_data->p_data = (uint8_t*)malloc(
                /* Y    */p_video_data->line_stride_in_bytes * p_video_data->yres +
                /* CbCr */p_video_data->line_stride_in_bytes * p_video_data->yres
            );
            break;

        case NDIlib_FourCC_video_type_PA16:
            p_video_data->line_stride_in_bytes = p_video_data->xres * sizeof(uint16_t);
            p_video_data->p_data = (uint8_t*)malloc(
                /* Y     */p_video_data->line_stride_in_bytes * p_video_data->yres +
                /* CbCr  */p_video_data->line_stride_in_bytes * p_video_data->yres +
                /* Alpha */p_video_data->line_stride_in_bytes * p_video_data->yres
            );
            break;

        case NDIlib_FourCC_video_type_BGRA:
        case NDIlib_FourCC_video_type_BGRX:
        case NDIlib_FourCC_video_type_RGBA:
        case NDIlib_FourCC_video_type_RGBX:
            p_video_data->line_stride_in_bytes = p_video_data->xres * 4;
            p_video_data->p_data = (uint8_t*)malloc(
                p_video_data->>line_stride_in_bytes*p_video_data->yres
            );
            break;

        default:
            // Error, not a supported FourCC
            p_video_data->line_stride_in_bytes = 0;
            p_video_data->p_data = NULL;
            return false;
    }

    return true; // Success.
}

bool video_custom_deallocator(void* p_opaque, const NDIlib_video_frame_v2_t* p_video_data)
{
    free(p_video_data->p_data);
    return true;
}

One may then simply assign the allocator for any receiver with:

NDIlib_recv_set_video_allocator(
    pNDI_recv, NULL,
    video_custom_allocator, video_custom_deallocator
);

If you wish to reset the video memory allocators, at any time you may simply pass in null pointers:

NDIlib_recv_set_video_allocator(pNDI_recv, NULL, NULL, NULL);

As a final note, although it is not needed that often, it is possible to use your own memory allocators to receive compressed video format if the NDI receiver is being specified to receive compressed data.

Audio Allocators

Audio allocations are implemented almost identically to video allocations, simply with different FourCC codes. An example memory allocator for audio might look as follows:

bool audio_custom_allocator(void* p_opaque, NDIlib_audio_frame_v3_t* p_audio_data)
{
    // Allocate uncompressed audio
    switch (p_audio_data->FourCC) {
        case NDIlib_FourCC_audio_type_FLTP:
            p_audio_data->channel_stride_in_bytes = sizeof(float) * p_audio_data->no_samples;
            p_audio_data->p_data = (uint8_t*)malloc(
                p_audio_data->channel_stride_in_bytes * p_audio_data->no_channels
            );
            break;

        default:
            p_audio_data->channel_stride_in_bytes = 0;
            p_audio_data->p_data = nullptr;
            return false;
    }

    return true;
}

bool audio_custom_deallocator(void* p_opaque, const NDIlib_audio_frame_v3_t* p_audio_data)
{
    free(p_audio_data->p_data);
    return true;
}

One may then simply assign the allocator for any receiver with:

NDIlib_recv_set_audio_allocator(
    pNDI_recv, NULL,
    audio_custom_allocator, audio_custom_deallocator
);

If you wish to reset the video memory allocators, at any time you may simply pass in null pointers:

NDIlib_recv_set_audio_allocator(pNDI_recv, NULL, NULL, NULL);

Last updated 5 months ago

Was this helpful?