Skip to content

ascmitc/fdl

Repository files navigation

ASC Framing Decision List (FDL)

Getting Started:


INTRODUCTION:

ASC FDL’s are a set of instructions for how to view content in any application. The ASC FDL provides a mechanism to document framing decisions through all phases of a production's life cycle, from pre-visualization through post-production. The FDL can exist in the form of a sidecar JSON file, or embedded into another data structure like camera original files. Any time an application is rendering media to another department or person, an accompanying set of ASC FDL data should be created and delivered. Therefore any downstream applications are able to apply the intended frame.


1-SHEET:

This is the first document you should read. This is a very brief introduction to what the FDL is and the problem it has set out to solve.


USER GUIDE:

This is a document intended for end users to better understand how the FDL could be used within their workflows. This will also be a great reference for implementers to better understand the intention behind FDL usability.


GETTING ACCESS TO SAMPLE MEDIA:

The latest ScenariosForImplementors, including reference images and associated source/result FDL data, can be found on the releases page.

The FDL Viewer is a desktop application that allows you to view framing charts, configure settings, and instantly see the expected outcome both visually and as the resulting FDL JSON. Precompiled binaries for macOS, Windows, and Linux are available on the releases page.


SPECIFICATION:

This is the technical specification for implementers.


IMPLIMENTATION GUIDE:

For anyone looking to implement the ASCFDL into their tooling, a guide has been created to offer helpful information.


DOCUMENTATION:

Full documentation is available at ascmitc.github.io/fdl. There you will find tutorials, system architecture overviews, API references for Python, TypeScript, and C++, template application algorithms, and guides for implementers.


CI AVAILABLE FOR MACOS, WINDOWS & LINUX:

Click on the CI/CD badge below to see per-platform results CI/CD Nightly Build GitHub Actions

Repository Overview

This repository contains the ASC FDL reference implementation: a native C library with language bindings and Python application packages for working with Framing Decision List files.

Directory Structure

.
├── native/                          # Native (C/C++) core and bindings
│   ├── core/                        # libfdl_core — shared C library
│   │   ├── include/fdl/             #   Public C ABI header (fdl_core.h)
│   │   ├── src/                     #   Implementation (parsing, validation, geometry, pipeline, templates)
│   │   └── tests/                   #   Catch2 C++ unit tests with JSON test vectors
│   ├── bindings/
│   │   ├── python/                  # asc-fdl — Python ctypes bindings & facade
│   │   │   ├── fdl/                 #   FDL, Canvas, Context, FramingDecision, etc.
│   │   │   ├── fdl_ffi/             #   Low-level ctypes FFI loader and function declarations
│   │   │   └── tests/              #   Python unit tests (351 tests)
│   │   ├── cpp/fdl/                 # fdl.hpp — C++ RAII header-only wrapper
│   │   └── node/                    # Node.js bindings (placeholder)
│   ├── api/                         # OpenAPI spec (fdl_api.yaml)
│   └── tools/                       # Code generation and test vector extraction scripts
│
├── packages/                        # Python application packages
│   ├── fdl_imaging/                 # asc-fdl-imaging — FDL-based image processing (OpenImageIO)
│   │   ├── src/fdl_imaging/         #   Image extraction, resizing, comparison utilities
│   │   └── tests/                   #   Image processing tests (6 tests)
│   ├── fdl_frameline_generator/     # asc-fdl-frameline-generator — frameline overlay generation
│   │   ├── src/fdl_frameline_generator/  # EXR/PNG/TIFF/SVG frameline rendering
│   │   └── tests/                   #   Renderer + regression tests (157 tests)
│   └── fdl_viewer/                  # asc-fdl-viewer — PySide6 desktop application
│       ├── src/fdl_viewer/          #   MVC architecture (models, views, controllers)
│       └── tests/                   #   UI, controller, model, and visual QC tests (130+ tests)
│
├── schema/                          # JSON Schema definitions (v0.1, v1.0, v2.0, v2.0.1)
├── resources/FDL/                   # Test resources
│   ├── Original_Source_Files/       #   Source FDL + TIFF image pairs
│   ├── Scenarios_For_Implementers/  #   30+ numbered scenarios with expected results
│   └── EdgeCases/                   #   Generated edge-case FDL files
├── docs/                            # Documentation (template logic, implementer guide)
├── Specification/                   # ASC FDL specification documents
└── pyproject.toml                   # uv workspace root

Key Components

libfdl_core (native/core/) — The core engine, written in C++ and exposed via a C ABI. Handles FDL parsing, serialization (JSON), schema validation (Draft 2020-12 via jsoncons), geometry calculations, canvas resolution pipeline, and template application. Built with CMake.

asc-fdl (native/bindings/python/) — Python package providing a high-level facade over libfdl_core via ctypes. Classes include FDL, Canvas, Context, FramingIntent, FramingDecision, and CanvasTemplate. Also provides rounding strategies, validation, and a fdl-validate CLI tool.

asc-fdl-imaging (packages/fdl_imaging/) — Image processing utilities using OpenImageIO. Extracts framing regions from source images based on FDL geometry and produces output images matching target canvas dimensions.

asc-fdl-frameline-generator (packages/fdl_frameline_generator/) — Generates frameline overlay images from FDL files. Supports EXR, PNG, TIFF (via OIIO), and SVG vector output. Includes a fdl-frameline CLI tool.

asc-fdl-viewer (packages/fdl_viewer/) — A PySide6 desktop application for interactively viewing, transforming, and exporting FDL files. Supports source/output scene visualization with HUD overlays, template-based transforms, and image export. Built with an MVC architecture.


Developer Guide

Prerequisites

  • Python 3.10+
  • uv (Python package manager) — install instructions
  • CMake 3.20+
  • C++ compiler with C++17 support (Clang, GCC, or MSVC)
  • OpenImageIO 2.4+ (required by asc-fdl-imaging and asc-fdl-frameline-generator)

Clone the Repository

git clone https://github.com/ascmitc/fdl.git
cd fdl

Code Generation

The Python bindings (FFI layer and facade classes) and the C++ RAII header are auto-generated from the IDL schema. Codegen must run before building or testing.

# Install codegen dependencies
uv pip install pyyaml jinja2 --system

# Run all codegen targets (python-ffi, python-facade, cpp-raii)
python scripts/run_codegen.py

This generates files into native/bindings/python/fdl_ffi/, native/bindings/python/fdl/, and native/bindings/cpp/fdl/fdl.hpp.

Build the Native Library

The Python packages depend on libfdl_core, which must be compiled before running tests or using the Python bindings.

# Build and run C++ tests (recommended)
python scripts/build_native.py --run-tests

# Build without tests
python scripts/build_native.py --no-tests

Or manually with CMake:

cmake -S native/core -B native/core/build -DCMAKE_BUILD_TYPE=Release
cmake --build native/core/build --config Release -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)

This produces native/core/build/libfdl_core.dylib (macOS), libfdl_core.so (Linux), or fdl_core.dll (Windows). The Python FFI loader finds it automatically at this path.

Set Up the Python Environment

# Create the virtual environment and install all workspace packages + dev dependencies
uv sync --extra dev

This installs the full workspace (asc-fdl, asc-fdl-imaging, asc-fdl-frameline-generator, asc-fdl-viewer) in editable mode along with test dependencies (pytest, pytest-xdist, pytest-qt, pytest-cov, mktestdocs).

Run the Tests

C++ core tests (113 tests):

python scripts/build_native.py --run-tests
# or: ctest --test-dir native/core/build --output-on-failure

FDL core Python bindings (351 tests):

uv run pytest native/bindings/python/tests/ -v -n auto -p no:pytest-qt

FDL Imaging (6 tests):

uv run pytest packages/fdl_imaging/tests/ -v -n auto -p no:pytest-qt

FDL Frameline Generator (157 tests):

uv run pytest packages/fdl_frameline_generator/tests/ -v -p no:pytest-qt

FDL Viewer:

# All viewer tests (can take a long time due to UI scenario matrix)
uv run pytest packages/fdl_viewer/tests/ -v

# Exclude slow visual QC tests
uv run pytest packages/fdl_viewer/tests/ -v \
    --ignore=packages/fdl_viewer/tests/test_visual_qc_matrix.py \
    --ignore=packages/fdl_viewer/tests/test_visual_qc_edge_cases.py

Run everything (fast subset):

uv run pytest native/bindings/python/tests/ packages/fdl_imaging/tests/ packages/fdl_frameline_generator/tests/ -v -n auto -p no:pytest-qt

Linting

The project uses ruff for linting and formatting:

# Check for lint errors
uvx ruff check .

# Check formatting
uvx ruff format --check .

# Auto-format
uvx ruff format .

CI/CD

The GitHub Actions workflow (.github/workflows/main.yml) runs on every push, pull request, and nightly schedule across macOS, Windows, and Linux.

Pipeline Overview

lint --> test (macOS, Windows, Linux) --> build_artifacts --> publish_release
Job Trigger Description
Lint All pushes/PRs Runs ruff check and ruff format --check on Ubuntu
Test After lint passes Codegen, native build + C++ tests, Python tests (all 4 suites) on 3 platforms
Build Artifacts Nightly, manual, or tag push Builds platform-specific wheels (asc-fdl, asc-fdl-imaging, asc-fdl-frameline-generator, asc-fdl-viewer) and standalone FDL Viewer app (PyInstaller)
Publish Release Tag push (v*) on main Creates a GitHub Release and uploads all artifacts

Caching

Git LFS objects are cached per-OS to avoid re-downloading large test resources on every run. No build artifacts are cached.

Test Parallelism

Non-viewer Python test suites run with pytest-xdist (-n auto) for parallel execution across all available CPU cores. Viewer tests run serially to avoid display conflicts.


Release Process

All package versions across the repository (Node.js, Python, and C++ core) are kept in sync using scripts/set_version.py.

Steps

1. Bump the version

Run the version script with the new version string. This updates all 9 version-bearing files in one command:

python scripts/set_version.py 0.2.0
# or for a pre-release:
python scripts/set_version.py 0.2.0-rc.1

Use --dry-run to preview changes without writing:

python scripts/set_version.py --dry-run 0.2.0

2. Commit and open a PR

git add -A
git commit -m "Bump version to 0.2.0"
git push origin your-branch
# Open a PR targeting main and get it reviewed and merged

3. Tag after CI passes on main

Once the PR is merged and the CI/CD pipeline on main passes, tag the merge commit:

git checkout main
git pull origin main
git tag v0.2.0
git push origin v0.2.0

Pushing the tag triggers the full release pipeline: artifact builds on all platforms, GitHub Release creation, npm publish of @asc-mitc/fdl to the npm registry, and Python package publishing to PyPI.

Pre-release tags (containing -dev, -alpha, or -rc) can be pushed from the dev branch and will create a pre-release on GitHub without requiring the tag to be on main.

ABI Version

The C library ABI version (FDL_ABI_VERSION_MAJOR/MINOR/PATCH in native/core/cmake/FDLVersion.cmake) is independent of the package version and is not updated by set_version.py.

The ABI version must be bumped manually, directly in FDLVersion.cmake, and only when the public C ABI changes in a binary-incompatible way (e.g. removing or changing the signature of a symbol in fdl_core.h). Routine package version bumps (pre-releases, patch fixes, new features that don't break the C ABI) leave the ABI triple unchanged.

Version type Managed by When to bump
Package version (0.x.y-dev.z) scripts/set_version.py Every release
C ABI version (FDL_ABI_VERSION_*) Manual edit in FDLVersion.cmake Only on binary-incompatible C ABI change