Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: Rust CI

on:
push:
branches: [ main, develop ]
paths:
- 'bindings/rust/**'
- 'src/**'
- 'include/**'
- 'CMakeLists.txt'
- '.github/workflows/rust.yml'
pull_request:
branches: [ main, develop ]
paths:
- 'bindings/rust/**'
- 'src/**'
- 'include/**'
- 'CMakeLists.txt'
- '.github/workflows/rust.yml'

env:
CARGO_TERM_COLOR: always
CCAP_SKIP_CAMERA_TESTS: 1

permissions:
contents: read

jobs:
# Job 1: Static Linking (Development Mode)
# Verifies that the crate links correctly against a pre-built C++ library.
static-link:
name: Static Link (Dev)
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install system dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential pkg-config libclang-dev

- name: Install system dependencies (Windows)
if: matrix.os == 'windows-latest'
run: |
choco install cmake llvm -y

- name: Configure LIBCLANG_PATH (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: echo "LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_ENV

- name: Install system dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install cmake llvm
echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> $GITHUB_ENV

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
components: clippy, rustfmt
cache: false

# Build C++ Library (Linux/macOS)
# We build in build/Debug to match build.rs expectations for Unix Makefiles
- name: Build C library (Unix)
if: runner.os != 'Windows'
run: |
mkdir -p build/Debug
cd build/Debug
cmake -DCMAKE_BUILD_TYPE=Debug -DCCAP_BUILD_EXAMPLES=OFF -DCCAP_BUILD_TESTS=OFF ../..
cmake --build . --config Debug --parallel

# Build C++ Library (Windows)
# Build both Debug and Release versions
# MSVC is a multi-config generator, so we build to build/ and specify config at build time
- name: Build C library (Windows)
if: runner.os == 'Windows'
run: |
mkdir build
cd build
cmake -DCCAP_BUILD_EXAMPLES=OFF -DCCAP_BUILD_TESTS=OFF ..
cmake --build . --config Debug --parallel
cmake --build . --config Release --parallel

- name: Check formatting
if: matrix.os == 'ubuntu-latest'
working-directory: bindings/rust
run: cargo fmt -- --check

- name: Run clippy
if: matrix.os == 'ubuntu-latest'
working-directory: bindings/rust
run: cargo clippy --all-targets --no-default-features --features static-link -- -D warnings

- name: Build Rust bindings
working-directory: bindings/rust
run: cargo build --verbose --no-default-features --features static-link

- name: Run tests
working-directory: bindings/rust
run: cargo test --verbose --no-default-features --features static-link

# Job 2: Source Build (Distribution Mode)
# Verifies that the crate builds correctly from source using the cc crate.
# This is crucial for crates.io distribution.
build-source:
name: Build Source (Dist)
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install system dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config

- name: Install system dependencies (macOS)
if: matrix.os == 'macos-latest'
run: brew install llvm

- name: Install system dependencies (Windows)
if: matrix.os == 'windows-latest'
run: |
choco install llvm -y
refreshenv

- name: Configure LIBCLANG_PATH (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: echo "LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin" >> $env:GITHUB_ENV

- name: Configure LIBCLANG_PATH (macOS)
if: matrix.os == 'macos-latest'
run: echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> $GITHUB_ENV

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
cache: false
# The build.rs script should handle it via the 'build-source' feature.

- name: Build Rust bindings (Source)
working-directory: bindings/rust
# Disable default features (static-link) and enable build-source
run: cargo build --verbose --no-default-features --features build-source

- name: Run tests (Source)
working-directory: bindings/rust
run: cargo test --verbose --no-default-features --features build-source
100 changes: 100 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,106 @@
"problemMatcher": "$msCompile"
}
},
{
"label": "Run Rust print_camera",
"type": "shell",
"command": "cargo",
"args": [
"run",
"--example",
"print_camera"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Run Rust minimal_example",
"type": "shell",
"command": "cargo",
"args": [
"run",
"--example",
"minimal_example"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Run Rust capture_grab",
"type": "shell",
"command": "cargo",
"args": [
"run",
"--example",
"capture_grab"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Run Rust capture_callback",
"type": "shell",
"command": "cargo",
"args": [
"run",
"--example",
"capture_callback"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Build Rust Bindings",
"type": "shell",
"command": "cargo",
"args": [
"build"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Build Rust Examples",
"type": "shell",
"command": "cargo",
"args": [
"build",
"--examples"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Test Rust Bindings",
"type": "shell",
"command": "cargo",
"args": [
"test"
],
"options": {
"cwd": "${workspaceFolder}/bindings/rust"
},
"group": "build",
"problemMatcher": "$rustc"
},
{
"label": "Run ccap CLI --video test.mp4 (Debug)",
"type": "shell",
Expand Down
35 changes: 34 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,37 @@ if (CCAP_INSTALL)
message(STATUS " Libraries: ${CMAKE_INSTALL_PREFIX}/${CCAP_INSTALL_LIBDIR}")
message(STATUS " Headers: ${CMAKE_INSTALL_PREFIX}/${CCAP_INSTALL_INCLUDEDIR}")
message(STATUS " CMake: ${CMAKE_INSTALL_PREFIX}/${CCAP_INSTALL_CMAKEDIR}")
endif ()
endif ()

# ############### Rust Bindings ################
option(CCAP_BUILD_RUST "Build Rust bindings" OFF)

if (CCAP_BUILD_RUST)
message(STATUS "ccap: Building Rust bindings")
# Find Rust/Cargo
find_program(CARGO_CMD cargo)
if (NOT CARGO_CMD)
message(WARNING "cargo not found - Rust bindings disabled")
else ()
message(STATUS "ccap: Found cargo: ${CARGO_CMD}")
# Add custom target to build Rust bindings
add_custom_target(ccap-rust
COMMAND ${CARGO_CMD} build --release --no-default-features --features static-link
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bindings/rust
COMMENT "Building Rust bindings"
DEPENDS ccap
)
# Add custom target to test Rust bindings
add_custom_target(ccap-rust-test
COMMAND ${CARGO_CMD} test --no-default-features --features static-link
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bindings/rust
COMMENT "Testing Rust bindings"
DEPENDS ccap-rust
)
# Rust bindings are optional, do not add to main build automatically
# Users can explicitly build with: cmake --build . --target ccap-rust
message(STATUS "ccap: Rust bindings targets added:")
message(STATUS " ccap-rust: Build Rust bindings")
message(STATUS " ccap-rust-test: Test Rust bindings")
endif ()
endif ()
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
[![Windows Build](https://github.com/wysaid/CameraCapture/actions/workflows/windows-build.yml/badge.svg)](https://github.com/wysaid/CameraCapture/actions/workflows/windows-build.yml)
[![macOS Build](https://github.com/wysaid/CameraCapture/actions/workflows/macos-build.yml/badge.svg)](https://github.com/wysaid/CameraCapture/actions/workflows/macos-build.yml)
[![Linux Build](https://github.com/wysaid/CameraCapture/actions/workflows/linux-build.yml/badge.svg)](https://github.com/wysaid/CameraCapture/actions/workflows/linux-build.yml)
[![Rust CI](https://github.com/wysaid/CameraCapture/actions/workflows/rust.yml/badge.svg)](https://github.com/wysaid/CameraCapture/actions/workflows/rust.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![C++17](https://img.shields.io/badge/C++-17-blue.svg)](https://isocpp.org/)
[![C99](https://img.shields.io/badge/C-99-blue.svg)](https://en.wikipedia.org/wiki/C99)
[![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20macOS%20%7C%20iOS%20%7C%20Linux-brightgreen)](https://github.com/wysaid/CameraCapture)

[English](./README.md) | [中文](./README.zh-CN.md)

A high-performance, lightweight cross-platform camera capture library with hardware-accelerated pixel format conversion, supporting both camera capture and video file playback (Windows/macOS), providing complete C++ and pure C language interfaces.
A high-performance, lightweight cross-platform camera capture library with hardware-accelerated pixel format conversion, supporting both camera capture and video file playback (Windows/macOS). Provides complete C++ and pure C interfaces, plus Rust bindings.

> 🌐 **Official Website:** [ccap.work](https://ccap.work)

Expand Down Expand Up @@ -207,6 +208,27 @@ int main() {
}
```

### Rust Bindings

Rust bindings are available as a crate on crates.io:

- Crate: [ccap-rs on crates.io](https://crates.io/crates/ccap-rs)
- Docs: [docs.rs/ccap-rs](https://docs.rs/ccap-rs)
- Source: `bindings/rust/`

Quick install:

```bash
cargo add ccap-rs
```

Or, if you want the crate name in code to be `ccap`:

```toml
[dependencies]
ccap = { package = "ccap-rs", version = "<latest>" }
```

## CLI Tool

ccap includes a powerful command-line tool for quick camera operations and video processing without writing code:
Expand Down Expand Up @@ -234,6 +256,7 @@ cmake --build .
```

**Key Features:**

- 📷 List and select camera devices
- 🎯 Capture single or multiple images
- 👁️ Real-time preview window (with GLFW)
Expand All @@ -243,12 +266,13 @@ cmake --build .
- ⏱️ Duration-based or count-based capture modes
- 🔁 Video looping and playback speed control


For complete CLI documentation, see [CLI Tool Guide](./docs/content/cli.md).

## System Requirements

| Platform | Compiler | System Requirements |
|----------|----------|---------------------|
| -------- | -------- | ------------------- |
| **Windows** | MSVC 2019+ (including 2026) / MinGW-w64 | DirectShow |
| **macOS** | Xcode 11+ | macOS 10.13+ |
| **iOS** | Xcode 11+ | iOS 13.0+ |
Expand All @@ -268,7 +292,7 @@ For complete CLI documentation, see [CLI Tool Guide](./docs/content/cli.md).
## Examples

| Example | Description | Language | Platform |
|---------|-------------|----------|----------|
| ------- | ----------- | -------- | -------- |
| [0-print_camera](./examples/desktop/0-print_camera.cpp) / [0-print_camera_c](./examples/desktop/0-print_camera_c.c) | List available cameras | C++ / C | Desktop |
| [1-minimal_example](./examples/desktop/1-minimal_example.cpp) / [1-minimal_example_c](./examples/desktop/1-minimal_example_c.c) | Basic frame capture | C++ / C | Desktop |
| [2-capture_grab](./examples/desktop/2-capture_grab.cpp) / [2-capture_grab_c](./examples/desktop/2-capture_grab_c.c) | Continuous capture | C++ / C | Desktop |
Expand Down
Loading
Loading