Skip to content
Open
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
18 changes: 10 additions & 8 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@
## Code Guidelines
- Add tests for new features/bug fixes and run all tests before committing
- Use English for commit messages and PR descriptions
- Run `./scripts/update_version.sh <version>` to update version files
- Remove `dev.cmake` before standard builds/tests (use for custom CMake options)
- Run `scripts/format-all.sh` before committing
- Use `./scripts/update_version.sh <version>` to update version files
- Remove `dev.cmake` before standard builds/tests; use it only for custom CMake options
- Run `./scripts/format-all.sh` before committing

## Communication Guidelines
- Respond in user's language (except `docs/` which must be English)
- Maintain language consistency within conversations
- Respond in the user's language, except for `docs/`, which must be English
- Keep the same language throughout the conversation

## File Management
- Store temporary files, development documents, and drafts in `dev-docs/`
- `.md` files in `docs/` must be English and require review before publishing
- Treat `dev-docs/` as `/tmp`
- Treat `dev-docs/` as disposable temporary storage
- Markdown files in `docs/` must be English and reviewed before publishing

## Tool Constraints
- **`gh` CLI:** Always prepend `$env:GH_PAGER=""` in PowerShell (e.g. `$env:GH_PAGER=""; gh pr list`), or `GH_PAGER=` in bash/zsh — never omit this or the command will hang; never modify global git/gh config
- **`gh` CLI:** Always prepend `$env:GH_PAGER=""` in PowerShell (for example, `$env:GH_PAGER=""; gh pr list`) or `GH_PAGER=` in bash/zsh; never omit it, and never modify global git or gh config.
- **Build/Test Work:** Use `.vscode/tasks.json` only as the reference for command sequence, `cwd`, config toggles, and prerequisites. Run the underlying commands directly in the terminal or with the appropriate dedicated tool; do **not** invoke VS Code tasks unless the user explicitly asks for a named task.


## Skills

Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"-ExecutionPolicy",
"Bypass",
"-Command",
"git clean -fdx build; if ($LASTEXITCODE -ne 0 -and (Test-Path 'build')) { Remove-Item -Recurse -Force 'build' }; git clean -fdx build_shared; if ($LASTEXITCODE -ne 0 -and (Test-Path 'build_shared')) { Remove-Item -Recurse -Force 'build_shared' }; git clean -fdx examples; if ($LASTEXITCODE -ne 0 -and (Test-Path 'examples')) { Remove-Item -Recurse -Force 'examples' }"
"git clean -fdx build; if ($LASTEXITCODE -ne 0 -and (Test-Path 'build')) { Remove-Item -Recurse -Force 'build' }; git clean -fdx build_shared; if ($LASTEXITCODE -ne 0 -and (Test-Path 'build_shared')) { Remove-Item -Recurse -Force 'build_shared' }"
],
"options": {
"cwd": "${workspaceFolder}"
Expand Down
39 changes: 23 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "[Aa][Rr][Mm]64|[Aa][Aa][Rr][Cc]h64" OR
endif ()
endif ()


file(GLOB LIB_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h)

# Exclude file reader sources if file playback is disabled
Expand Down Expand Up @@ -235,31 +234,39 @@ elseif (UNIX AND NOT APPLE AND NOT WIN32)
# Propagate to pkg-config for consumers
set(PKG_CONFIG_LIBS_PRIVATE "Libs.private: -lpthread")
elseif (WIN32)
# Windows – link Media Foundation libraries for video file playback (if enabled)
# Windows – Media Foundation is used by the MSMF camera backend and optional file playback.
target_link_libraries(ccap PUBLIC
mf
mfplat
mfreadwrite
mfuuid)

if (CCAP_ENABLE_FILE_PLAYBACK)
target_link_libraries(ccap PUBLIC
mfplat
mfreadwrite
mfuuid
shlwapi
propsys)
set(PKG_CONFIG_LIBS_PRIVATE "Libs.private: -lmf -lmfplat -lmfreadwrite -lmfuuid -lshlwapi -lpropsys")
else ()
set(PKG_CONFIG_LIBS_PRIVATE "Libs.private: -lmf -lmfplat -lmfreadwrite -lmfuuid")
message(STATUS "ccap: Windows build without file playback extras (shlwapi/propsys not linked)")
endif ()

# MSVC: Delay load Media Foundation DLLs to support Windows XP camera functionality
# The program can start on XP and use DirectShow cameras, but will crash if video playback is attempted
if (MSVC)
# MSVC: Delay load Media Foundation DLLs to preserve legacy DirectShow-only startup paths.
if (MSVC)
if (CCAP_BUILD_SHARED)
target_link_options(ccap PRIVATE
/DELAYLOAD:mf.dll
/DELAYLOAD:mfplat.dll
/DELAYLOAD:mfreadwrite.dll
)
else ()
target_link_options(ccap INTERFACE
/DELAYLOAD:mf.dll
/DELAYLOAD:mfplat.dll
/DELAYLOAD:mfreadwrite.dll
)
target_link_libraries(ccap PUBLIC delayimp.lib)
endif ()

# Set pkg-config private libs for Windows with Media Foundation
set(PKG_CONFIG_LIBS_PRIVATE "Libs.private: -lmfplat -lmfreadwrite -lmfuuid -lshlwapi -lpropsys")
else ()
# No Media Foundation libraries when file playback is disabled
set(PKG_CONFIG_LIBS_PRIVATE "")
message(STATUS "ccap: Windows build without Media Foundation libraries (file playback disabled)")
target_link_libraries(ccap PUBLIC delayimp.lib)
endif ()
else ()
# Other platforms
Expand Down
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ A high-performance, lightweight cross-platform camera capture library with hardw

- **High Performance**: Hardware-accelerated pixel format conversion with up to 10x speedup (AVX2, Apple Accelerate, NEON)
- **Lightweight**: No third-party dependencies - uses only system frameworks
- **Cross Platform**: Windows (DirectShow), macOS/iOS (AVFoundation), Linux (V4L2)
- **Cross Platform**: Windows (DirectShow by default with optional Media Foundation), macOS/iOS (AVFoundation), Linux (V4L2)
- **Windows Dual Backends**: DirectShow is the default on Windows for compatibility with OBS Virtual Camera and other virtual devices, while Media Foundation stays available through explicit opt-in
- **Multiple Formats**: RGB, BGR, YUV (NV12/I420) with automatic conversion
- **Dual Language APIs**: ✨ **Complete Pure C Interface** - Both modern C++ API and traditional C99 interface for various project integration and language bindings
- **Video File Playback**: 🎬 Play video files (MP4, AVI, MOV, etc.) using the same API as camera capture - supports Windows and macOS
- **CLI Tool**: Ready-to-use command-line tool for quick camera operations and video processing - list devices, capture images, real-time preview, video playback ([Documentation](./docs/content/cli.md))
- **Production Ready**: Comprehensive test suite with 95%+ accuracy validation
- **Virtual Camera Support**: Compatible with OBS Virtual Camera and similar tools
- **Virtual Camera Support**: Compatible with OBS Virtual Camera and similar tools through the default DirectShow path on Windows

## Quick Start

Expand Down Expand Up @@ -211,6 +212,29 @@ int main() {
}
```

### Windows Backend Selection

On Windows, camera capture now uses DirectShow by default. This keeps OBS Virtual Camera and other virtual cameras working reliably after upgrades, while Media Foundation remains available when you explicitly request it. In `auto` mode, camera enumeration merges results from both Windows backends and `Provider::open()` routes the selected device to a compatible backend automatically: DirectShow-only devices stay on DirectShow, Media Foundation-only devices go straight to Media Foundation, and devices visible in both backends prefer DirectShow with Media Foundation as the secondary fallback.

For most Windows applications, staying in `auto` mode is recommended. ccap normalizes the public capture API, frame orientation handling, and output pixel-format conversion across both backends so callers usually do not need backend-specific code.

- Pass `extraInfo` as `"auto"`, `"msmf"`, `"dshow"`, or `"backend=<value>"` in the C++/C constructors that accept it.
- Set the environment variable `CCAP_WINDOWS_BACKEND=auto|msmf|dshow` to affect the whole process, including the CLI and Rust bindings.

```powershell
# PowerShell: opt into Media Foundation for the current process
$env:CCAP_WINDOWS_BACKEND = "msmf"
.\ccap --list-devices
```

```cpp
// Force Media Foundation explicitly on Windows
ccap::Provider msmfProvider("", "msmf");

// Force DirectShow explicitly on Windows
ccap::Provider dshowProvider("", "dshow");
```

### Rust Bindings

Rust bindings are available as a crate on crates.io:
Expand Down Expand Up @@ -276,7 +300,7 @@ For complete CLI documentation, see [CLI Tool Guide](./docs/content/cli.md).

| Platform | Compiler | System Requirements |
| -------- | -------- | ------------------- |
| **Windows** | MSVC 2019+ (including 2026) / MinGW-w64 | DirectShow |
| **Windows** | MSVC 2019+ (including 2026) / MinGW-w64 | DirectShow (default) + Media Foundation opt-in |
| **macOS** | Xcode 11+ | macOS 10.13+ |
| **iOS** | Xcode 11+ | iOS 13.0+ |
| **Linux** | GCC 7+ / Clang 6+ | V4L2 (Linux 2.6+) |
Expand Down
36 changes: 33 additions & 3 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@

- **高性能**:硬件加速的像素格式转换,提升高达 10 倍性能(AVX2、Apple Accelerate、NEON)
- **轻量级**:无第三方库依赖,仅使用系统框架
- **跨平台**:Windows(DirectShow)、macOS/iOS(AVFoundation)、Linux(V4L2)
- **跨平台**:Windows(默认 DirectShow,可选 Media Foundation)、macOS/iOS(AVFoundation)、Linux(V4L2)
- **Windows 双后端**:Windows 默认使用 DirectShow,以更好兼容 OBS Virtual Camera 等虚拟摄像头;如果需要,也可以显式切换到 Media Foundation
- **多种格式**:RGB、BGR、YUV(NV12/I420)及自动转换
- **双语言接口**:✨ **新增完整纯 C 接口**,同时提供现代化 C++ API 和传统 C99 接口,支持各种项目集成和语言绑定
- **视频文件播放**:🎬 使用与相机相同的 API 播放视频文件(MP4、AVI、MOV 等)- 支持 Windows 和 macOS
- **命令行工具**:开箱即用的命令行工具,快速实现相机操作和视频处理 - 列出设备、捕获图像、实时预览、视频播放([文档](./docs/content/cli.zh.md))
- **生产就绪**:完整测试套件,95%+ 精度验证
- **虚拟相机支持**:兼容 OBS Virtual Camera 等工具
- **虚拟相机支持**:在 Windows 上通过默认 DirectShow 路径兼容 OBS Virtual Camera 等工具

## 快速开始

Expand Down Expand Up @@ -174,6 +175,35 @@ int main() {
}
```

### Windows 后端选择

Windows 上现在默认使用 DirectShow。这样做的主要原因是 DirectShow 对 OBS Virtual Camera 等虚拟摄像头的兼容性更好,能够避免用户升级后因为默认后端变化而突然失去虚拟摄像头支持。在 `auto` 模式下,设备枚举会合并 DirectShow 和 Media Foundation 的结果,而 `Provider::open()` 会根据选中的设备自动路由到兼容的后端:仅 DirectShow 可见的设备会直接走 DirectShow,仅 MSMF 可见的设备会直接走 MSMF,同时被两个后端看到的设备优先走 DirectShow,必要时再回退到 MSMF。

对大多数 Windows 应用来说,建议直接使用 `auto` 模式。ccap 会在两个后端之上统一公开的采集 API、帧朝向处理和输出像素格式转换,所以调用方通常不需要编写后端分支逻辑。

- 在支持 `extraInfo` 的 C++ / C 构造接口中传入 `"auto"`、`"msmf"`、`"dshow"` 或 `"backend=<value>"`。
- 设置环境变量 `CCAP_WINDOWS_BACKEND=auto|msmf|dshow`,对整个进程生效,包括 CLI 和 Rust 绑定。

```powershell
# PowerShell:为当前进程显式启用 Media Foundation
$env:CCAP_WINDOWS_BACKEND = "msmf"
.\ccap --list-devices
```

```cpp
// 下面两段是互斥示例;同一时刻不要对同一设备同时创建两个 Provider。

// Force MSMF
{
ccap::Provider provider("", "msmf");
}

// Force DirectShow
{
ccap::Provider provider("", "dshow");
}
```

### Rust 绑定

本项目提供 Rust bindings(已发布到 crates.io):
Expand Down Expand Up @@ -237,7 +267,7 @@ cmake --build .

| 平台 | 编译器 | 系统要求 |
|------|--------|----------|
| **Windows** | MSVC 2019+(包括 2026)/ MinGW-w64 | DirectShow |
| **Windows** | MSVC 2019+(包括 2026)/ MinGW-w64 | DirectShow(默认)+ Media Foundation 可选启用 |
| **macOS** | Xcode 11+ | macOS 10.13+ |
| **iOS** | Xcode 11+ | iOS 13.0+ |
| **Linux** | GCC 7+ / Clang 6+ | V4L2 (Linux 2.6+) - 相机捕获支持,视频播放暂不支持 |
Expand Down
20 changes: 11 additions & 9 deletions bindings/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
[![Documentation](https://docs.rs/ccap-rs/badge.svg)](https://docs.rs/ccap-rs)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Safe Rust bindings for [CameraCapture (ccap)](https://github.com/wysaid/CameraCapture) — a high-performance, lightweight, cross-platform **webcam/camera capture** library with **hardware-accelerated pixel format conversion** (Windows DirectShow, macOS/iOS AVFoundation, Linux V4L2).
Safe Rust bindings for [CameraCapture (ccap)](https://github.com/wysaid/CameraCapture) — a high-performance, lightweight, cross-platform **webcam/camera capture** library with **hardware-accelerated pixel format conversion** (Windows DirectShow by default with optional Media Foundation, macOS/iOS AVFoundation, Linux V4L2).

> Note: The published *package* name on crates.io is `ccap-rs`, but the *crate name in code* is `ccap`.

## Features

- **High Performance**: Hardware-accelerated pixel format conversion with up to 10x speedup (AVX2, Apple Accelerate, NEON)
- **Cross Platform**: Windows (DirectShow), macOS/iOS (AVFoundation), Linux (V4L2)
- **Cross Platform**: Windows (DirectShow by default with optional Media Foundation), macOS/iOS (AVFoundation), Linux (V4L2)
- **Multiple Formats**: RGB, BGR, YUV (NV12/I420) with automatic conversion
- **Zero Dependencies**: Uses only system frameworks
- **Memory Safe**: Safe Rust API with automatic resource management
Expand Down Expand Up @@ -149,9 +149,11 @@ An ASan-instrumented `libccap.a` requires the ASan runtime at link/run time.

## Platform notes

- Camera capture: Windows (DirectShow), macOS/iOS (AVFoundation), Linux (V4L2)
- Camera capture: Windows (DirectShow by default with optional Media Foundation), macOS/iOS (AVFoundation), Linux (V4L2)
- Video file playback support depends on the underlying C/C++ library backend (currently Windows/macOS only).

On Windows, camera capture defaults to DirectShow because virtual cameras such as OBS Virtual Camera are exposed there more reliably. To opt into Media Foundation, set `CCAP_WINDOWS_BACKEND=msmf`, or use `Provider::with_device_name_and_extra_info`, `Provider::with_device_and_extra_info`, `Provider::open_device_with_extra_info`, and `Provider::open_with_index_and_extra_info` with `"msmf"`.

## API Documentation

### Core Types
Expand Down Expand Up @@ -186,12 +188,12 @@ match provider.grab_frame(3000) { // 3 second timeout

## Platform Support

| Platform | Backend | Status |
| -------- | ------------ | ------------ |
| Windows | DirectShow | ✅ Supported |
| macOS | AVFoundation | ✅ Supported |
| iOS | AVFoundation | ✅ Supported |
| Linux | V4L2 | ✅ Supported |
| Platform | Backend | Status |
| --- | --- | --- |
| Windows | DirectShow default, Media Foundation opt-in | ✅ Supported |
| macOS | AVFoundation | ✅ Supported |
| iOS | AVFoundation | ✅ Supported |
| Linux | V4L2 | ✅ Supported |

## System Requirements

Expand Down
8 changes: 7 additions & 1 deletion bindings/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ Please vendor the sources into bindings/rust/native/, or set CCAP_SOURCE_DIR to
{
build
.file(ccap_root.join("src/ccap_imp_windows.cpp"))
.file(ccap_root.join("src/ccap_imp_windows_msmf.cpp"))
.file(ccap_root.join("src/ccap_file_reader_windows.cpp"));
}

Expand Down Expand Up @@ -368,10 +369,11 @@ Please vendor the sources into bindings/rust/native/, or set CCAP_SOURCE_DIR to

#[cfg(target_os = "windows")]
{
println!("cargo:rustc-link-lib=mf");
println!("cargo:rustc-link-lib=strmiids");
println!("cargo:rustc-link-lib=ole32");
println!("cargo:rustc-link-lib=oleaut32");
// Media Foundation libraries for video file playback
// Media Foundation libraries for the MSMF camera backend and video file playback
println!("cargo:rustc-link-lib=mfplat");
println!("cargo:rustc-link-lib=mfreadwrite");
println!("cargo:rustc-link-lib=mfuuid");
Expand Down Expand Up @@ -457,6 +459,10 @@ Please vendor the sources into bindings/rust/native/, or set CCAP_SOURCE_DIR to
"cargo:rerun-if-changed={}/src/ccap_imp_windows.cpp",
ccap_root.display()
);
println!(
"cargo:rerun-if-changed={}/src/ccap_imp_windows_msmf.cpp",
ccap_root.display()
);
println!(
"cargo:rerun-if-changed={}/src/ccap_file_reader_windows.cpp",
ccap_root.display()
Expand Down
Loading
Loading