tree: 54b98c8b4931339b695acb6c8227128ebf97e626 [path history] [tgz]
  1. .cargo/
  2. .circleci/
  3. .github/
  4. src/
  5. .android-checksum.json
  6. .cargo-checksum.json
  7. .cargo_vcs_info.json
  8. Android.bp
  9. android_config.toml
  10. Cargo.lock
  11. Cargo.toml
  12. Cargo.toml.orig
  13. cargo_embargo.json
  14. CHANGELOG.md
  15. CODE_OF_CONDUCT.md
  16. LICENSE-APACHE.md
  17. METADATA
  18. MODULE_LICENSE_APACHE2
  19. README.md
  20. rust-toolchain.toml
  21. TEST_MAPPING
crates/yuv/README.md

Rust utilities for YUV format handling and conversion.

crates.io Build

Fast and simple YUV approximation conversion in pure Rust. At most the same as libyuv does. Performance will be equal to libyuv or slightly higher on platforms where SIMD is implemented. Otherwise, equal or slower.

Mostly implemented AVX-512, AVX2, SSE, NEON, WASM. Waiting for SVE to be available in nightly.

x86 targets with SSE and AVX uses runtime dispatch to detect available cpu features.

Supports:

  • [x] YCbCr ( aka YUV )
  • [x] YCgCo
  • [x] YCgCo-Re/YCgCo-Ro
  • [x] YUY2
  • [x] Identity ( GBR )
  • [x] Sharp YUV

All the methods support RGB, BGR, BGRA and RGBA

Scaling

If need scaling support then pic-scale is available.

SIMD

Runtime dispatch is used for use if available sse4.1, avx2, avx512bw, avx512vbmi, avx512vnni, avxvnni, rdm for NEON.

For the sse4.1, avx2, rdm there is no action needed, however for AVX-512 activated feature nightly_avx512 along nightly rust channel is required.

Always consider to compile with nightly_avx512 when compiling for x86, it adds noticeable gain on supported cpus.

Wasm simd128 as target feature should be enabled for implemented SIMD wasm paths support,

Rayon

Some paths have multi-threading support. However, YUV conversion usually makes more sense in single-threaded mode, thus use this feature with care.

Adding to project

cargo add yuv

RGB to YCbCr

let mut planar_image =
    YuvPlanarImageMut::<u8>::alloc(width as u32, height as u32, YuvChromaSubsampling::Yuv420);
rgb_to_yuv422(
    &mut planar_image,
    &src_bytes,
    rgba_stride as u32,
    YuvRange::Limited,
    YuvStandardMatrix::Bt601,
)
.unwrap();

YCbCr to RGB

yuv420_to_rgb(
    &yuv_planar_image,
    &mut rgba,
    rgba_stride as u32,
    YuvRange::Limited,
    YuvStandardMatrix::Bt601,
)
.unwrap();

HDR Formats

The following planar formats are used for HDR content, with either 10-bit or 12-bit color depth:

Supported:

  • I010, I012, P010, P012, P016
    Half width, half height
  • I210, I212, P210, P212, P216
    Half width, full height
  • I410, I412, P410, P412
    Full width, full height

Format Breakdown:

  • I: Represents the color space (as defined above), and these formats use 3 planes: Y (luminance), U (chrominance), and V (chrominance).
  • ICgC: Represents the color space (as defined above), and these formats use 3 planes: Y (luminance), Cg (chrominance), and Co (chrominance).
  • P: A biplanar format (similar to NV12), but with 16-bit precision, where the valid bits are stored in the high bits. This format has:
    • A Y plane
    • A UV plane (with U and V interleaved)
  • GB: Represents the GBR planar format, which uses 3 separate planes for each of the red, green, and blue color components. This format has:
    • G plane (green channel)
    • B plane (blue channel)
    • R plane (red channel)

Subsampling:

  • 0: Represents 4:2:0 chroma subsampling.
  • 2: Represents 4:2:2 chroma subsampling.
  • 4: Represents 4:4:4 chroma subsampling.

Bit Depth:

  • 10,12,14,16: Indicates the bits per channel.

Benchmarks

Tests performed on the image 1997x1331

YUV 8 bit-depth conversion

aarch64 tested on Mac Pro M3.

AVX2 tests performed on m4.large with Ubuntu 24.04 droplet. AVX2 Win test performed on Windows 11 Intel Core i9-14900HX.

cargo bench --bench yuv8 --manifest-path ./app/Cargo.toml --features fast_mode,professional_mode,rdm

AVX-512 tests performed on AWS c5.large with Ubuntu 24.04 instance with command

cargo +nightly bench --bench yuv8 --manifest-path ./app/Cargo.toml --features nightly_avx512,fast_mode,professional_mode

Encoding 8-bit

Conversiontime(NEON)Time(AVX2 Win)Time(AVX2)Time(AVX-512)
utils RGB->YUV 4:2:0255.25µs354.25µs973.17µs722.87µs
libyuv RGB->YUV 4:2:0306.80µs3.62ms1.10ms972.52µs
utils RGBA->YUV 4:2:0257.02µs367.47µs781.54µs785.93µs
libyuv RGBA->YUV 4:2:0429.36µs2.70ms846.69µs707.33µs
utils RGBA->YUV 4:2:2327.11µs464.82µs1.06ms964.87µs
libyuv RGBA->YUV 4:2:2616.29µs4.3003ms1.09ms947.97µs
utils RGBA->YUV 4:4:4378.49µs534.87µs1.09ms974.29µs

Decoding 8-bit

Conversiontime(NEON)Time(AVX2 Win)Time(AVX2)Time(AVX-512)
utils YUV NV12->RGBA377.59µs359.11µs917.52µs736.21µs
utils YUV NV12->RGB273.38µs339.53µs817.71µs654.37µs
libyuv YUV NV12->RGB621.11µs5.46ms979.96µs800.85µs
utils YUV 4:2:0->RGB346.13µs375.34µs923.83µs614.19µs
libyuv YUV 4:2:0->RGB675.72µs5.8231ms1.42ms1.16ms
utils YUV 4:2:0->RGBA396.58µs380.13µs942.92µs733.88µs
libyuv YUV 4:2:0->RGBA710.88µs557.44µs1.03ms870.64µs
utils YUV 4:2:2->RGBA438.19µs410.71µs1.10ms824.69µs
libyuv YUV 4:2:2->RGBA734.25µs579.24µs1.04ms851.24µs
utils YUV 4:4:4->RGBA429.60µs366.85µs1.10ms819.17µs
libyuv YUV 4:4:4->RGBA596.55µs525.90µs963.66µs803.62µs
utils YUV 4:0:0->RGBA220.67µs254.83µs651.88µs600.43µs
libyuv YUV 4:0:0->RGBA522.71µs1.8204ms635.61µs525.56µs

YUV 16 bit-depth conversion

cargo bench --bench yuv16 --manifest-path ./app/Cargo.toml --features rdm

AVX-512 tests performed on AWS c5.large with Ubuntu 24.04 instance with command

cargo +nightly bench --bench yuv16 --manifest-path ./app/Cargo.toml --features nightly_avx512

Encoding 10-bit

10-bit encoding is not implemented in libyuv

time(NEON)Time(AVX2 Win)Time(AVX2)Time(AVX-512)
utils RGB10->YUV10 4:2:0502.65µs745.02µs1.88ms1.21ms
libyuv RGB10->YUV10 4:2:0xxxx
utils RGBA10->YUV10 4:2:0605.45µs807.89µs2.03ms1.57ms
libyuv RGBA10->YUV10 4:2:0xxxx
utils RGBA10->YUV10 4:2:2769.08µs1.04ms2.51ms1.83ms
libyuv RGBA10->YUV10 4:2:2xxxx
utils RGBA10->YUV10 4:4:4600.56µs1.12ms2.82ms2.03ms

Decoding 10-bit

time(NEON)Time(AVX2 Win)Time(AVX2)Time(AVX-512)
utils YUV10 4:2:0->RGB10596.78µs662.38µs1.76ms1.23ms
libyuv YUV10 4:2:0->RGB10xxxx
utils YUV10 4:2:0->RGBA10727.52µs670.15µs1.92ms1.59ms
utils YUV10 4:2:0->RGBA8765.23µs492.63µs1.36ms900.10µs
libyuv YUV10 4:2:0->RGBA81.54ms6.8641ms1.16ms966.94µs
utils YUV10 4:2:2->RGBA10746.51µs787.41µs2.02ms1.61ms
utils YUV10 4:2:2->RGBA8799.25µs438.14µs1.23ms972.19µs
libyuv YUV10 4:2:2->RGBA81.55ms6.8374ms1.21ms991.23µs
utils YUV10 4:4:4->RGBA10953.73µs848.02µs2.26ms1.8639ms

Geometry and mirroring

cargo bench --bench geometry --manifest-path ./app/Cargo.toml
time(NEON)Time(AVX2 Win)Time(AVX2)
utils Rotate 90 RGBA8560.74µs655.43µs2.50ms
libyuv Rotate 90 RGBA81.84ms1.01ms2.86ms
utils Rotate 90 Plane8215.43µs387.44µs1.05ms
libyuv Rotate 90 Plane8291.15µs416.52µs1.06ms
utils Rotate 180 RGBA8326.44µs506.35µs657.93µs
libyuv Rotate 180 RGBA8378.70µs512.83µs669.12µs
utils Rotate 180 Plane861.02µs127.26µs227.66µs
libyuv Rotate 180 Plane894.11µs418.83µs233.66µs
utils Rotate 270 RGBA8564.78µs652.83µs2.57ms
libyuv Rotate 270 RGBA81.99ms1.03ms3.06ms

This project is licensed under either of

  • BSD-3-Clause License (see LICENSE)
  • Apache License, Version 2.0 (see LICENSE)

at your option.