{"id":18041658,"url":"https://github.com/katyo/linux-video-rs","last_synced_at":"2025-04-09T19:22:05.007Z","repository":{"id":66335226,"uuid":"547496237","full_name":"katyo/linux-video-rs","owner":"katyo","description":"Thin and safe Linux V4L2 API for Rust","archived":false,"fork":false,"pushed_at":"2024-05-23T15:31:20.000Z","size":290,"stargazers_count":5,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T21:11:48.760Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/katyo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-07T19:34:28.000Z","updated_at":"2024-09-12T15:13:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"9941ae3d-da8f-401c-905a-e0fe05f18161","html_url":"https://github.com/katyo/linux-video-rs","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Flinux-video-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Flinux-video-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Flinux-video-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Flinux-video-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/katyo","download_url":"https://codeload.github.com/katyo/linux-video-rs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248095447,"owners_count":21046850,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-30T16:11:19.270Z","updated_at":"2025-04-09T19:22:04.986Z","avatar_url":"https://github.com/katyo.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Linux V4L2 API for Rust\n\n[![github](https://img.shields.io/badge/github-katyo/linux--video--rs-8da0cb.svg?style=for-the-badge\u0026logo=github)](https://github.com/katyo/linux-video-rs)\n[![crate](https://img.shields.io/crates/v/linux-video.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust)](https://crates.io/crates/linux-video)\n[![docs](https://img.shields.io/badge/docs.rs-linux--video-66c2a5?style=for-the-badge\u0026logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K)](https://docs.rs/linux-video)\n[![MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)\n[![CI](https://img.shields.io/github/actions/workflow/status/katyo/linux-video-rs/ci.yml?branch=master\u0026style=for-the-badge\u0026logo=github-actions\u0026logoColor=white)](https://github.com/katyo/linux-video-rs/actions?query=workflow%3ARust)\n\nThis crates intended to provide access to Linux V4L2 APIs without any limitations.\n\nThe primary design goal is an optimal balance between safety and overhead.\nThe implementation much closer to system calls than v4l.\nInterface types wraps kernel types to avoid unnecessary copying.\n\nThe secondary goal is providing full set of features of the original API.\n\nAt end this is my demure attempt to do things right.\n\n## Crates\n\n- [linux-video-core](https://crates.io/crates/linux-video-core) - core abstractions and low level interface (not for end users)\n- **[linux-video](https://crates.io/crates/linux-video)** - sync interface which supports synchronous operation only\n- [tokio-linux-video](https://crates.io/crates/tokio-linux-video) - async interface for [tokio](https://tokio.rs/) users\n- [async-std-linux-video](https://crates.io/crates/async-std-linux-video) - async interface for [async-std](https://async.rs/) users\n\n## Usage examples\n\nEnumerating devices:\n\n```rust,no_run\nuse linux_video::Device;\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let mut devs = Device::list()?;\n\n    while let Some(path) = devs.fetch_next()? {\n        let dev = Device::open(\u0026path)?;\n\n        let caps = dev.capabilities()?;\n\n        println!(\"path: {}, {caps}\", path.display());\n    }\n\n    Ok(())\n}\n```\n\nGetting capabilities and controls:\n\n```rust,no_run\nuse linux_video::Device;\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let dev = Device::open(\"/dev/video0\")?;\n\n    let caps = dev.capabilities()?;\n\n    println!(\"Capabilities: {caps}\");\n\n    println!(\"Controls:\");\n    let mut controls = dev.controls(None);\n\n    while let Some(ctrl) = controls.fetch_next()? {\n        println!(\"  {ctrl}\");\n\n        if let Some(mut items) = dev.control_items(\u0026ctrl) {\n            while let Some(item) = items.fetch_next()? {\n                println!(\"    {item}\");\n            }\n        }\n    }\n\n    Ok(())\n}\n```\n\nGetting supported formats:\n\n```rust,no_run\nuse linux_video::{types::BufferType, Device};\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let dev = Device::open(\"/dev/video0\")?;\n\n    let caps = dev.capabilities()?;\n\n    for type_ in BufferType::ALL {\n        if type_.is_supported(caps.capabilities()) {\n            println!(\"{type_} formats:\");\n            let mut fmts = dev.formats(type_);\n\n            if let Some(fmt) = fmts.fetch_next()? {\n                println!(\"  {fmt}\");\n\n                if type_.content().is_video() {\n                    let mut sizes = dev.sizes(fmt.pixel_format());\n\n                    while let Some(size) = sizes.fetch_next()? {\n                        println!(\"    {size}\");\n\n                        for size in size.sizes() {\n                            println!(\"      {size}\");\n                            let mut intervals = dev.intervals(fmt.pixel_format(), size.width(), size.height());\n\n                            while let Some(interval) = intervals.fetch_next()? {\n                                println!(\"        {interval}\");\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    Ok(())\n}\n```\n\nUsing controls:\n\n```rust,no_run\nuse linux_video::{types::*, Device};\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let dev = Device::open(\"/dev/video0\")?;\n\n    // Get control from device by identifier\n    let contrast_ctrl = dev.control(CtrlId::Contrast)?;\n\n    // Create a value for control\n    let mut contrast = Value::from(\u0026contrast_ctrl);\n\n    // Get control value from device\n    dev.get_control(\u0026mut contrast)?;\n\n    // Get reference to value data\n    let contrast_value = contrast.try_ref::\u003ci32\u003e().unwrap();\n\n    println!(\"Current contrast: {contrast_value:?}\");\n\n    // Set new value by reference\n    *contrast.try_mut::\u003ci32\u003e().unwrap() = contrast_value + 10;\n\n    println!(\"Updated contrast: {:?}\", contrast.try_ref::\u003ci32\u003e().unwrap());\n\n    // Set new control value to device\n    dev.set_control(\u0026contrast)?;\n\n    Ok(())\n}\n```\n\nCapture video data:\n\n```rust,no_run\nuse linux_video::{types::*, Device};\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let dev = Device::open(\"/dev/video0\")?;\n\n    // Get current format\n    let mut fmt = dev.format(BufferType::VideoOutput)?;\n    println!(\"  {fmt}\");\n\n    // Start video capture stream\n    let stream = dev.stream::\u003cIn, Mmap\u003e(ContentType::Video, 4)?;\n\n    let mut i = 0;\n    while let Ok(buffer) = stream.next() {\n        let buffer = buffer.lock();\n        println!(\"#{i} {buffer}\");\n\n        // Get reference to frame buffer contents\n        let _data: \u0026[u8] = buffer.as_ref();\n\n        i += 1;\n        if i \u003e 30 {\n            break;\n        }\n    }\n\n    Ok(())\n}\n```\n\nOutput video data:\n\n```rust,no_run\nuse linux_video::{types::*, Device};\n\nfn main() -\u003e std::io::Result\u003c()\u003e {\n    let dev = Device::open(\"/dev/video0\")?;\n\n    // Get current format\n    let mut fmt = dev.format(BufferType::VideoOutput)?;\n    println!(\"  {fmt}\");\n\n    // Start video output stream\n    let stream = dev.stream::\u003cOut, Mmap\u003e(ContentType::Video, 4)?;\n\n    let mut i = 0;\n    while let Ok(mut buffer) = stream.next() {\n        let mut buffer = buffer.lock();\n        println!(\"#{i} {buffer}\");\n\n        // Get reference to frame buffer contents\n        let _data: \u0026mut [u8] = buffer.as_mut();\n\n        i += 1;\n        if i \u003e 30 {\n            break;\n        }\n    }\n\n    Ok(())\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Flinux-video-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkatyo%2Flinux-video-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Flinux-video-rs/lists"}