wav1c 0.1.2

Wondrous AV1 encoder written in safe Rust.
Documentation
# wav1c - Wondrous AV1 Encoder

An AV1 video encoder written from scratch in safe Rust with zero dependencies. Produces IVF files decodable by [dav1d](https://code.videolan.org/videolan/dav1d).

## Features

- YUV 4:2:0 encoding (8-bit)
- Intra prediction (DC mode) with per-pixel reconstructed context
- Inter prediction (GLOBALMV with LAST_FRAME reference)
- Forward DCT transforms (4x4 chroma, 8x8 luma)
- MSAC arithmetic coding with full coefficient encoding
- GoP structure (keyframe + inter frames)
- Arbitrary frame dimensions up to 4096x2304
- Y4M input, IVF output
- Streaming encoder API (frame-by-frame encoding)
- C FFI shared library for embedding in non-Rust applications

## Workspace Structure

```
wav1c/          Core library with batch and streaming APIs
wav1c-cli/      Command-line encoder
wav1c-ffi/      C FFI shared library (cdylib + staticlib)
```

## Build

```bash
cargo build --workspace --release
```

## CLI Usage

Encode a Y4M video:

```bash
wav1c input.y4m -o output.ivf
```

Encode a solid color frame:

```bash
wav1c 320 240 128 128 128 -o gray.ivf
```

With options:

```bash
wav1c input.y4m -o output.ivf -q 100 --keyint 10 --bitrate 500k
```

Decode with dav1d:

```bash
dav1d -i output.ivf -o decoded.y4m
```

Generate test input with ffmpeg:

```bash
ffmpeg -f lavfi -i testsrc=duration=2:size=320x240:rate=25 -pix_fmt yuv420p input.y4m
```

## Rust Streaming API

```rust
use wav1c::{Encoder, EncoderConfig, FrameType};
use wav1c::y4m::FramePixels;

let config = EncoderConfig {
    base_q_idx: 128,
    keyint: 25,
    target_bitrate: None,
    fps: 25.0,
};

let mut encoder = Encoder::new(320, 240, config).unwrap();
let frame = FramePixels::solid(320, 240, 128, 128, 128);

encoder.send_frame(&frame).unwrap();
let packet = encoder.receive_packet().unwrap();

assert_eq!(packet.frame_type, FrameType::Key);
// packet.data contains raw AV1 OBUs (TD + SequenceHeader + Frame)
```

## C FFI

The `wav1c-ffi` crate produces `libwav1c_ffi.dylib` (macOS) / `libwav1c_ffi.so` (Linux) and `libwav1c_ffi.a`.

```c
#include "wav1c.h"

Wav1cConfig cfg = { .base_q_idx = 128, .keyint = 25, .fps = 25.0 };
Wav1cEncoder *enc = wav1c_encoder_new(320, 240, &cfg);

wav1c_encoder_send_frame(enc, y, y_len, u, u_len, v, v_len);
Wav1cPacket *pkt = wav1c_encoder_receive_packet(enc);
// pkt->data, pkt->size contain raw AV1 OBUs

wav1c_packet_free(pkt);
wav1c_encoder_free(enc);
```

Build the C example:

```bash
cargo build -p wav1c-ffi --release
cc -o encode -I wav1c-ffi/include wav1c-ffi/examples/encode.c \
   -L target/release -lwav1c_ffi
```

## FFmpeg Integration

A patch is included to add wav1c as an FFmpeg external encoder (`-c:v libwav1c`).

```bash
# Build the wav1c static library
cargo build -p wav1c-ffi --release

# Clone and patch FFmpeg
git clone https://git.ffmpeg.org/ffmpeg.git
cd ffmpeg
git apply /path/to/wav1c/ffmpeg-libwav1c.patch

# Configure with libwav1c (adjust library path as needed)
./configure --enable-libwav1c \
  --extra-cflags="-I/path/to/wav1c/wav1c-ffi/include" \
  --extra-ldflags="-L/path/to/wav1c/target/release"

make -j$(nproc)

# Encode
./ffmpeg -i input.y4m -c:v libwav1c -wav1c-q 128 output.mp4
```

## Test

```bash
cargo test --workspace
```

Integration tests decode output with [dav1d](https://code.videolan.org/videolan/dav1d) and verify pixel accuracy. Install dav1d and ensure it is available in your `PATH`, or set the `DAV1D` environment variable to point to the binary. Tests will skip gracefully if dav1d is not found.

## License

This project is licensed under the Mozilla Public License 2.0. See [LICENSE](LICENSE) for details.