How to Configure Tile-Based Threading in librav1e

This article explains how to configure tile-based threading in librav1e, the Rust-based AV1 video encoder. It covers the underlying concepts of AV1 tiling, provides step-by-step instructions for configuring tiles via both the command-line interface (CLI) and the developer API, and outlines best practices for balancing encoding speed with visual quality.

Understanding AV1 Tiles and Threading

In the AV1 video coding format, a frame can be partitioned into a grid of independently decodable rectangles known as “tiles.” Because these tiles do not rely on spatial prediction from neighboring tiles, they can be encoded and decoded in parallel.

librav1e leverages this architecture to distribute the encoding workload across multiple CPU threads. To achieve optimal multi-threaded performance, you must configure both the tile grid structure and the encoder’s thread limit.

Method 1: Configuring Tiles via the CLI

If you are using the rav1e command-line tool, tile-based threading is controlled using three primary arguments: --tile-cols, --tile-rows, and --threads.

In AV1, tile counts are specified as exponents of 2 (\(\log_2\) values):

Example Command

To encode a video using a 2x2 tile grid (4 tiles total) utilizing 4 threads, use the following command:

rav1e input.y4m -o output.ivf --tile-cols 1 --tile-rows 1 --threads 4

Method 2: Configuring Tiles via the Rust API

If you are integrating librav1e directly into a Rust application, you must configure these parameters inside the Config and EncoderConfig structures.

  1. Initialize your EncoderConfig.
  2. Set the tile_cols and tile_rows fields (using \(\log_2\) values).
  3. Set the threads option in the outer Config struct to allocate worker threads to the thread pool.
use rav1e::prelude::*;

fn main() {
    // 1. Create the base encoder configuration
    let mut enc_cfg = EncoderConfig::default();
    
    // Configure a 2x2 tile layout (2^1 columns x 2^1 rows = 4 tiles)
    enc_cfg.tile_cols = 1; 
    enc_cfg.tile_rows = 1;

    // 2. Wrap it in the master Config struct and set thread limits
    let cfg = Config::new()
        .with_encoder_config(enc_cfg)
        .with_threads(4); // Allocate 4 threads for parallel tile processing
}

Best Practices for Tile Configuration

While increasing the tile count improves encoding speed by enabling higher CPU utilization, it can negatively impact compression efficiency. Because prediction cannot cross tile boundaries, a high density of tiles results in a higher bitrate for the same visual quality.

To achieve the best balance: * 1080p Video: Use 2 columns and 1 row (2 tiles) or 2 columns and 2 rows (4 tiles). * 4K Video: Use 4 columns and 2 rows (8 tiles). * Thread Allocation: Always ensure your --threads count is at least equal to the total number of tiles (columns \(\times\) rows) to prevent thread starvation during parallel execution.