Skip to content

seethroughlab/libnclc

Repository files navigation

libnclc

An open source C library implementing the NotchLC video codec, with an FFmpeg plugin.

Status: Active development. The core library, GPU decode path, encoder, and FFmpeg wrappers are implemented and tested on macOS/Linux. Windows builds are expected to work (C99, no POSIX dependencies, MSVC support in CMake) but have not yet been tested. See ROADMAP.md.


What Is NotchLC?

NotchLC (nclc) is a GPU-friendly intra-frame video codec used in the live visual and VJ community, primarily via Notch. It stores each frame as a YUV+Alpha image using spatial-domain block compression with LZ4 or LZF entropy coding, inside a QuickTime MOV container.

The codec is designed so that compressed frames can be uploaded directly to the GPU and decompressed via compute shaders, minimizing PCI-e bandwidth and avoiding CPU-side decode overhead. FFmpeg has an existing CPU-side decoder; libnclc aims to provide both CPU and GPU-friendly decode paths, plus an encoder (which no open-source implementation currently provides).


Format Overview

Property Value
FourCC nclc
Container QuickTime MOV
Color model YCbCr + Alpha
Luma depth 12 bits
Chroma depth 8 bits (expanded to 12 on decode)
Alpha depth 8 bits (expanded to 12 on decode)
Decoded pixel format YUVA 4:4:4 12-bit
Compression LZF or LZ4 (custom variant)
Block sizes 4x4 (luma), 16x16 hierarchical (chroma, alpha)
Typical compression 5:1 to 8:1 vs raw

See format.md for the complete bitstream specification.


Building

cmake -B build
cmake --build build

Testing

ctest --test-dir build --output-on-failure

Installing

cmake --install build --prefix /usr/local

FFmpeg Integration

FFmpeg AVCodec wrappers are provided in ffmpeg/ for both decoding and encoding. These must be integrated into an FFmpeg source tree — see ffmpeg/README.md.


Usage

Decode

#include <nclc/nclc.h>

nclc_decoder_t *dec = nclc_decoder_create();
nclc_frame_t frame;

nclc_error_t err = nclc_decode_frame(dec, sample_data, sample_size,
                                     NCLC_PIXFMT_RGBA8, &frame);
if (err == NCLC_OK) {
    /* frame.planes[0] is RGBA8, frame.width x frame.height */
    nclc_frame_free(&frame);
}

nclc_decoder_destroy(dec);

Encode

nclc_encoder_params_t params = {
    .width = 1920, .height = 1080,
    .quality = NCLC_QUALITY_HIGH,
    .compress = NCLC_COMPRESS_LZ4,
};
nclc_encoder_t *enc = nclc_encoder_create(&params);

uint8_t *out_data; size_t out_size;
nclc_encode_frame(enc, &input_frame, &out_data, &out_size);
/* out_data is a complete NotchLC frame, decodable by FFmpeg/libnclc */

nclc_encoder_destroy(enc);

GPU Path

nclc_gpu_frame_t gpu;
nclc_decode_gpu(dec, sample_data, sample_size, &gpu);

/* Option A: Upload individual sections */
/* gpu.y_control, gpu.y_data, gpu.y_block_offsets, gpu.uv_data, etc. */

/* Option B: Single packed buffer upload */
const uint8_t *pack; size_t pack_size;
nclc_gpu_pack(dec, &gpu, &pack, &pack_size);
/* Upload pack buffer, dispatch shaders using nclc_gpu_header_t offsets */

Reference compute shaders are provided in shaders/ (GLSL 450, HLSL SM 5.0, Metal).


Project Structure

libnclc/
├── include/
│   └── nclc/
│       └── nclc.h          # Public C API
├── src/
│   ├── internal.h          # Shared internal definitions
│   ├── bitstream.h/.c      # Bit reader/writer
│   ├── lz4.c               # Custom LZ4 decompressor
│   ├── lzf.c               # LZF decompressor
│   ├── decode.c            # Frame-level decode dispatch
│   ├── decode_y.c          # Y channel block decoder
│   ├── decode_uv.c         # UV channel hierarchical decoder
│   ├── decode_alpha.c      # Alpha channel decoder
│   ├── decode_gpu_ref.c    # CPU reference decode from GPU data
│   ├── gpu_pack.c          # Single-buffer GPU upload packing
│   ├── colorspace.c        # YUVA ↔ RGBA conversion
│   ├── encode.c            # Frame-level encoder
│   ├── encode_y.c          # Y channel block encoder
│   ├── encode_uv.c         # UV hierarchical encoder
│   └── encode_alpha.c      # Alpha channel encoder
├── shaders/
│   ├── nclc_common.glsl    # Shared GLSL definitions
│   ├── nclc_decode_y.comp  # Y luma decode (GLSL 450)
│   ├── nclc_decode_uv.comp # UV chroma decode (GLSL 450)
│   ├── nclc_decode_alpha.comp # Alpha decode (GLSL 450)
│   ├── nclc_yuva_to_rgba.comp # Colorspace conversion (GLSL 450)
│   ├── hlsl/               # HLSL SM 5.0 translations
│   └── metal/              # Metal Shading Language translations
├── ffmpeg/
│   ├── nclcdec.c           # FFmpeg AVCodec decoder wrapper
│   ├── nclcenc.c           # FFmpeg AVCodec encoder wrapper
│   └── README.md           # FFmpeg integration instructions
├── tools/
│   ├── nclcinfo.c          # CLI inspection tool
│   ├── nclcenc.c           # Raw RGBA8-to-frame encoder CLI
│   └── nclcdec.c           # Frame-to-raw RGBA8 decoder CLI
├── tests/
│   ├── test_decode.c       # Decoder and malformed-input tests
│   ├── test_gpu_ref.c      # CPU vs GPU-reference validation
│   ├── test_encode.c       # Encoder round-trip tests
│   └── test_lz4_roundtrip.c # Custom LZ4 tests
├── cmake/
│   └── libnclcConfig.cmake.in # CMake package config template
├── format.md               # Bitstream specification
├── ROADMAP.md              # Phased development plan
├── CONTRIBUTING.md          # Contribution guidelines
├── CMakeLists.txt
└── LICENSE

Prior Art


Legal

NotchLC's bitstream format was determined through reverse engineering of files produced by Notch, with reference to FFmpeg's LGPL-licensed decoder implementation. Reverse engineering for interoperability is protected under EU Software Directive Article 6 and has defensible basis under DMCA §1201(f).

This project is not affiliated with or endorsed by Notch.


License

GNU Lesser General Public License v2.1 or later. See LICENSE.

Contributions require assignment of rights compatible with LGPL-2.1+. See CONTRIBUTING.md.

About

Open source NotchLC video codec library — decoder, GPU path, encoder, FFmpeg integration

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors