diff --git a/.gitmodules b/.gitmodules index f13ae215..b70842c2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "livekit/protocol"] path = livekit-protocol/protocol url = https://github.com/livekit/protocol +[submodule "yuv-sys/libyuv"] + path = yuv-sys/libyuv + url = https://chromium.googlesource.com/libyuv/libyuv diff --git a/Cargo.toml b/Cargo.toml index 52650e01..c0a232a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,15 @@ members = [ "livekit-runtime", "libwebrtc", "soxr-sys", + "yuv-sys", + "imgproc", "webrtc-sys", "webrtc-sys/build", ] [workspace.dependencies] +imgproc = { version = "0.3.11", path = "imgproc" } +yuv-sys = { version = "0.3.6", path = "yuv-sys" } libwebrtc = { version = "0.3.7", path = "libwebrtc" } livekit-api = { version = "0.4.1", path = "livekit-api" } livekit-ffi = { version = "0.12.3", path = "livekit-ffi" } diff --git a/imgproc/Cargo.lock b/imgproc/Cargo.lock new file mode 100644 index 00000000..6bf8e288 --- /dev/null +++ b/imgproc/Cargo.lock @@ -0,0 +1,442 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "imgproc" +version = "0.3.6" +dependencies = [ + "yuv-sys", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "yuv-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9a8a1a93479f1701a725ffeaaa0dc03d8096387490e820a12daf3f302065fe" +dependencies = [ + "bindgen", + "cc", + "regex", +] diff --git a/imgproc/Cargo.toml b/imgproc/Cargo.toml new file mode 100644 index 00000000..6f49dccd --- /dev/null +++ b/imgproc/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "imgproc" +version = "0.3.11" +edition = "2021" +authors = ["Theo Monnom "] +license = "MIT OR Apache-2.0" +description = "image processing library" + +[dependencies] +yuv-sys = { path = "../yuv-sys" } diff --git a/imgproc/rustfmt.toml b/imgproc/rustfmt.toml new file mode 100644 index 00000000..18a73ace --- /dev/null +++ b/imgproc/rustfmt.toml @@ -0,0 +1,10 @@ +comment_width = 100 +doc_comment_code_block_width = 100 +format_code_in_doc_comments = true +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +max_width = 100 +use_small_heuristics = "Max" +wrap_comments = true +# Workaround for https://github.com/rust-lang/rust.vim/issues/464 +edition = "2021" diff --git a/imgproc/src/colorcvt/assert.rs b/imgproc/src/colorcvt/assert.rs new file mode 100644 index 00000000..0d184b44 --- /dev/null +++ b/imgproc/src/colorcvt/assert.rs @@ -0,0 +1,164 @@ +#[inline] +pub fn valid_420( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + width: u32, + height: u32, +) { + assert!(width > 0); + assert!(height > 0); + + let chroma_width = (width + 1) / 2; + let chroma_height = (height + 1) / 2; + + assert!(src_stride_y >= width); + assert!(src_stride_u >= chroma_width); + assert!(src_stride_v >= chroma_width); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_u.len() >= (src_stride_u * chroma_height) as usize); + assert!(src_v.len() >= (src_stride_v * chroma_height) as usize); +} + +#[inline] +pub fn valid_420a( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + src_a: &[u8], + src_stride_a: u32, + width: u32, + height: u32, +) { + assert!(width > 0); + assert!(height > 0); + + let chroma_width = (width + 1) / 2; + let chroma_height = (height + 1) / 2; + + assert!(src_stride_y >= width); + assert!(src_stride_u >= chroma_width); + assert!(src_stride_v >= chroma_width); + assert!(src_stride_a >= width); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_u.len() >= (src_stride_u * chroma_height) as usize); + assert!(src_v.len() >= (src_stride_v * chroma_height) as usize); + assert!(src_a.len() >= (src_stride_a * height) as usize); +} + +#[inline] +pub fn valid_422( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + width: u32, + height: u32, +) { + assert!(width > 0); + assert!(height > 0); + + let chroma_width = (width + 1) / 2; + let chroma_height = height; + + assert!(src_stride_y >= width); + assert!(src_stride_u >= chroma_width); + assert!(src_stride_v >= chroma_width); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_u.len() >= (src_stride_u * chroma_height) as usize); + assert!(src_v.len() >= (src_stride_v * chroma_height) as usize); +} + +#[inline] +pub fn valid_444( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + width: u32, + height: u32, +) { + assert!(height > 0); + assert!(width > 0); + + let chroma_width = width; + let chroma_height = height; + + assert!(src_stride_y >= width); + assert!(src_stride_u >= chroma_width); + assert!(src_stride_v >= chroma_width); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_u.len() >= (src_stride_u * chroma_height) as usize); + assert!(src_v.len() >= (src_stride_v * chroma_height) as usize); +} + +#[inline] +pub fn valid_010( + src_y: &[u16], + src_stride_y: u32, + src_u: &[u16], + src_stride_u: u32, + src_v: &[u16], + src_stride_v: u32, + width: u32, + height: u32, +) { + assert!(height > 0); + assert!(width > 0); + + let chroma_width = (width + 1) / 2; + let chroma_height = (height + 1) / 2; + + assert!(src_stride_y >= width); + assert!(src_stride_u >= chroma_width); + assert!(src_stride_v >= chroma_width); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_u.len() >= (src_stride_u * chroma_height) as usize); + assert!(src_v.len() >= (src_stride_v * chroma_height) as usize); +} + +#[inline] +pub fn valid_nv12( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + width: u32, + height: u32, +) { + assert!(width > 0); + assert!(height > 0); + + let chroma_height = (height + 1) / 2; + + assert!(src_stride_y >= width); + assert!(src_stride_uv >= width + width % 2); + assert!(src_y.len() >= (src_stride_y * height) as usize); + assert!(src_uv.len() >= (src_stride_uv * chroma_height) as usize); +} + +#[inline] +pub fn valid_rgba(src_rgba: &[u8], src_stride_rgba: u32, width: u32, height: u32) { + assert!(width > 0); + assert!(height > 0); + assert!(src_stride_rgba >= width * 4); + assert!(src_rgba.len() >= (src_stride_rgba * height) as usize); +} + +#[inline] +pub fn valid_rgb(src_rgb: &[u8], src_stride_rgb: u32, width: u32, height: u32) { + assert!(width > 0); + assert!(height > 0); + assert!(src_stride_rgb >= width * 3); + assert!(src_rgb.len() >= (src_stride_rgb * height) as usize); +} diff --git a/imgproc/src/colorcvt/mod.rs b/imgproc/src/colorcvt/mod.rs new file mode 100644 index 00000000..5c192ee8 --- /dev/null +++ b/imgproc/src/colorcvt/mod.rs @@ -0,0 +1,1101 @@ +mod assert; + +macro_rules! x420_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_y: &[u8], + stride_y: u32, + src_u: &[u8], + stride_u: u32, + src_v: &[u8], + stride_v: u32, + dst_rgba: &mut [u8], + dst_stride_rgba: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_420(src_y, stride_y, src_u, stride_u, src_v, stride_v, width, height); + assert::valid_rgba(dst_rgba, dst_stride_rgba, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_y.as_ptr(), + stride_y as i32, + src_u.as_ptr(), + stride_u as i32, + src_v.as_ptr(), + stride_v as i32, + dst_rgba.as_mut_ptr(), + dst_stride_rgba as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +x420_to_rgba!(i420_to_rgba, rs_I420ToRGBA); +x420_to_rgba!(i420_to_abgr, rs_I420ToABGR); +x420_to_rgba!(i420_to_bgra, rs_I420ToBGRA); +x420_to_rgba!(i420_to_argb, rs_I420ToARGB); +x420_to_rgba!(j420_to_argb, rs_J420ToARGB); +x420_to_rgba!(j420_to_abgr, rs_J420ToABGR); +x420_to_rgba!(h420_to_argb, rs_H420ToARGB); +x420_to_rgba!(h420_to_abgr, rs_H420ToABGR); +x420_to_rgba!(u420_to_argb, rs_U420ToARGB); +x420_to_rgba!(u420_to_abgr, rs_U420ToABGR); + +pub fn i420_to_rgb24( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_rgb24: &mut [u8], + dst_stride_rgb24: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_420(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_rgb24, dst_stride_rgb24, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I420ToRGB24( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_rgb24.as_mut_ptr(), + dst_stride_rgb24 as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i420_to_raw( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_raw: &mut [u8], + dst_stride_raw: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_420(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_raw, dst_stride_raw, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I420ToRAW( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_raw.as_mut_ptr(), + dst_stride_raw as i32, + width as i32, + height, + ) == 0 + }); +} + +macro_rules! rgba_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_abgr: &[u8], + src_stride_abgr: u32, + dst_argb: &mut [u8], + dst_stride_argb: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_rgba(src_abgr, src_stride_abgr, width, height); + assert::valid_rgba(dst_argb, dst_stride_argb, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_abgr.as_ptr(), + src_stride_abgr as i32, + dst_argb.as_mut_ptr(), + dst_stride_argb as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +rgba_to_rgba!(abgr_to_argb, rs_ABGRToARGB); +rgba_to_rgba!(argb_to_abgr, rs_ARGBToABGR); +rgba_to_rgba!(rgba_to_argb, rs_RGBAToARGB); +rgba_to_rgba!(bgra_to_argb, rs_BGRAToARGB); + +macro_rules! rgba_to_420 { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_rgba: &[u8], + src_stride_rgba: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_rgba(src_rgba, src_stride_rgba, width, height); + assert::valid_420( + dst_y, + dst_stride_y, + dst_u, + dst_stride_u, + dst_v, + dst_stride_v, + width, + height, + ); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_rgba.as_ptr(), + src_stride_rgba as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +rgba_to_420!(rgba_to_i420, rs_RGBAToI420); +rgba_to_420!(bgra_to_i420, rs_BGRAToI420); +rgba_to_420!(argb_to_i420, rs_ARGBToI420); +rgba_to_420!(abgr_to_i420, rs_ABGRToI420); + +pub fn raw_to_i420( + src_raw: &[u8], + src_stride_raw: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_rgb(src_raw, src_stride_raw, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + unsafe { + yuv_sys::rs_RAWToI420( + src_raw.as_ptr(), + src_stride_raw as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) + }; +} + +pub fn i422_to_i420( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_422(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I422ToI420( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i444_to_i420( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_444(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I444ToI420( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i010_to_i420( + src_y: &[u16], + src_stride_y: u32, + src_u: &[u16], + src_stride_u: u32, + src_v: &[u16], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_010(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I010ToI420( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn nv12_to_i420( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_nv12(src_y, src_stride_y, src_uv, src_stride_uv, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_NV12ToI420( + src_y.as_ptr(), + src_stride_y as i32, + src_uv.as_ptr(), + src_stride_uv as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i422_to_raw( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_raw: &mut [u8], + dst_stride_raw: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_422(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_raw, dst_stride_raw, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I422ToRAW( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_raw.as_mut_ptr(), + dst_stride_raw as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i422_to_rgb24( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_rgb24: &mut [u8], + dst_stride_rgb24: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_422(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_rgb24, dst_stride_rgb24, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I422ToRGB24( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_rgb24.as_mut_ptr(), + dst_stride_rgb24 as i32, + width as i32, + height, + ) == 0 + }); +} + +macro_rules! x422_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_rgba: &mut [u8], + dst_stride_rgba: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_422( + src_y, + src_stride_y, + src_u, + src_stride_u, + src_v, + src_stride_v, + width, + height, + ); + assert::valid_rgba(dst_rgba, dst_stride_rgba, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_rgba.as_mut_ptr(), + dst_stride_rgba as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +x422_to_rgba!(i422_to_abgr, rs_I422ToABGR); +x422_to_rgba!(j422_to_argb, rs_J422ToARGB); +x422_to_rgba!(i422_to_bgra, rs_I422ToBGRA); +x422_to_rgba!(i422_to_rgba, rs_I422ToRGBA); + +pub fn i444_to_raw( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_raw: &mut [u8], + dst_stride_raw: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_444(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_raw, dst_stride_raw, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I444ToRAW( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_raw.as_mut_ptr(), + dst_stride_raw as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i444_to_rgb24( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_rgb24: &mut [u8], + dst_stride_rgb24: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_444(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_rgb(dst_rgb24, dst_stride_rgb24, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I444ToRGB24( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_rgb24.as_mut_ptr(), + dst_stride_rgb24 as i32, + width as i32, + height, + ) == 0 + }); +} + +macro_rules! x444_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_rgba: &mut [u8], + dst_stride_rgba: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_444( + src_y, + src_stride_y, + src_u, + src_stride_u, + src_v, + src_stride_v, + width, + height, + ); + assert::valid_rgba(dst_rgba, dst_stride_rgba, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_rgba.as_mut_ptr(), + dst_stride_rgba as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +x444_to_rgba!(i444_to_abgr, rs_I444ToABGR); +x444_to_rgba!(i444_to_argb, rs_I444ToARGB); + +macro_rules! x010_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_y: &[u16], + src_stride_y: u32, + src_u: &[u16], + src_stride_u: u32, + src_v: &[u16], + src_stride_v: u32, + dst_abgr: &mut [u8], + dst_stride_abgr: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_010( + src_y, + src_stride_y, + src_u, + src_stride_u, + src_v, + src_stride_v, + width, + height, + ); + assert::valid_rgba(dst_abgr, dst_stride_abgr, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_abgr.as_mut_ptr(), + dst_stride_abgr as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +x010_to_rgba!(i010_to_abgr, rs_I010ToABGR); +x010_to_rgba!(i010_to_argb, rs_I010ToARGB); + +pub fn nv12_to_raw( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + dst_raw: &mut [u8], + dst_stride_raw: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_nv12(src_y, src_stride_y, src_uv, src_stride_uv, width, height); + assert::valid_rgb(dst_raw, dst_stride_raw, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_NV12ToRAW( + src_y.as_ptr(), + src_stride_y as i32, + src_uv.as_ptr(), + src_stride_uv as i32, + dst_raw.as_mut_ptr(), + dst_stride_raw as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn nv12_to_rgb24( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + dst_rgb24: &mut [u8], + dst_stride_rgb24: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_nv12(src_y, src_stride_y, src_uv, src_stride_uv, width, height); + assert::valid_rgb(dst_rgb24, dst_stride_rgb24, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_NV12ToRGB24( + src_y.as_ptr(), + src_stride_y as i32, + src_uv.as_ptr(), + src_stride_uv as i32, + dst_rgb24.as_mut_ptr(), + dst_stride_rgb24 as i32, + width as i32, + height, + ) == 0 + }); +} + +macro_rules! nv12_to_rgba { + ($rust_fnc:ident, $yuv_sys_fnc:ident) => { + pub fn $rust_fnc( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + dst_rgba: &mut [u8], + dst_stride_rgba: u32, + width: u32, + height: u32, + flip_y: bool, + ) { + assert::valid_nv12(src_y, src_stride_y, src_uv, src_stride_uv, width, height); + assert::valid_rgba(dst_rgba, dst_stride_rgba, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::$yuv_sys_fnc( + src_y.as_ptr(), + src_stride_y as i32, + src_uv.as_ptr(), + src_stride_uv as i32, + dst_rgba.as_mut_ptr(), + dst_stride_rgba as i32, + width as i32, + height, + ) == 0 + }); + } + }; +} + +nv12_to_rgba!(nv12_to_abgr, rs_NV12ToABGR); +nv12_to_rgba!(nv12_to_argb, rs_NV12ToARGB); + +pub fn i420_copy( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_420(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_420(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I420Copy( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i420a_copy( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + src_a: &[u8], + src_stride_a: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + dst_a: &mut [u8], + dst_stride_a: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_420a( + src_y, + src_stride_y, + src_u, + src_stride_u, + src_v, + src_stride_v, + src_a, + src_stride_a, + width, + height, + ); + + assert::valid_420a( + dst_y, + dst_stride_y, + dst_u, + dst_stride_u, + dst_v, + dst_stride_v, + dst_a, + dst_stride_a, + width, + height, + ); + + i420_copy( + src_y, + src_stride_y, + src_u, + src_stride_u, + src_v, + src_stride_v, + dst_y, + dst_stride_y, + dst_u, + dst_stride_u, + dst_v, + dst_stride_v, + width, + height, + flip_y, + ); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + unsafe { + yuv_sys::rs_CopyPlane( + src_a.as_ptr(), + src_stride_a as i32, + dst_a.as_mut_ptr(), + dst_stride_a as i32, + width as i32, + height, + ) + } +} + +pub fn i422_copy( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_422(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_422(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I422Copy( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i444_copy( + src_y: &[u8], + src_stride_y: u32, + src_u: &[u8], + src_stride_u: u32, + src_v: &[u8], + src_stride_v: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_u: &mut [u8], + dst_stride_u: u32, + dst_v: &mut [u8], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_444(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_444(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I444Copy( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn i010_copy( + src_y: &[u16], + src_stride_y: u32, + src_u: &[u16], + src_stride_u: u32, + src_v: &[u16], + src_stride_v: u32, + dst_y: &mut [u16], + dst_stride_y: u32, + dst_u: &mut [u16], + dst_stride_u: u32, + dst_v: &mut [u16], + dst_stride_v: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_010(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, width, height); + assert::valid_010(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!(unsafe { + yuv_sys::rs_I010Copy( + src_y.as_ptr(), + src_stride_y as i32, + src_u.as_ptr(), + src_stride_u as i32, + src_v.as_ptr(), + src_stride_v as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_u.as_mut_ptr(), + dst_stride_u as i32, + dst_v.as_mut_ptr(), + dst_stride_v as i32, + width as i32, + height, + ) == 0 + }); +} + +pub fn nv12_copy( + src_y: &[u8], + src_stride_y: u32, + src_uv: &[u8], + src_stride_uv: u32, + dst_y: &mut [u8], + dst_stride_y: u32, + dst_uv: &mut [u8], + dst_stride_uv: u32, + width: u32, + height: u32, + flip_y: bool, +) { + assert::valid_nv12(src_y, src_stride_y, src_uv, src_stride_uv, width, height); + assert::valid_nv12(dst_y, dst_stride_y, dst_uv, dst_stride_uv, width, height); + + let height = height as i32 * if flip_y { -1 } else { 1 }; + + assert!( + unsafe { + yuv_sys::rs_NV12Copy( + src_y.as_ptr(), + src_stride_y as i32, + src_uv.as_ptr(), + src_stride_uv as i32, + dst_y.as_mut_ptr(), + dst_stride_y as i32, + dst_uv.as_mut_ptr(), + dst_stride_uv as i32, + width as i32, + height, + ) + } == 0 + ); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_data() { + const WIDTH: usize = 160; + const HEIGHT: usize = 90; + + let dst_abgr = &mut [0u8; WIDTH * HEIGHT * 4]; + let src_y = &[0u8; WIDTH * HEIGHT]; + let src_u = &[0u8; WIDTH * HEIGHT + 1 / 2]; + let src_v = &[0u8; WIDTH * HEIGHT + 1 / 2]; + + i420_to_abgr( + src_y, + WIDTH as u32, + src_u, + WIDTH as u32 + 1 / 2, + src_v, + WIDTH as u32 + 1 / 2, + dst_abgr, + WIDTH as u32 * 4, + WIDTH as u32, + HEIGHT as u32, + false, + ); + } +} diff --git a/imgproc/src/lib.rs b/imgproc/src/lib.rs new file mode 100644 index 00000000..68b89620 --- /dev/null +++ b/imgproc/src/lib.rs @@ -0,0 +1 @@ +pub mod colorcvt; diff --git a/livekit-ffi/Cargo.toml b/livekit-ffi/Cargo.toml index 01d74323..b7cab7fd 100644 --- a/livekit-ffi/Cargo.toml +++ b/livekit-ffi/Cargo.toml @@ -20,6 +20,7 @@ tracing = ["tokio/tracing", "console-subscriber"] [dependencies] livekit = { workspace = true } soxr-sys = { path = "../soxr-sys" } +imgproc = { path = "../imgproc" } livekit-protocol = { workspace = true } tokio = { version = "1", features = ["full", "parking_lot"] } futures-util = { version = "0.3", default-features = false, features = ["sink"] } @@ -33,7 +34,6 @@ dashmap = "5.4" env_logger = "0.10" downcast-rs = "1.2" console-subscriber = { version = "0.1", features = ["parking_lot"], optional = true } -imgproc = "0.3.11" [target.'cfg(target_os = "android")'.dependencies] jni = "0.21.1" diff --git a/yuv-sys/Cargo.lock b/yuv-sys/Cargo.lock new file mode 100644 index 00000000..2cda4831 --- /dev/null +++ b/yuv-sys/Cargo.lock @@ -0,0 +1,479 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "prettyplease" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "yuv-sys" +version = "0.3.5" +dependencies = [ + "bindgen", + "cc", + "rayon", + "regex", +] diff --git a/yuv-sys/Cargo.toml b/yuv-sys/Cargo.toml new file mode 100644 index 00000000..38481573 --- /dev/null +++ b/yuv-sys/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "yuv-sys" +version = "0.3.6" +edition = "2021" +authors = ["Theo Monnom "] +license = "MIT OR Apache-2.0" +description = "libyuv bindings" + +[build-dependencies] +bindgen = "0.69" +cc = "1.0" +regex = "1" +rayon = "1.8" diff --git a/yuv-sys/build.rs b/yuv-sys/build.rs new file mode 100644 index 00000000..34a93610 --- /dev/null +++ b/yuv-sys/build.rs @@ -0,0 +1,143 @@ +use cc; +use rayon::prelude::*; +use regex::Regex; +use std::borrow::Cow; +use std::path::Path; +use std::{env, path::PathBuf}; +use std::{fs, io}; + +//const LIBYUV_REPO: &str = "https://chromium.googlesource.com/libyuv/libyuv"; +//const LIBYUV_COMMIT: &str = "af6ac82"; +const FNC_PREFIX: &str = "rs_"; + +/*fn run_git_cmd(current_dir: &PathBuf, args: &[&str]) -> ExitStatus { + Command::new("git") + .current_dir(current_dir) + .args(args) + .status() + .unwrap() +}*/ + +fn rename_symbols( + fnc_list: &[&str], + include_files: &[fs::DirEntry], + source_files: &[fs::DirEntry], +) { + // Find all occurences of the function in every header and source files + // and prefix it with FNC_PREFIX + include_files.par_iter().chain(source_files).for_each(|file| { + let mut content = fs::read_to_string(&file.path()).unwrap(); + for line in fnc_list { + let fnc = line.trim(); + if fnc.is_empty() { + continue; + } + + // Split line using space as delimiter (If there is two words, the second word is the new name instead of using prefix) + let split: Vec<&str> = fnc.split_whitespace().collect(); + let fnc = split[0]; + + let new_name = if split.len() > 1 { + split[1].to_owned() + } else { + format!("{}{}", FNC_PREFIX, fnc) + }; + + let re = Regex::new(&format!(r"\b{}\b", fnc)).unwrap(); + if let Cow::Owned(c) = re.replace_all(&content, &new_name) { + content = c + } + } + + fs::write(&file.path(), content.to_string()).unwrap(); + }); +} + +fn copy_dir(source: impl AsRef, destination: impl AsRef) -> io::Result<()> { + fs::create_dir_all(&destination)?; + for entry in fs::read_dir(source)? { + let entry = entry?; + if entry.file_type()?.is_dir() { + copy_dir(entry.path(), destination.as_ref().join(entry.file_name()))?; + } else { + fs::copy(entry.path(), destination.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} + +fn clone_if_needed(_output_dir: &PathBuf, libyuv_dir: &PathBuf) -> bool { + if libyuv_dir.exists() { + return false; // Already cloned + } + + /*let status = run_git_cmd(output_dir, &["clone", LIBYUV_REPO]); + if !status.success() { + fs::remove_dir_all(&libyuv_dir).unwrap(); + panic!("failed to clone libyuv, is git installed?"); + } + + let status = run_git_cmd(&libyuv_dir, &["checkout", LIBYUV_COMMIT]); + if !status.success() { + fs::remove_dir_all(&libyuv_dir).unwrap(); + panic!("failed to checkout to {}", LIBYUV_COMMIT); + }*/ + + if let Err(err) = copy_dir("libyuv", libyuv_dir) { + fs::remove_dir_all(&libyuv_dir).unwrap(); + panic!("failed to copy libyuv: {:?}", err); + } + + true +} + +fn main() { + let output_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let libyuv_dir = output_dir.join("libyuv"); + let include_dir = libyuv_dir.join("include"); + let source_dir = libyuv_dir.join("source"); + + let cloned = clone_if_needed(&output_dir, &libyuv_dir); + + let include_files = fs::read_dir(include_dir.join("libyuv")) + .unwrap() + .map(Result::unwrap) + .filter(|f| f.path().extension().unwrap() == "h") + .collect::>(); + + let source_files = fs::read_dir(source_dir) + .unwrap() + .map(Result::unwrap) + .filter(|f| f.path().extension().unwrap() == "cc") + .collect::>(); + + let fnc_content = fs::read_to_string("yuv_functions.txt").unwrap(); + let fnc_list = fnc_content.lines().collect::>(); + + if cloned { + // Rename symbols to avoid conflicts with other libraries + // that have libyuv statically linked (e.g libwebrtc). + rename_symbols(&fnc_list, &include_files, &source_files); + } + + cc::Build::new() + .warnings(false) + .include(libyuv_dir.join("include")) + .files(source_files.iter().map(|f| f.path())) + .compile("yuv"); + + let mut bindgen = bindgen::Builder::default() + .header(include_dir.join("libyuv.h").to_string_lossy()) + .clang_arg(format!("-I{}", include_dir.to_str().unwrap())); + + for fnc in fnc_list { + let new_name = format!("{}{}", FNC_PREFIX, fnc); + bindgen = bindgen.allowlist_function(&new_name); + } + + let output = bindgen.generate().unwrap(); + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("yuv.rs"); + output.write_to_file(out_path).unwrap(); + + println!("cargo:rerun-if-changed=yuv_functions.txt"); +} diff --git a/yuv-sys/libyuv b/yuv-sys/libyuv new file mode 160000 index 00000000..3a0ad00e --- /dev/null +++ b/yuv-sys/libyuv @@ -0,0 +1 @@ +Subproject commit 3a0ad00ed34afe3a43eb742579d53e9e7c597ae3 diff --git a/yuv-sys/src/lib.rs b/yuv-sys/src/lib.rs new file mode 100644 index 00000000..6839d5ea --- /dev/null +++ b/yuv-sys/src/lib.rs @@ -0,0 +1,6 @@ +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +include!(concat!(env!("OUT_DIR"), "/yuv.rs")); diff --git a/yuv-sys/yuv_functions.txt b/yuv-sys/yuv_functions.txt new file mode 100644 index 00000000..cecd256b --- /dev/null +++ b/yuv-sys/yuv_functions.txt @@ -0,0 +1,1193 @@ +NAME##ToYRow_C rs_##NAME##ToYRow_C +NAME##ToYJRow_C rs_##NAME##ToYJRow_C +NAME##ToUVRow_C rs_##NAME##ToUVRow_C +NAME##ToUVJRow_C rs_##NAME##ToUVJRow_C +kYuv##name##Constants +kYvu##name##Constants +ScalePlane +ScalePlane_16 +ScalePlane_12 +I420Scale +I420Scale_16 +I420Scale_12 +I444Scale +I444Scale_16 +I444Scale_12 +I422Scale +I422Scale_16 +I422Scale_12 +NV12Scale +Scale +CopyPlane +CopyPlane_16 +Convert16To8Plane +Convert8To16Plane +SetPlane +DetilePlane +DetilePlane_16 +DetileSplitUVPlane +DetileToYUY2 +SplitUVPlane +MergeUVPlane +SplitUVPlane_16 +MergeUVPlane_16 +ConvertToMSBPlane_16 +ConvertToLSBPlane_16 +HalfMergeUVPlane +SwapUVPlane +SplitRGBPlane +MergeRGBPlane +SplitARGBPlane +MergeARGBPlane +MergeXR30Plane +MergeAR64Plane +MergeARGB16To8Plane +I400ToI400 +I422Copy +I444Copy +I210Copy +I410Copy +NV12Copy +NV21Copy +YUY2ToI422 +UYVYToI422 +YUY2ToNV12 +UYVYToNV12 +NV21ToNV12 +YUY2ToY +UYVYToY +I420ToI400 +I420Mirror +I400Mirror +NV12Mirror +ARGBMirror +RGB24Mirror +MirrorPlane +MirrorUVPlane +RAWToRGB24 +I420Rect +ARGBRect +ARGBGrayTo +ARGBGray +ARGBSepia +ARGBColorMatrix +RGBColorMatrix +ARGBColorTable +RGBColorTable +ARGBLumaColorTable +ARGBPolynomial +HalfFloatPlane +ByteToFloat +ARGBQuantize +ARGBCopy +ARGBCopyAlpha +ARGBExtractAlpha +ARGBCopyYToAlpha +ARGBBlend +BlendPlane +I420Blend +ARGBMultiply +ARGBAdd +ARGBSubtract +I422ToYUY2 +I422ToUYVY +ARGBAttenuate +ARGBUnattenuate +ARGBComputeCumulativeSum +ARGBBlur +GaussPlane_F32 +ARGBShade +InterpolatePlane +InterpolatePlane_16 +ARGBInterpolate +I420Interpolate +ARGBAffineRow_C +ARGBAffineRow_SSE2 +ARGBShuffle +AR64Shuffle +ARGBSobelToPlane +ARGBSobel +ARGBSobelXY +ARGBScale +ARGBScaleClip +YUVToARGBScaleClip +HashDjb2 +ComputeHammingDistance +ARGBDetect +ComputeSumSquareError +ComputeSumSquareErrorPlane +SumSquareErrorToPsnr +CalcFramePsnr +I420Psnr +CalcFrameSsim +I420Ssim +I420ToARGB +I420ToABGR +J420ToARGB +J420ToABGR +H420ToARGB +H420ToABGR +U420ToARGB +U420ToABGR +I422ToARGB +I422ToABGR +J422ToARGB +J422ToABGR +H422ToARGB +H422ToABGR +U422ToARGB +U422ToABGR +I444ToARGB +I444ToABGR +J444ToARGB +J444ToABGR +H444ToARGB +H444ToABGR +U444ToARGB +U444ToABGR +I444ToRGB24 +I444ToRAW +I010ToARGB +I010ToABGR +H010ToARGB +H010ToABGR +U010ToARGB +U010ToABGR +I210ToARGB +I210ToABGR +H210ToARGB +H210ToABGR +U210ToARGB +U210ToABGR +I420AlphaToARGB +I420AlphaToABGR +I422AlphaToARGB +I422AlphaToABGR +I444AlphaToARGB +I444AlphaToABGR +I400ToARGB +J400ToARGB +NV12ToARGB +NV21ToARGB +NV12ToABGR +NV21ToABGR +NV12ToRGB24 +NV21ToRGB24 +NV21ToYUV24 +NV12ToRAW +NV21ToRAW +YUY2ToARGB +UYVYToARGB +I010ToAR30 +H010ToAR30 +I010ToAB30 +H010ToAB30 +U010ToAR30 +U010ToAB30 +I210ToAR30 +I210ToAB30 +H210ToAR30 +H210ToAB30 +U210ToAR30 +U210ToAB30 +BGRAToARGB +ABGRToARGB +RGBAToARGB +RGB24ToARGB +RAWToARGB +RAWToRGBA +RGB565ToARGB +ARGB1555ToARGB +ARGB4444ToARGB +AR30ToARGB +AR30ToABGR +AR30ToAB30 +AR64ToARGB +AB64ToARGB +AR64ToAB64 +MJPGToARGB +Android420ToARGB +Android420ToABGR +NV12ToRGB565 +I422ToBGRA +I422ToRGBA +I420ToBGRA +I420ToRGBA +I420ToRGB24 +I420ToRAW +H420ToRGB24 +H420ToRAW +J420ToRGB24 +J420ToRAW +I422ToRGB24 +I422ToRAW +I420ToRGB565 +J420ToRGB565 +H420ToRGB565 +I422ToRGB565 +I420ToRGB565Dither +I420ToARGB1555 +I420ToARGB4444 +I420ToAR30 +I420ToAB30 +H420ToAR30 +H420ToAB30 +I420ToARGBMatrix +I422ToARGBMatrix +I444ToARGBMatrix +I444ToRGB24Matrix +I010ToAR30Matrix +I210ToAR30Matrix +I410ToAR30Matrix +I010ToARGBMatrix +I012ToAR30Matrix +I012ToARGBMatrix +I210ToARGBMatrix +I410ToARGBMatrix +P010ToARGBMatrix +P210ToARGBMatrix +P010ToAR30Matrix +P210ToAR30Matrix +I420AlphaToARGBMatrix +I422AlphaToARGBMatrix +I444AlphaToARGBMatrix +I010AlphaToARGBMatrix +I210AlphaToARGBMatrix +I410AlphaToARGBMatrix +NV12ToARGBMatrix +NV21ToARGBMatrix +NV12ToRGB565Matrix +NV12ToRGB24Matrix +NV21ToRGB24Matrix +Android420ToARGBMatrix +I422ToRGBAMatrix +I420ToRGBAMatrix +I420ToRGB24Matrix +I422ToRGB24Matrix +I420ToRGB565Matrix +I422ToRGB565Matrix +I420ToAR30Matrix +I400ToARGBMatrix +I420ToARGBMatrixFilter +I422ToARGBMatrixFilter +I422ToRGB24MatrixFilter +I420ToRGB24MatrixFilter +I010ToAR30MatrixFilter +I210ToAR30MatrixFilter +I010ToARGBMatrixFilter +I210ToARGBMatrixFilter +I420AlphaToARGBMatrixFilter +I422AlphaToARGBMatrixFilter +I010AlphaToARGBMatrixFilter +I210AlphaToARGBMatrixFilter +P010ToARGBMatrixFilter +P210ToARGBMatrixFilter +P010ToAR30MatrixFilter +P210ToAR30MatrixFilter +ConvertToARGB +I420Rotate +I422Rotate +I444Rotate +I010Rotate +I210Rotate +I410Rotate +NV12ToI420Rotate +Android420ToI420Rotate +RotatePlane +RotatePlane90 +RotatePlane180 +RotatePlane270 +RotatePlane_16 +SplitRotateUV +SplitRotateUV90 +SplitRotateUV180 +SplitRotateUV270 +TransposePlane +SplitTransposeUV +ARGBToBGRA +ARGBToABGR +ARGBToRGBA +ABGRToAR30 +ARGBToAR30 +ARGBToRGB24 +ARGBToRAW +ARGBToRGB565 +ARGBToRGB565Dither +ARGBToARGB1555 +ARGBToARGB4444 +ARGBToI444 +ARGBToAR64 +ARGBToAB64 +ARGBToI422 +ARGBToJ420 +ARGBToJ422 +ARGBToJ400 +ABGRToJ420 +ABGRToJ422 +ABGRToJ400 +RGBAToJ400 +ARGBToI400 +ARGBToG +ARGBToNV12 +ARGBToNV21 +ABGRToNV12 +ABGRToNV21 +ARGBToYUY2 +ARGBToUYVY +RAWToJNV21 +UVScale +UVScale_16 +I420ToI010 +I420ToI012 +I420ToI422 +I420ToI444 +I400Copy +I420ToNV12 +I420ToNV21 +I420ToYUY2 +I420ToUYVY +ConvertFromI420 +I444ToI420 +I444ToNV12 +I444ToNV21 +I422ToI420 +I422ToI444 +I422ToI210 +MM21ToNV12 +MM21ToI420 +MM21ToYUY2 +MT2TToP010 +I422ToNV21 +I420Copy +I010Copy +I010ToI420 +I210ToI420 +I210ToI422 +I410ToI420 +I410ToI444 +I012ToI420 +I212ToI422 +I212ToI420 +I412ToI444 +I412ToI420 +I410ToI010 +I210ToI010 +I010ToI410 +I210ToI410 +I010ToP010 +I210ToP210 +I012ToP012 +I212ToP212 +I400ToI420 +I400ToNV21 +NV12ToI420 +NV21ToI420 +NV12ToNV24 +NV16ToNV24 +P010ToI010 +P012ToI012 +P010ToP410 +P210ToP410 +YUY2ToI420 +UYVYToI420 +AYUVToNV12 +AYUVToNV21 +Android420ToI420 +ARGBToI420 +ARGBToI420Alpha +BGRAToI420 +ABGRToI420 +RGBAToI420 +RGB24ToI420 +RGB24ToJ420 +RAWToI420 +RAWToJ420 +RGB565ToI420 +ARGB1555ToI420 +ARGB4444ToI420 +RGB24ToJ400 +RAWToJ400 +MJPGToI420 +MJPGToNV21 +MJPGToNV12 +MJPGSize +ConvertToI420 +ARGBRotate +RGBScale +DetileToYUY2_Any_SSE2 +DetileSplitUVRow_Any_SSSE3 +DetileRow_16_Any_AVX +DetileRow_16_Any_SSE2 +DetileRow_Any_SSE2 +UYVYToUVRow_Any_SSE2 +YUY2ToUVRow_Any_SSE2 +UYVYToUVRow_Any_AVX2 +RGBAToUVRow_Any_SSSE3 +ABGRToUVRow_Any_SSSE3 +BGRAToUVRow_Any_SSSE3 +ARGBToUVRow_Any_SSSE3 +ABGRToUVJRow_Any_SSSE3 +ARGBToUVJRow_Any_SSSE3 +ABGRToUVJRow_Any_AVX2 +ARGBToUVJRow_Any_AVX2 +ABGRToUVRow_Any_AVX2 +ARGBToUVRow_Any_AVX2 +SplitARGBRow_Any_AVX2 +SplitARGBRow_Any_SSSE3 +SplitARGBRow_Any_SSE2 +SplitXRGBRow_Any_AVX2 +SplitXRGBRow_Any_SSSE3 +SplitXRGBRow_Any_SSE2 +SplitRGBRow_Any_SSSE3 +SplitUVRow_16_Any_AVX2 +UYVYToUV422Row_Any_SSE2 +YUY2ToUV422Row_Any_SSE2 +UYVYToUV422Row_Any_AVX2 +YUY2ToUV422Row_Any_AVX2 +ARGBToUV444Row_Any_SSSE3 +SplitUVRow_Any_AVX2 +SplitUVRow_Any_SSE2 +SetRow_Any_X86 +RGB24MirrorRow_Any_SSSE3 +ARGBMirrorRow_Any_SSE2 +ARGBMirrorRow_Any_AVX2 +MirrorUVRow_Any_SSSE3 +MirrorUVRow_Any_AVX2 +MirrorRow_Any_SSSE3 +MirrorRow_Any_AVX2 +InterpolateRow_16To8_Any_AVX2 +InterpolateRow_Any_SSSE3 +InterpolateRow_Any_AVX2 +UYVYToARGBRow_Any_AVX2 +ScalePlaneDown2_16To8 +J400ToARGBRow_SSE2 +RGB24ToARGBRow_SSSE3 +RAWToARGBRow_SSSE3 +RAWToRGBARow_SSSE3 +RAWToRGB24Row_SSSE3 +RGB565ToARGBRow_SSE2 +ARGB1555ToARGBRow_SSE2 +ARGB4444ToARGBRow_SSE2 +ARGBToRGB24Row_SSSE3 +ARGBToRAWRow_SSSE3 +ARGBToRGB24Row_AVX2 +ARGBToRAWRow_AVX2 +ARGBToRGB565Row_SSE2 +ARGBToRGB565DitherRow_SSE2 +ARGBToRGB565DitherRow_AVX2 +ARGBToARGB1555Row_SSE2 +ARGBToARGB4444Row_SSE2 +ARGBToAR30Row_SSSE3 +ABGRToAR30Row_SSSE3 +ARGBToAR30Row_AVX2 +ABGRToAR30Row_AVX2 +ARGBToAR64Row_SSSE3 +ARGBToAB64Row_SSSE3 +AR64ToARGBRow_SSSE3 +AB64ToARGBRow_SSSE3 +ARGBToAR64Row_AVX2 +ARGBToAB64Row_AVX2 +AR64ToARGBRow_AVX2 +AB64ToARGBRow_AVX2 +ARGBToYRow_SSSE3 +ARGBToYJRow_SSSE3 +ABGRToYJRow_SSSE3 +RGBAToYJRow_SSSE3 +ARGBToYRow_AVX2 +ABGRToYRow_AVX2 +ARGBToYJRow_AVX2 +ABGRToYJRow_AVX2 +RGBAToYJRow_AVX2 +ARGBToUVRow_SSSE3 +ARGBToUVRow_AVX2 +ABGRToUVRow_AVX2 +ARGBToUVJRow_AVX2 +ABGRToUVJRow_AVX2 +ARGBToUVJRow_SSSE3 +ABGRToUVJRow_SSSE3 +ARGBToUV444Row_SSSE3 +BGRAToYRow_SSSE3 +BGRAToUVRow_SSSE3 +ABGRToYRow_SSSE3 +RGBAToYRow_SSSE3 +ABGRToUVRow_SSSE3 +RGBAToUVRow_SSSE3 +I444ToARGBRow_SSSE3 +I444AlphaToARGBRow_SSSE3 +I422ToRGB24Row_SSSE3 +I444ToRGB24Row_SSSE3 +I422ToARGBRow_SSSE3 +I422ToAR30Row_SSSE3 +I210ToARGBRow_SSSE3 +I212ToARGBRow_SSSE3 +I210ToAR30Row_SSSE3 +I212ToAR30Row_SSSE3 +I410ToARGBRow_SSSE3 +I210AlphaToARGBRow_SSSE3 +I410AlphaToARGBRow_SSSE3 +I410ToAR30Row_SSSE3 +I422AlphaToARGBRow_SSSE3 +NV12ToARGBRow_SSSE3 +NV21ToARGBRow_SSSE3 +YUY2ToARGBRow_SSSE3 +UYVYToARGBRow_SSSE3 +P210ToARGBRow_SSSE3 +P410ToARGBRow_SSSE3 +P210ToAR30Row_SSSE3 +P410ToAR30Row_SSSE3 +I422ToRGBARow_SSSE3 +I444ToARGBRow_AVX2 +I422ToARGBRow_AVX2 +I422ToAR30Row_AVX2 +I210ToARGBRow_AVX2 +I212ToARGBRow_AVX2 +I210ToAR30Row_AVX2 +I212ToAR30Row_AVX2 +I410ToARGBRow_AVX2 +I210AlphaToARGBRow_AVX2 +I410AlphaToARGBRow_AVX2 +I410ToAR30Row_AVX2 +I444AlphaToARGBRow_AVX2 +I422AlphaToARGBRow_AVX2 +I422ToRGBARow_AVX2 +NV12ToARGBRow_AVX2 +NV21ToARGBRow_AVX2 +YUY2ToARGBRow_AVX2 +UYVYToARGBRow_AVX2 +P210ToARGBRow_AVX2 +P410ToARGBRow_AVX2 +P210ToAR30Row_AVX2 +P410ToAR30Row_AVX2 +I400ToARGBRow_SSE2 +I400ToARGBRow_AVX2 +MirrorRow_SSSE3 +MirrorRow_AVX2 +MirrorUVRow_SSSE3 +MirrorUVRow_AVX2 +MirrorSplitUVRow_SSSE3 +RGB24MirrorRow_SSSE3 +ARGBMirrorRow_SSE2 +ARGBMirrorRow_AVX2 +SplitUVRow_AVX2 +SplitUVRow_SSE2 +DetileRow_SSE2 +DetileRow_16_SSE2 +DetileRow_16_AVX +DetileToYUY2_SSE2 +DetileSplitUVRow_SSSE3 +MergeUVRow_AVX2 +MergeUVRow_SSE2 +MergeUVRow_16_AVX2 +SplitUVRow_16_AVX2 +MultiplyRow_16_AVX2 +DivideRow_16_AVX2 +Convert16To8Row_SSSE3 +Convert16To8Row_AVX2 +Convert8To16Row_SSE2 +Convert8To16Row_AVX2 +SplitRGBRow_SSSE3 +MergeRGBRow_SSSE3 +MergeARGBRow_SSE2 +MergeXRGBRow_SSE2 +MergeARGBRow_AVX2 +MergeXRGBRow_AVX2 +SplitARGBRow_SSE2 +SplitXRGBRow_SSE2 +SplitARGBRow_SSSE3 +SplitXRGBRow_SSSE3 +SplitARGBRow_AVX2 +SplitXRGBRow_AVX2 +MergeXR30Row_AVX2 +MergeAR64Row_AVX2 +MergeXR64Row_AVX2 +MergeARGB16To8Row_AVX2 +MergeXRGB16To8Row_AVX2 +CopyRow_SSE2 +CopyRow_AVX +CopyRow_ERMS +ARGBCopyAlphaRow_SSE2 +ARGBCopyAlphaRow_AVX2 +ARGBExtractAlphaRow_SSE2 +ARGBExtractAlphaRow_AVX2 +ARGBCopyYToAlphaRow_SSE2 +ARGBCopyYToAlphaRow_AVX2 +SetRow_X86 +SetRow_ERMS +ARGBSetRow_X86 +YUY2ToYRow_SSE2 +YUY2ToNVUVRow_SSE2 +YUY2ToUVRow_SSE2 +YUY2ToUV422Row_SSE2 +UYVYToYRow_SSE2 +UYVYToUVRow_SSE2 +UYVYToUV422Row_SSE2 +YUY2ToYRow_AVX2 +YUY2ToNVUVRow_AVX2 +YUY2ToUVRow_AVX2 +YUY2ToUV422Row_AVX2 +UYVYToYRow_AVX2 +UYVYToUVRow_AVX2 +UYVYToUV422Row_AVX2 +ARGBBlendRow_SSSE3 +BlendPlaneRow_SSSE3 +BlendPlaneRow_AVX2 +ARGBAttenuateRow_SSSE3 +ARGBAttenuateRow_AVX2 +ARGBUnattenuateRow_SSE2 +ARGBUnattenuateRow_AVX2 +ARGBGrayRow_SSSE3 +ARGBSepiaRow_SSSE3 +ARGBColorMatrixRow_SSSE3 +ARGBQuantizeRow_SSE2 +ARGBShadeRow_SSE2 +ARGBMultiplyRow_SSE2 +ARGBMultiplyRow_AVX2 +ARGBAddRow_SSE2 +ARGBAddRow_AVX2 +ARGBSubtractRow_SSE2 +ARGBSubtractRow_AVX2 +SobelXRow_SSE2 +SobelYRow_SSE2 +SobelRow_SSE2 +SobelToPlaneRow_SSE2 +SobelXYRow_SSE2 +ComputeCumulativeSumRow_SSE2 +CumulativeSumToAverageRow_SSE2 +InterpolateRow_SSSE3 +InterpolateRow_AVX2 +ARGBShuffleRow_SSSE3 +ARGBShuffleRow_AVX2 +I422ToYUY2Row_SSE2 +I422ToUYVYRow_SSE2 +I422ToYUY2Row_AVX2 +I422ToUYVYRow_AVX2 +ARGBPolynomialRow_SSE2 +ARGBPolynomialRow_AVX2 +HalfFloatRow_SSE2 +HalfFloatRow_AVX2 +ARGBColorTableRow_X86 +RGBColorTableRow_X86 +ARGBLumaColorTableRow_SSSE3 +NV21ToYUV24Row_SSSE3 +NV21ToYUV24Row_AVX2 +SwapUVRow_SSSE3 +SwapUVRow_AVX2 +HalfMergeUVRow_SSSE3 +HalfMergeUVRow_AVX2 +ClampFloatToZero_SSE2 +MergeARGBRow_Any_SSE2 +MergeARGBRow_Any_AVX2 +I444AlphaToARGBRow_Any_SSSE3 +I444AlphaToARGBRow_Any_AVX2 +I422AlphaToARGBRow_Any_SSSE3 +I422AlphaToARGBRow_Any_AVX2 +I210AlphaToARGBRow_Any_SSSE3 +I210AlphaToARGBRow_Any_AVX2 +I410AlphaToARGBRow_Any_SSSE3 +I410AlphaToARGBRow_Any_AVX2 +MergeAR64Row_Any_AVX2 +MergeARGB16To8Row_Any_AVX2 +MergeRGBRow_Any_SSSE3 +MergeXRGBRow_Any_SSE2 +MergeXRGBRow_Any_AVX2 +I422ToYUY2Row_Any_SSE2 +I422ToUYVYRow_Any_SSE2 +I422ToYUY2Row_Any_AVX2 +I422ToUYVYRow_Any_AVX2 +BlendPlaneRow_Any_AVX2 +BlendPlaneRow_Any_SSSE3 +I422ToARGBRow_Any_SSSE3 +I422ToRGBARow_Any_SSSE3 +I422ToARGB4444Row_Any_SSSE3 +I422ToARGB1555Row_Any_SSSE3 +I422ToRGB565Row_Any_SSSE3 +I422ToRGB24Row_Any_SSSE3 +I422ToAR30Row_Any_SSSE3 +I422ToAR30Row_Any_AVX2 +I444ToARGBRow_Any_SSSE3 +I444ToRGB24Row_Any_SSSE3 +I422ToRGB24Row_Any_AVX2 +I422ToARGBRow_Any_AVX2 +I422ToRGBARow_Any_AVX2 +I444ToARGBRow_Any_AVX2 +I444ToRGB24Row_Any_AVX2 +I422ToARGB4444Row_Any_AVX2 +I422ToARGB1555Row_Any_AVX2 +I422ToRGB565Row_Any_AVX2 +I210ToAR30Row_Any_SSSE3 +I210ToARGBRow_Any_SSSE3 +I210ToARGBRow_Any_AVX2 +I210ToAR30Row_Any_AVX2 +I410ToAR30Row_Any_SSSE3 +I410ToARGBRow_Any_SSSE3 +I410ToARGBRow_Any_AVX2 +I410ToAR30Row_Any_AVX2 +I212ToAR30Row_Any_SSSE3 +I212ToARGBRow_Any_SSSE3 +I212ToARGBRow_Any_AVX2 +I212ToAR30Row_Any_AVX2 +MergeXR30Row_Any_AVX2 +MergeXR64Row_Any_AVX2 +MergeXRGB16To8Row_Any_AVX2 +MergeUVRow_Any_SSE2 +MergeUVRow_Any_AVX2 +NV21ToYUV24Row_Any_SSSE3 +NV21ToYUV24Row_Any_AVX2 +ARGBMultiplyRow_Any_SSE2 +ARGBAddRow_Any_SSE2 +ARGBSubtractRow_Any_SSE2 +ARGBMultiplyRow_Any_AVX2 +ARGBAddRow_Any_AVX2 +ARGBSubtractRow_Any_AVX2 +SobelRow_Any_SSE2 +SobelToPlaneRow_Any_SSE2 +SobelXYRow_Any_SSE2 +YUY2ToNVUVRow_Any_SSE2 +YUY2ToNVUVRow_Any_AVX2 +NV12ToARGBRow_Any_SSSE3 +NV12ToARGBRow_Any_AVX2 +NV21ToARGBRow_Any_SSSE3 +NV21ToARGBRow_Any_AVX2 +NV12ToRGB24Row_Any_SSSE3 +NV21ToRGB24Row_Any_SSSE3 +NV12ToRGB24Row_Any_AVX2 +NV21ToRGB24Row_Any_AVX2 +NV12ToRGB565Row_Any_SSSE3 +NV12ToRGB565Row_Any_AVX2 +P210ToAR30Row_Any_SSSE3 +P210ToARGBRow_Any_SSSE3 +P210ToARGBRow_Any_AVX2 +P210ToAR30Row_Any_AVX2 +P410ToAR30Row_Any_SSSE3 +P410ToARGBRow_Any_SSSE3 +P410ToARGBRow_Any_AVX2 +P410ToAR30Row_Any_AVX2 +MergeUVRow_16_Any_AVX2 +CopyRow_Any_AVX +CopyRow_Any_SSE2 +ARGBToRGB24Row_Any_SSSE3 +ARGBToRAWRow_Any_SSSE3 +ARGBToRGB565Row_Any_SSE2 +ARGBToARGB1555Row_Any_SSE2 +ARGBToARGB4444Row_Any_SSE2 +ARGBToRGB24Row_Any_AVX2 +ARGBToRAWRow_Any_AVX2 +ABGRToAR30Row_Any_SSSE3 +ARGBToAR30Row_Any_SSSE3 +ABGRToAR30Row_Any_AVX2 +ARGBToAR30Row_Any_AVX2 +J400ToARGBRow_Any_SSE2 +RGB24ToARGBRow_Any_SSSE3 +RAWToARGBRow_Any_SSSE3 +RGB565ToARGBRow_Any_SSE2 +ARGB1555ToARGBRow_Any_SSE2 +ARGB4444ToARGBRow_Any_SSE2 +RAWToRGBARow_Any_SSSE3 +RAWToRGB24Row_Any_SSSE3 +ARGBToYRow_Any_AVX2 +ABGRToYRow_Any_AVX2 +ARGBToYJRow_Any_AVX2 +ABGRToYJRow_Any_AVX2 +RGBAToYJRow_Any_AVX2 +UYVYToYRow_Any_AVX2 +YUY2ToYRow_Any_AVX2 +ARGBToYRow_Any_SSSE3 +BGRAToYRow_Any_SSSE3 +ABGRToYRow_Any_SSSE3 +RGBAToYRow_Any_SSSE3 +YUY2ToYRow_Any_SSE2 +UYVYToYRow_Any_SSE2 +ARGBToYJRow_Any_SSSE3 +ABGRToYJRow_Any_SSSE3 +RGBAToYJRow_Any_SSSE3 +RGB24ToYJRow_Any_AVX2 +RGB24ToYJRow_Any_SSSE3 +RAWToYJRow_Any_AVX2 +RAWToYJRow_Any_SSSE3 +SwapUVRow_Any_SSSE3 +SwapUVRow_Any_AVX2 +ARGBAttenuateRow_Any_SSSE3 +ARGBUnattenuateRow_Any_SSE2 +ARGBAttenuateRow_Any_AVX2 +ARGBUnattenuateRow_Any_AVX2 +ARGBExtractAlphaRow_Any_SSE2 +ARGBExtractAlphaRow_Any_AVX2 +ARGBCopyAlphaRow_Any_AVX2 +ARGBCopyAlphaRow_Any_SSE2 +ARGBCopyYToAlphaRow_Any_AVX2 +ARGBCopyYToAlphaRow_Any_SSE2 +I400ToARGBRow_Any_SSE2 +I400ToARGBRow_Any_AVX2 +ARGBToRGB565DitherRow_Any_SSE2 +ARGBToRGB565DitherRow_Any_AVX2 +ARGBShuffleRow_Any_SSSE3 +ARGBShuffleRow_Any_AVX2 +ARGBToAR64Row_Any_SSSE3 +ARGBToAB64Row_Any_SSSE3 +AR64ToARGBRow_Any_SSSE3 +AB64ToARGBRow_Any_SSSE3 +ARGBToAR64Row_Any_AVX2 +ARGBToAB64Row_Any_AVX2 +AR64ToARGBRow_Any_AVX2 +AB64ToARGBRow_Any_AVX2 +Convert16To8Row_Any_SSSE3 +Convert16To8Row_Any_AVX2 +Convert8To16Row_Any_SSE2 +Convert8To16Row_Any_AVX2 +MultiplyRow_16_Any_AVX2 +DivideRow_16_Any_AVX2 +HalfFloatRow_Any_SSE2 +HalfFloatRow_Any_AVX2 +YUY2ToARGBRow_Any_SSSE3 +UYVYToARGBRow_Any_SSSE3 +YUY2ToARGBRow_Any_AVX2 +ScaleRowUp2_Linear_Any_C +ScaleRowUp2_Linear_16_Any_C +ScaleRowUp2_Bilinear_Any_C +ScaleRowUp2_Bilinear_16_Any_C +ScaleUVRowUp2_Linear_Any_C +ScaleUVRowUp2_Linear_16_Any_C +ScaleUVRowUp2_Bilinear_Any_C +ScaleUVRowUp2_Bilinear_16_Any_C +RGB24ToARGBRow_C +RAWToARGBRow_C +RAWToRGBARow_C +RAWToRGB24Row_C +RGB565ToARGBRow_C +ARGB1555ToARGBRow_C +ARGB4444ToARGBRow_C +AR30ToARGBRow_C +AR30ToABGRRow_C +AR30ToAB30Row_C +ARGBToRGB24Row_C +ARGBToRAWRow_C +ARGBToRGB565Row_C +ARGBToRGB565DitherRow_C +ARGBToARGB1555Row_C +ARGBToARGB4444Row_C +ABGRToAR30Row_C +ARGBToAR30Row_C +ARGBToAR64Row_C +ARGBToAB64Row_C +AR64ToARGBRow_C +AB64ToARGBRow_C +AR64ShuffleRow_C +ARGBToYRow_C +ARGBToUVRow_C +BGRAToYRow_C +BGRAToUVRow_C +ABGRToYRow_C +ABGRToUVRow_C +RGBAToYRow_C +RGBAToUVRow_C +RGB24ToYRow_C +RGB24ToUVRow_C +RAWToYRow_C +RAWToUVRow_C +ARGBToYJRow_C +ARGBToUVJRow_C +ABGRToYJRow_C +ABGRToUVJRow_C +RGBAToYJRow_C +RGBAToUVJRow_C +RGB24ToYJRow_C +RGB24ToUVJRow_C +RAWToYJRow_C +RAWToUVJRow_C +RGB565ToYRow_C +ARGB1555ToYRow_C +ARGB4444ToYRow_C +RGB565ToUVRow_C +ARGB1555ToUVRow_C +ARGB4444ToUVRow_C +ARGBToUV444Row_C +ARGBGrayRow_C +ARGBSepiaRow_C +ARGBColorMatrixRow_C +ARGBColorTableRow_C +RGBColorTableRow_C +ARGBQuantizeRow_C +ARGBShadeRow_C +ARGBMultiplyRow_C +ARGBAddRow_C +ARGBSubtractRow_C +SobelXRow_C +SobelYRow_C +SobelRow_C +SobelToPlaneRow_C +SobelXYRow_C +J400ToARGBRow_C +I444ToARGBRow_C +I444ToRGB24Row_C +I422ToARGBRow_C +I210ToARGBRow_C +I410ToARGBRow_C +I210AlphaToARGBRow_C +I410AlphaToARGBRow_C +I212ToARGBRow_C +I210ToAR30Row_C +I212ToAR30Row_C +I410ToAR30Row_C +P210ToARGBRow_C +P410ToARGBRow_C +P210ToAR30Row_C +P410ToAR30Row_C +I422ToAR30Row_C +I444AlphaToARGBRow_C +I422AlphaToARGBRow_C +I422ToRGB24Row_C +I422ToARGB4444Row_C +I422ToARGB1555Row_C +I422ToRGB565Row_C +NV12ToARGBRow_C +NV21ToARGBRow_C +NV12ToRGB24Row_C +NV21ToRGB24Row_C +NV12ToRGB565Row_C +YUY2ToARGBRow_C +UYVYToARGBRow_C +I422ToRGBARow_C +I400ToARGBRow_C +MirrorRow_C +MirrorRow_16_C +MirrorUVRow_C +MirrorSplitUVRow_C +ARGBMirrorRow_C +RGB24MirrorRow_C +SplitUVRow_C +MergeUVRow_C +DetileRow_C +DetileRow_16_C +DetileSplitUVRow_C +DetileToYUY2_C +UnpackMT2T_C +SplitRGBRow_C +MergeRGBRow_C +SplitARGBRow_C +MergeARGBRow_C +MergeXR30Row_C +MergeAR64Row_C +MergeARGB16To8Row_C +MergeXR64Row_C +MergeXRGB16To8Row_C +SplitXRGBRow_C +MergeXRGBRow_C +MergeUVRow_16_C +SplitUVRow_16_C +MultiplyRow_16_C +DivideRow_16_C +Convert16To8Row_C +Convert8To16Row_C +CopyRow_C +CopyRow_16_C +SetRow_C +ARGBSetRow_C +YUY2ToUVRow_C +YUY2ToNVUVRow_C +YUY2ToUV422Row_C +YUY2ToYRow_C +UYVYToUVRow_C +UYVYToUV422Row_C +UYVYToYRow_C +ARGBBlendRow_C +BlendPlaneRow_C +ARGBAttenuateRow_C +ARGBUnattenuateRow_C +ComputeCumulativeSumRow_C +CumulativeSumToAverageRow_C +InterpolateRow_C +InterpolateRow_16_C +InterpolateRow_16To8_C +ARGBShuffleRow_C +I422ToYUY2Row_C +I422ToUYVYRow_C +ARGBPolynomialRow_C +HalfFloatRow_C +ByteToFloatRow_C +ARGBLumaColorTableRow_C +ARGBCopyAlphaRow_C +ARGBExtractAlphaRow_C +ARGBCopyYToAlphaRow_C +ScaleSumSamples_C +ScaleMaxSamples_C +ScaleSamples_C +GaussRow_C +GaussCol_C +GaussRow_F32_C +GaussCol_F32_C +NV21ToYUV24Row_C +AYUVToUVRow_C +AYUVToVURow_C +AYUVToYRow_C +SwapUVRow_C +HalfMergeUVRow_C +kYuvI601Constants +kYvuI601Constants +kYuvJPEGConstants +kYvuJPEGConstants +kYuvH709Constants +kYvuH709Constants +kYuvF709Constants +kYvuF709Constants +kYuv2020Constants +kYvu2020Constants +kYuvV2020Constants +kYvuV2020Constants +fixed_invtbl8 +YUY2ToUVRow_Any_AVX2 +ScaleRowDown2_Any_SSSE3 +ScaleRowDown2Linear_Any_SSSE3 +ScaleRowDown2Box_Any_SSSE3 +ScaleRowDown2Box_Odd_SSSE3 +ScaleUVRowDown2Box_Any_SSSE3 +ScaleUVRowDown2Box_Any_AVX2 +ScaleRowDown2_Any_AVX2 +ScaleRowDown2Linear_Any_AVX2 +ScaleRowDown2Box_Any_AVX2 +ScaleRowDown2Box_Odd_AVX2 +ScaleRowDown4_Any_SSSE3 +ScaleRowDown4Box_Any_SSSE3 +ScaleRowDown4_Any_AVX2 +ScaleRowDown4Box_Any_AVX2 +ScaleRowDown34_Any_SSSE3 +ScaleRowDown34_0_Box_Any_SSSE3 +ScaleRowDown34_1_Box_Any_SSSE3 +ScaleRowDown38_Any_SSSE3 +ScaleRowDown38_3_Box_Any_SSSE3 +ScaleRowDown38_2_Box_Any_SSSE3 +ScaleARGBRowDown2_Any_SSE2 +ScaleARGBRowDown2Linear_Any_SSE2 +ScaleARGBRowDown2Box_Any_SSE2 +ScaleARGBRowDownEven_Any_SSE2 +ScaleARGBRowDownEvenBox_Any_SSE2 +ScaleAddRow_Any_SSE2 +ScaleAddRow_Any_AVX2 +ScaleRowUp2_Linear_Any_SSE2 +ScaleRowUp2_Linear_Any_SSSE3 +ScaleRowUp2_Linear_12_Any_SSSE3 +ScaleRowUp2_Linear_16_Any_SSE2 +ScaleRowUp2_Linear_Any_AVX2 +ScaleRowUp2_Linear_12_Any_AVX2 +ScaleRowUp2_Linear_16_Any_AVX2 +ScaleRowUp2_Bilinear_Any_SSE2 +ScaleRowUp2_Bilinear_12_Any_SSSE3 +ScaleRowUp2_Bilinear_16_Any_SSE2 +ScaleRowUp2_Bilinear_Any_SSSE3 +ScaleRowUp2_Bilinear_Any_AVX2 +ScaleRowUp2_Bilinear_12_Any_AVX2 +ScaleRowUp2_Bilinear_16_Any_AVX2 +ScaleUVRowUp2_Linear_Any_SSSE3 +ScaleUVRowUp2_Linear_Any_AVX2 +ScaleUVRowUp2_Linear_16_Any_SSE41 +ScaleUVRowUp2_Linear_16_Any_AVX2 +ScaleUVRowUp2_Bilinear_Any_SSSE3 +ScaleUVRowUp2_Bilinear_Any_AVX2 +ScaleUVRowUp2_Bilinear_16_Any_SSE41 +ScaleUVRowUp2_Bilinear_16_Any_AVX2 +ScaleRowDown2_Any_NEON +ScaleRowDown2Linear_Any_NEON +ScaleRowDown2Box_Any_NEON +ScaleRowDown2Box_Odd_NEON +ScaleUVRowDown2_Any_NEON +ScaleUVRowDown2Linear_Any_NEON +ScaleUVRowDown2Box_Any_NEON +ScaleRowDown4_Any_NEON +ScaleRowDown4Box_Any_NEON +ScaleRowDown34_Any_NEON +ScaleRowDown34_0_Box_Any_NEON +ScaleRowDown34_1_Box_Any_NEON +ScaleRowDown38_Any_NEON +ScaleRowDown38_3_Box_Any_NEON +ScaleRowDown38_2_Box_Any_NEON +ScaleARGBRowDown2_Any_NEON +ScaleARGBRowDown2Linear_Any_NEON +ScaleARGBRowDown2Box_Any_NEON +ScaleARGBRowDownEven_Any_NEON +ScaleARGBRowDownEvenBox_Any_NEON +ScaleRowDown2_Any_NEON +ScaleRowDown2Linear_Any_NEON +ScaleRowDown2Box_Any_NEON +ScaleRowDown2Box_Odd_NEON +ScaleUVRowDown2_Any_NEON +ScaleUVRowDown2Linear_Any_NEON +ScaleUVRowDown2Box_Any_NEON +ScaleRowDown4_Any_NEON +ScaleRowDown4Box_Any_NEON +ScaleRowDown34_Any_NEON +ScaleRowDown34_0_Box_Any_NEON +ScaleRowDown34_1_Box_Any_NEON +ScaleRowDown38_Any_NEON +ScaleRowDown38_3_Box_Any_NEON +ScaleRowDown38_2_Box_Any_NEON +ScaleARGBRowDown2_Any_NEON +ScaleARGBRowDown2Linear_Any_NEON +ScaleARGBRowDown2Box_Any_NEON +ScaleARGBRowDownEven_Any_NEON +ScaleARGBRowDownEvenBox_Any_NEON +ScaleUVRowDownEven_Any_NEON +ScaleAddRow_Any_NEON +ScaleFilterCols_Any_NEON +ScaleARGBCols_Any_NEON +ScaleARGBFilterCols_Any_NEON +ScaleRowUp2_Linear_Any_NEON +ScaleRowUp2_Linear_12_Any_NEON +ScaleRowUp2_Linear_16_Any_NEON +ScaleRowUp2_Bilinear_Any_NEON +ScaleRowUp2_Bilinear_12_Any_NEON +ScaleRowUp2_Bilinear_16_Any_NEON +ScaleUVRowUp2_Linear_Any_NEON +ScaleUVRowUp2_Linear_16_Any_NEON +ScaleUVRowUp2_Bilinear_Any_NEON +ScaleUVRowUp2_Bilinear_16_Any_NEON +I422ToARGBRow_Any_AVX512BWa +MergeUVRow_Any_AVX512BW +ARGBToRGB24Row_Any_AVX512VBMI +YUY2ToUVRow_Any_AVX2 +I422ToRGB565Row_SSSE3 +I422ToARGB1555Row_SSSE3 +I422ToARGB4444Row_SSSE3 +NV12ToRGB565Row_SSSE3 +NV12ToRGB24Row_SSSE3 +NV21ToRGB24Row_SSSE3 +NV12ToRGB24Row_AVX2 +NV21ToRGB24Row_AVX2 +I422ToARGB1555Row_AVX2 +I422ToARGB4444Row_AVX2 +I422ToRGB24Row_AVX2 +I444ToRGB24Row_AVX2 +NV12ToRGB565Row_AVX2 +RGB24ToYJRow_AVX2 +RAWToYJRow_AVX2 +RGB24ToYJRow_SSSE3 +RAWToYJRow_SSSE3 +InterpolateRow_16To8_AVX2 +I422ToARGBRow_Any_AVX512BW +I422ToRGB565Row_SSSE3 +I422ToARGB1555Row_SSSE3 +I422ToARGB4444Row_SSSE3 +NV12ToRGB565Row_SSSE3 +NV12ToRGB24Row_SSSE3 +NV21ToRGB24Row_SSSE3 +NV12ToRGB24Row_AVX2 +NV21ToRGB24Row_AVX2 +I422ToRGB565Row_AVX2 +I422ToARGB1555Row_AVX2 +I422ToARGB4444Row_AVX2 +I422ToRGB24Row_AVX2 +I444ToRGB24Row_AVX2 +NV12ToRGB565Row_AVX2 +RGB24ToYJRow_AVX2 +RAWToYJRow_AVX2 +RGB24ToYJRow_SSSE3 +RAWToYJRow_SSSE3 +InterpolateRow_16To8_AVX2 +ARGBToRGB24Row_AVX512VBMI +I422ToARGBRow_AVX512BW +MergeUVRow_AVX512BW +ARGBToABGRRow_C +ARGBToBGRARow_C +ARGBToRGBARow_C +RGBAToARGBRow_C +AR64ToAB64Row_C +YUY2ToARGBMatrix +UYVYToARGBMatrix