rav1d

repository·main·Indexed 20 days ago

https://github.com/memorysafety/rav1d

A high-performance, open-source AV1 decoder written in Rust. As a Rust port of the dav1d decoder, rav1d focuses on speed and correctness while providing a C API for drop-in compatibility with libdav1d. It supports x86, x86_64, aarch64, arm, and riscv64 targets, with optional assembly optimizations via nasm.

Tokens
10.8K
Snippets
42
Records
55
Agent score
71%

What's inside rav1d

  1. Cross-compile rav1d

    main

    You can cross-compile rav1d using cargo --target. This requires setting the RUSTFLAGS environment variable to specify the correct linker for the target platform.

    Supported Targets:

    • x86_64-unknown-linux-gnu
    • i686-unknown-linux-gnu
    • armv7-unknown-linux-gnueabihf
    • aarch64-unknown-linux-gnu
    • riscv64gc-unknown-linux-gnu

    Running tests under QEMU: If cross-compiling for QEMU execution, you must specify the +crt-static target feature in RUSTFLAGS.

    # Example: Compiling for aarch64 from Ubuntu
    RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc" cargo build --target aarch64-unknown-linux-gnu
    
    # Example: Compiling for QEMU with static CRT
    RUSTFLAGS="-C target-feature=+crt-static -C linker=aarch64-linux-gnu-gcc" cargo build --target aarch64-unknown-linux-gnu
  2. Build rav1d

    main

    rav1d is a Rust-based AV1 decoder. To build it, you need the standard Rust toolchain (installable via https://rustup.rs).

    Target Support & Toolchain Requirements:

    • x86, x86_64, and aarch64: Supported on stable Rust.
    • arm and riscv64: Currently require a nightly compiler (configured by default via rust-toolchain.toml).
    • x86 targets: Requires nasm to be installed for assembly support.

    Build Profiles:

    • Release build: Standard optimized build.
    • opt-dev profile: Faster than debug but keeps all debug checks enabled; recommended for development.
    • Stable build: To force a stable compiler build (useful for x86/aarch64), use the +stable flag.
    # Standard release build
    cargo build --release
    
    # Development profile (optimized with debug checks)
    cargo build --profile opt-dev
    
    # Build only the library using stable Rust
    cargo +stable build --lib --release
  3. Re-transpile functions after C code changes

    main

    If you have modified the underlying C code and need to update the corresponding re-transpiled functions (fns), follow this workflow using the retranspile.sh script. This process involves re-running the transpilation, generating diffs to compare the old and new versions, and manually patching the changes back into the codebase.

    Workflow Steps:

    1. Modify C code: Apply your changes to the C source files.
    2. Run Transpilation: Execute ./retranspile.sh transpile to perform the re-transpilation.
    3. Prepare New Function Files: For each function ${fn_name} you modified, copy the fn ${fn_name} block and any newly introduced callees to a new file named retranspile/${fn_name}.fn.new.
    4. Stash Changes: Run ./retranspile.sh stash to stash all current re-transpilation changes.
    5. Diff and Patch: For each modified function ${fn_name}:
      • Generate a diff between the initial transpilation and the new version: ./retranspile.sh fn-diff ${fn_name}. This saves the diff to retranspile/${fn_name}.fn.diff.
      • Replace the existing fn in the source with the new version from your .new file.
      • Manually apply the changes from retranspile/${fn_name}.fn.diff back into the source to ensure only the intended logic changes are kept.
      • Commit the updated function: ./retranspile.sh commit ${fn_name}.
    6. Cleanup: Remove intermediate files using ./retranspile.sh cleanup ${fn_name} (for a specific function) or ./retranspile.sh cleanup (to clean all files).
    # 1. Transpile
    ./retranspile.sh transpile
    
    # 2. Stash
    ./retranspile.sh stash
    
    # 3. Diff a specific function
    ./retranspile.sh fn-diff ${fn_name}
    
    # 4. Commit changes
    ./retranspile.sh commit ${fn_name}
    
    # 5. Cleanup
    ./retranspile.sh cleanup ${fn_name}
  4. Run rav1d tests

    main

    rav1d uses the original dav1d Meson test suite.

    Prerequisites:

    1. Install Meson.
    2. Manually build rav1d using cargo before running tests. It is highly recommended to use the release or opt-dev profiles to prevent test timeouts.

    Execution: Use the .github/workflows/test.sh helper script to run the suite.

    # 1. Build the project
    cargo build --release
    
    # 2. Run tests using the helper script
    .github/workflows/test.sh -r target/release/dav1d
  5. Configure Rav1dLogger output targets

    main

    The Rav1dLogger enum defines where log messages are directed. You can use it to switch between different output streams:

    • Rav1dLogger::Stdout: Redirects logs to standard output.
    • Rav1dLogger::Stderr: Redirects logs to standard error (the default).
    • Rav1dLogger::Dav1d(Dav1dLogger): Uses a custom Dav1dLogger instance for C-style callback logging.
    // Set logger to stdout
    let logger = Rav1dLogger::Stdout;
    
    // Set logger to stderr (default)
    let logger = Rav1dLogger::Stderr;
  6. Configure rav1d feature flags

    main

    rav1d uses feature flags to control assembly optimization and bitdepth support. All features are enabled by default.

    Available Features:

    • asm: Enables optimized assembly routines (requires nasm on x86).
    • bitdepth_8: Enables 8-bit depth decoding.
    • bitdepth_16: Enables 10 and 12-bit depth decoding.

    To disable default features and selectively enable others (e.g., to test Rust fallback functions by disabling assembly), use --no-default-features and --features.

    # Build without assembly routines, but keep bitdepth support
    cargo build --no-default-features --features="bitdepth_8,bitdepth_16"
  7. Configure picture allocation with `Rav1dPicAllocator`

    main

    The Rav1dPicAllocator manages how Rav1dPicture memory is allocated and released.

    • Default Allocator: Using Rav1dPicAllocator::default() provides a standard allocator that uses dav1d_default_picture_alloc and dav1d_default_picture_release. This default allocator is designed to work with a MemPool provided via a cookie.
    • Custom Allocation: You can provide a custom alloc_picture_callback and release_picture_callback to control the lifecycle of picture buffers, which is useful for integrating with custom memory management systems or specialized hardware allocators.
  8. Use the rav1d CLI for decoding

    main
    The rav1d CLI tool is used for decoding AV1 bitstreams. It supports various input demuxers, output muxers, and realtime playback synchronization. The tool provides progress statistics to stderr by default, showing decoded frame counts, percentages, and FPS (frames per second).
  9. Use the rav1d C API

    main

    The librav1d library is designed as a drop-in replacement for libdav1d. It primarily exposes a C API via the librav1d.a library generated by cargo build.

    • C Integration: Use the same API patterns as libdav1d. For detailed documentation, refer to the dav1d C API documentation.
    • Rust Integration: Equivalent Rust functions are located in src/lib.rs.
    • Note: A dedicated, idiomatic Rust API is planned for future releases.
  10. Configure Loop Restoration Parameters

    main

    Loop restoration in rav1d uses two types of parameters: general filter parameters and Self-Guided Filter (SGR) parameters.

    LooprestorationParams

    This structure holds the filter coefficients. It is aligned to 16 bytes and contains a filter field which is a 2D array of 8 i16 values: [[i16; 8]; 2].

    LooprestorationParamsSgr

    This structure defines the parameters for the Self-Guided Filter (SGR). It is used to control the SGR behavior via the sgr() and sgr_mut() methods on LooprestorationParams.

    Fields:

    • s0: u32 (SGR parameter 0)
    • s1: u32 (SGR parameter 1)
    • w0: i16 (Weight 0)
    • w1: i16 (Weight 1)
    // Example of accessing SGR parameters from LooprestorationParams
    let sgr_params = params.sgr();
    let s0 = sgr_params.s0;
    let w0 = sgr_params.w0;
  11. Reference: retranspile.sh CLI commands

    main

    The retranspile.sh script provides several commands for managing the re-transpilation lifecycle of functions (fns).

    ./retranspile.sh transpile      # Re-transpile the C code
    ./retranspile.sh stash          # Stash all re-transpile changes
    ./retranspile.sh fn-diff <fn>   # Save diff for ${fn_name} to retranspile/${fn_name}.fn.diff
    ./retranspile.sh commit <fn>    # Commit the re-transpiled changes for ${fn_name}
    ./retranspile.sh cleanup <fn>   # Cleanup intermediate files for ${fn_name}
    ./retranspile.sh cleanup        # Cleanup all intermediate files